Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] 보조금 인터랙션 추가 ( resolve #23 ) #45

Merged
merged 16 commits into from
Jul 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 30 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"dependencies": {
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-lottie-player": "^2.1.0",
"zustand": "^4.5.4"
},
"devDependencies": {
Expand Down
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
16 changes: 16 additions & 0 deletions src/interactions/InteractionDescription.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
function InteractionDescription({ order, title, description, directive }) {
return (
<div className="w-full max-w-[1200px] px-10 lg:px-20 flex gap-2 items-start mt-16 lg:mt-[6.25rem] ">
<img src={`/icons/property${order}.svg`} alt={order} />
<div className="flex flex-col gap-3.5 font-bold">
<h3 className="text-neutral-400 text-title-m md:text-title-l">
{title}
</h3>
<p className="text-white text-body-m md:text-body-l">{description}</p>
<p className="text-neutral-200 text-body-s">{directive}</p>
</div>
</div>
);
}

export default InteractionDescription;
72 changes: 72 additions & 0 deletions src/interactions/distanceDriven/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { useImperativeHandle } from "react";
import InteractionDescription from "../InteractionDescription.jsx";
import usePointDrag from "./usePointDrag.js";

function DistanceDrivenInteraction({ interactCallback, $ref }) {
const { x, y, reset, onPointerDown } = usePointDrag();

const circleStyle = {
transform: `translate(${x}px, ${y}px)`,
};

function pulseAnimation(e) {
e.currentTarget.animate(
[
{ transform: "scale(1)", opacity: 0.5 },
{ transform: "scale(16)", opacity: 0 },
],
{
duration: 300,
iteractions: 1,
easing: "ease-out",
pseudoElement: "::before",
},
);
}

useImperativeHandle($ref, () => ({ reset }), [reset]);

return (
<article className="relative w-full h-full overflow-hidden flex items-center flex-col">
<InteractionDescription
order="1"
title="걱정 없이, 더 멀리"
description="The new IONIQ 5는 한 번의 충전으로 얼마나 멀리 주행할 수 있을까요?"
directive="가운데 점을 드래그하여 최대 주행거리를 예측해보세요!"
/>
<div className="absolute top-1/2">
<div
className="rounded-full size-8 bg-blue-500 cursor-pointer before:size-8 before:rounded-full before:absolute before:left-0 before:top-0 before:z-10 before:bg-blue-500 before:opacity-50"
onPointerDown={(e) => {
onPointerDown(e);
pulseAnimation(e);
interactCallback?.();
}}
style={circleStyle}
/>
<svg
className="overflow-visible stroke-blue-500 absolute top-4 left-4 pointer-events-none"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
>
<line
x1="0"
y1="0"
x2={x}
y2={y}
strokeWidth="4"
strokeLinecap="round"
></line>
</svg>
</div>
<p className="text-white absolute bottom-32 md:bottom-36 lg:bottom-[180px] text-title-s pointer-events-none">
<span className="text-head-m md:text-head-l lg:text-[4.375rem] mr-1.5 lg:mr-2.5">
{Math.round(Math.hypot(x, y) / 3)}
</span>
km
</p>
</article>
);
}

export default DistanceDrivenInteraction;
40 changes: 40 additions & 0 deletions src/interactions/distanceDriven/usePointDrag.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { useState, useRef, useCallback } from "react";
import useMountDragEvent from "@/common/useMountDragEvent.js";

function usePointDrag() {
const isDragging = useRef(false);
const prevState = useRef({ x: 0, y: 0, mouseX: 0, mouseY: 0 });
const [x, setX] = useState(0);
const [y, setY] = useState(0);

function onDragStart(e) {
isDragging.current = true;
prevState.current.mouseX = e.clientX;
prevState.current.mouseY = e.clientY;
prevState.current.x = x;
prevState.current.y = y;
}
const onDrag = useCallback(function (mouse) {
if (!isDragging.current) return;
setX(prevState.current.x + mouse.x - prevState.current.mouseX);
setY(prevState.current.y + mouse.y - prevState.current.mouseY);
}, []);
const onDragEnd = useCallback(function () {
if (!isDragging.current) return;
isDragging.current = false;
}, []);

useMountDragEvent(onDrag, onDragEnd);

return {
x,
y,
reset() {
setX(0);
setY(0);
},
onPointerDown: onDragStart,
};
}

export default usePointDrag;
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useImperativeHandle } from "react";
import InteractionDescription from "../InteractionDescription.jsx";
import BatteryProgressBar from "./BatteryProgressBar.jsx";
import orderIcon from "@/assets/property2.svg";
import dialSvg from "./timer.svg";
import dialSvg from "./assets/timer.svg";
import useDialDrag from "./useDialDrag.js";

const MAX_MINUTE = 30;
Expand Down Expand Up @@ -35,20 +35,12 @@ function FastChargeInteraction({ interactCallback, $ref }) {

return (
<article className="relative w-full h-full overflow-hidden flex items-center flex-col">
<div className="w-full max-w-[1200px] px-10 lg:px-20 flex gap-2 items-start mt-16 lg:mt-[6.25rem] ">
<img src={orderIcon} alt="2" />
<div className="flex flex-col gap-3.5 font-bold">
<h3 className="text-neutral-400 text-title-m md:text-title-l">
불편함 없이, 더 빠르게
</h3>
<p className="text-white text-body-m md:text-body-l">
The new IONIQ 5의 배터리를 충전하는 데 얼마만큼의 시간이 걸릴까요?
</p>
<p className="text-neutral-200 text-body-s">
다이얼을 돌려 충전에 필요한 시간을 확인해보세요!
</p>
</div>
</div>
<InteractionDescription
order="2"
title="불편함 없이, 더 빠르게"
description="The new IONIQ 5의 배터리를 충전하는 데 얼마만큼의 시간이 걸릴까요?"
directive="다이얼을 돌려 충전에 필요한 시간을 확인해보세요!"
/>
<div className="absolute top-[clamp(240px,40%,384px)] w-72 md:w-96 h-32 border-solid border-2 border-neutral-600 rounded-[30px] p-3.5">
<div className="absolute w-5 h-9 bg-neutral-600 right-[-1.25rem] top-[2.875rem] rounded-r-md"></div>
<BatteryProgressBar progress={progress} />
Expand Down
6 changes: 5 additions & 1 deletion src/interactions/fastCharge/useDialDrag.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,11 @@ function useDialDrag() {
setIsDrag(true);
}

const resetAngle = useCallback(() => setAngle(0), []);
const resetAngle = useCallback(() => {
setAngle(0);
angleCache.current = 0;
prevAngle.current = 0;
}, []);

const style = {
transform: `rotate(${angle}rad)`,
Expand Down
Loading