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

[Feature] performance 섹션 구현, useInView 커스텀 훅 제작 #67

Merged
merged 8 commits into from
Aug 14, 2024
Binary file added src/assets/images/powerImg.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
32 changes: 32 additions & 0 deletions src/constants/InfoData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,35 @@ export const convenienceInfoData = [
"주행/주차 중 전/후방 카메라를 통해 영상을 기록하고, 내비게이션 화면을 통해 영상을 확인하거나 스마트폰으로 전송할 수 있는 빌트인 영상기록 장치입니다.",
},
];

export const PERFORMANCE = {
title: "성능",
subtitle: "도심에서 빛나는 강력한 주행 성능",
};

export const ENGINE_SPECS = {
turbo_1_6: {
title: "1.6 가솔린 터보",
specs: [
{ value: "198", label: "최고출력\nps / 6,000rpm" },
{ value: "27.0", label: "최대토크\nkgf∙m / 1,600~45,00rpm" },
{ value: "12.8", label: "복합연비\nkm/L" },
],
note: "(2WD 16인치 타이어, 빌트인 캠 미장착 기준)",
},
gasoline_2_0: {
title: "2.0 가솔린",
specs: [
{ value: "149", label: "최고출력\nps / 6,000rpm" },
{ value: "18.3", label: "최대토크\nkgf∙m / 1,600~45,00rpm" },
{ value: "12.9", label: "복합연비\nkm/L" },
],
note: "(2WD 16인치 타이어 기준)",
},
};

export const ELECTRONIC_4WD = {
title: "전자식 4WD",
description:
"노면 및 주행 상황에 따라 구동력을 전후륜에 능동적으로 배분하여 안정적인 선회 및 우수한 주행 성능을 제공합니다.",
};
46 changes: 46 additions & 0 deletions src/hooks/useInView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { useEffect, useRef, useState } from "react";

/**
* 훅을 사용하는 컴포넌트가 랜더링 될 때 ref에 옵저버 등록
* 사용자 뷰에 threshold만큼 ref요소가 들어오면 isInView true 리턴
* @param {number} threshold 임계점
* @returns { isInView, elementRef }
* @example
* const ExampleComponent = () => {
* const { isInView, elementRef } = useInView<HTMLDivElement>(0.5);
* return <div ref={elementRef}>{isInView ? "In view" : "Out of view"}</div>;
* };
*/
const useInView = <T extends Element>(threshold: number) => {
const [isInView, setIsInView] = useState(false);
const elementRef = useRef<T>(null);

useEffect(() => {
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
setIsInView(true);
} else if (entry.intersectionRect.top !== 0) {
setIsInView(false);
}
});
},
{ threshold },
);

if (elementRef.current) {
observer.observe(elementRef.current);
}

return () => {
if (elementRef.current) {
observer.unobserve(elementRef.current);
}
};
}, [threshold]);

return { isInView, elementRef };
};

export default useInView;
32 changes: 3 additions & 29 deletions src/pages/mainPage/InfoScreen/ConvenienceSection.tsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,14 @@
import React, { useEffect, useRef, useState } from "react";
import ConvenienceDescriptionItem from "../../../components/mainPage/InfoScreen/ConvenienceDescriptionItem";
import { convenienceInfoData } from "../../../constants/InfoData";
import useInView from "../../../hooks/useInView";

const ConvenienceSection = () => {
const [isInView, setIsInView] = useState(false);
const divRef = useRef(null);
const { isInView, elementRef } = useInView<HTMLDivElement>(0.9);

useEffect(() => {
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
setIsInView(true);
} else if (entry.intersectionRect.top !== 0) {
setIsInView(false);
}
});
},
{
threshold: 0.9,
},
);

if (divRef.current) {
observer.observe(divRef.current);
}

return () => {
if (divRef.current) {
observer.unobserve(divRef.current);
}
};
}, []);
return (
<div
ref={divRef}
ref={elementRef}
className="flex h-screen w-screen snap-start items-center overflow-scroll bg-white"
>
<div
Expand Down
33 changes: 3 additions & 30 deletions src/pages/mainPage/InfoScreen/DriveSection.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useEffect, useRef, useState } from "react";
import DriveDescriptionItem from "../../../components/mainPage/InfoScreen/DriveDescriptionItem";
import { driveInfoData } from "../../../constants/InfoData";
import useInView from "../../../hooks/useInView";

const animationDelay = {
0: "delay-0",
Expand All @@ -12,40 +13,12 @@ const animationDelay = {
};

const DriveSection = () => {
const [isInView, setIsInView] = useState(false);
const { isInView, elementRef } = useInView<HTMLDivElement>(0.9);
const [selectedIndex, setSelectedIndex] = useState(-1);
const divRef = useRef(null);

useEffect(() => {
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
setIsInView(true);
} else if (entry.intersectionRect.top !== 0) {
setIsInView(false);
}
});
},
{
threshold: 0.9,
},
);

if (divRef.current) {
observer.observe(divRef.current);
}

return () => {
if (divRef.current) {
observer.unobserve(divRef.current);
}
};
}, []);

return (
<div
ref={divRef}
ref={elementRef}
className="flex h-screen w-screen snap-start flex-col items-center bg-white flex-center"
>
<div className="mb-600 h-[2.75rem] rounded-[6.25rem] px-500 py-300 font-kia-signature text-title-4 text-gray-400 flex-center gradient-border">
Expand Down
33 changes: 3 additions & 30 deletions src/pages/mainPage/InfoScreen/OutsideSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,10 @@ import OutsideDescriptionItem from "../../../components/mainPage/InfoScreen/Outs
import OutsideInfo from "../../../assets/images/OutsideInfo.png";
import { outsideInfoData } from "../../../constants/InfoData";
import Carousel from "../../../components/common/Carousel/Carousel";
import useInView from "../../../hooks/useInView";

const OutsideSection = () => {
const [isInView, setIsInView] = useState(false);
const imgRef = useRef(null);

useEffect(() => {
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
setIsInView(true);
} else if (entry.intersectionRect.top !== 0) {
setIsInView(false);
}
});
},
{
threshold: 0.9,
},
);

if (imgRef.current) {
observer.observe(imgRef.current);
}

return () => {
if (imgRef.current) {
observer.unobserve(imgRef.current);
}
};
}, []);
const { isInView, elementRef } = useInView<HTMLImageElement>(0.9);

return (
<div className="flex w-screen snap-start flex-col items-center bg-white">
Expand All @@ -44,7 +17,7 @@ const OutsideSection = () => {
역동적인 스타일에 미래적 감성을 더하다
</div>
<img
ref={imgRef}
ref={elementRef}
src={OutsideInfo}
alt="OutsideImage"
className={`h-screen w-screen snap-start ${isInView ? "scale-100" : "scale-90"} mb- transition-transform duration-200`}
Expand Down
Loading
Loading