Skip to content

Commit

Permalink
Merge pull request #45 from softeerbootcamp4th/feature/23-subsidyInte…
Browse files Browse the repository at this point in the history
…raction

[feat] 보조금 인터랙션 추가 ( resolve #23 )
  • Loading branch information
darkdulgi authored Jul 29, 2024
2 parents f88f238 + c66cf35 commit 96c5710
Show file tree
Hide file tree
Showing 17 changed files with 1,290 additions and 33 deletions.
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;
File renamed without changes
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

0 comments on commit 96c5710

Please sign in to comment.