Skip to content

Commit

Permalink
Merge pull request #56 from softeerbootcamp4th/feature/8-simpleinform…
Browse files Browse the repository at this point in the history
…ation

[feat] 차량 간단정보 구현
  • Loading branch information
lybell-art authored Aug 1, 2024
2 parents 0a9636b + fb9f818 commit 8acab20
Show file tree
Hide file tree
Showing 10 changed files with 160 additions and 5 deletions.
Binary file added public/carimg1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/carimg2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/carimg3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/carimg4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/carimg5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 2 additions & 5 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useEffect } from "react";
import IntroSection from "./introSection";
import Header from "./header";
import SimpleInformation from "./simpleInformation";
import QnA from "./qna";
import Footer from "./footer";

Expand All @@ -14,11 +15,7 @@ function App() {
<>
<IntroSection />
<Header />
<img
src="https://image.utoimage.com/preview/cp872655/2018/03/201803016775_500.jpg"
className="h-[2000px]"
alt="test image"
/>
<SimpleInformation />
<QnA />
<Footer />
</>
Expand Down
34 changes: 34 additions & 0 deletions src/simpleInformation/contentList.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"content": [
{
"src": "carimg1.png",
"title": "독창적인 디자인",
"desc": ["아이오닉 브랜드를 상징하는\n", "파라메트릭 픽셀 램프 디자인", "으로\n유니크한 이미지를 구현합니다."],
"sub": "프로젝션 타입과 MFR 타입 중 선택 가능"
},
{
"src": "carimg2.png",
"title": "전용 전기차 플랫폼(E-GMP)",
"desc": ["", "새로워진 전기차 플랫폼 E-GMP", "\n알루미늄 압출재를 이용해\n구조적 안정성을 높였습니다."],
"sub": "연출된 이미지로 실제 작동 사양과 다를 수 있음"
},
{
"src": "carimg3.png",
"title": "인터랙티브 픽셀 라이트",
"desc": ["", "신규 디자인의 스티어링 휠", "\n아이오닉5만의 차별화된\n주행 경험을 제공합니다."],
"sub": "시동 / 충전 중 / 후진 중 표시 가능"
},
{
"src": "carimg4.png",
"title": "증강현실 내비게이션",
"desc": ["주행에 필요한 각종 정보들을\n", "증강현실 기술", "을 통해\n직관적으로 제공합니다."],
"sub": "인포테인먼트 시스템 화면 이미지는 업데이트에 따라 변동 가능"
},
{
"src": "carimg5.png",
"title": "디지털 사이드 미러",
"desc": ["보다 슬림해진 ", "디지털 사이드 미러", "\n카메라와 ", "OLED 모니터", "를 통해\n선명한 후방 시야를 제공합니다."],
"sub": "모니터는 내부 운전석에 위치"
}
]
}
72 changes: 72 additions & 0 deletions src/simpleInformation/contentSection.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { useEffect, useRef, useState } from "react";
import style from "./contentSection.module.css";

export default function ContentSection({ content }) {
const contentRef = useRef(null);
const [isVisible, setIsVisible] = useState(false);
const [isHighlighted, setIsHighlighted] = useState(false);

useEffect(() => {
const contentDOM = contentRef.current;
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
setIsVisible(true);
observer.unobserve(entry.target); // 애니메이션 실행 후 옵저버 중지
}
});
},
{
threshold: 0.8, // 80%가 보일 때 실행
},
);

if (contentDOM) {
observer.observe(contentDOM);
}

// 클린업 함수
return () => {
if (contentDOM) {
observer.unobserve(contentDOM);
}
};
}, []);

const highlightDynamicStyle = {
"--progress": isHighlighted ? "100%" : "0%",
};

return (
<div
ref={contentRef}
onAnimationEnd={() => setIsHighlighted(true)}
className={`${isVisible ? style.fadeIn : "opacity-0"} z-0 flex flex-col font-bold`}
>
<img src={content.src} className="w-full" />

<span className="pt-10 text-body-l text-neutral-800">
{content.title}
</span>

<div className="pt-3 flex justify-between items-end">
<div>
{content.desc.map((str, index) => (
<span
key={index}
style={highlightDynamicStyle}
className={`${index % 2 ? style.highlightAnim : "text-neutral-800"} text-title-m whitespace-pre-wrap`}
>
{str}
</span>
))}
</div>

<span className="absoulte top-0 right-0 text-body-s text-neutral-300">
{content.sub}
</span>
</div>
</div>
);
}
30 changes: 30 additions & 0 deletions src/simpleInformation/contentSection.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
.fadeIn {
animation: fade-in 0.4s ease-out forwards;
}

@keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}

.highlightAnim {
display: inline-block;
position: relative;
}

.highlightAnim::before {
content: "";
position: absolute;
display: block;
width: 100%;
height: 1.4em;
background: linear-gradient(90deg, #3ED7BE, #069AF8);
opacity: 0.3;
z-index: -1;
clip-path: polygon(0 0, 0 100%, var(--progress, 0) 100%, var(--progress, 0) 0);
transition: clip-path 0.4s;
}
22 changes: 22 additions & 0 deletions src/simpleInformation/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import JSONData from "./contentList.json";
import ContentSection from "./contentSection";

export default function SimpleInformation() {
const contentList = JSONData.content;

return (
<div className="h-[4700px] flex justify-center ">
<div className="w-[1200px] flex flex-col gap-[160px]">
<div className="flex flex-col text-black font-bold pt-[240px]">
<span className="text-title-m">내가 선택한 단 하나의 전기차</span>

<span className="text-head-l">The new IONIQ 5</span>
</div>

{contentList.map((content, index) => (
<ContentSection key={index} content={content} />
))}
</div>
</div>
);
}

0 comments on commit 8acab20

Please sign in to comment.