몇 초 후에 자동으로 카드를 뒤집고 클릭시에도 카드를 뒤집는 효과이다
보통 이렇게 카드를 뒤집는 것을 card flip 이라고 하고, 검색으로 쉽게 구현이 가능한 효과다.
많은 사람들이 over 시 뒤집히도록 css로 hover 시 변화하도록 많이 구현하지만, 나는 hover가 아니라 클릭 시 뒤집히길 바라고, 클릭하지 않아도 몇 초 후에 자동으로 뒤집히게 구현해보고 싶었다.
핵심 원리를 요약하자면,
- CSS transition과 transform-style: preserve-3d;을 사용하여 카드 요소의 3D 회전 효과를 구현
- React의 useState와 useEffect로 카드의 뒤집힘 상태(isFlipped)를 관리하고, 시간 간격이나 클릭 이벤트에 따라 상태를 변경
- isFlipped 상태에 따라 flipped 클래스를 조건부로 적용하여 카드 뒤집기 효과를 활성화
이렇게 된다.
아래의 코드의 각 줄마다 상세 설명을 주석으로 남겨두었다.
Next.js 14와 타입스크립트를 사용하였지만, React에도 "use client" 를 제거하면 그대로 사용 가능하다.
"use client";
import Image from "next/image";
import MultiTypingEffect from "../MultiTypingEffect/MultiTypingEffect";
import useDeviceType from "@/app/hooks/useDeviceType";
import style from "./About.module.css";
import { useEffect, useState } from "react";
const aboutTexts = [
`문자열1`,`문자열2`
];
export default function About() {
const deviceType = useDeviceType();
const [isFlipped, setIsFlipped] = useState(false);
useEffect(() => {
const interval = setInterval(() => {
setIsFlipped((prev) => !prev);
}, 3000);
return () => clearTimeout(interval);
}, [isFlipped]);
const handleImageClick = () => {
setIsFlipped(!isFlipped);
};
return (
<section className={`${style.container} scroll-point`} id="about">
<div className={`w-full min-h-[28rem] flex justify-center`}>
{/* 좌측 텍스트 영역 */}
<div className={style.textWrapper}>
<h2 className={style.head2}>About</h2>
<div className=" text-2xl mb-8">
<MultiTypingEffect texts={aboutTexts} />
</div>
</div>
{/* 우측 사진 영역 */}
{deviceType === "desktop" && (
<div className={style.imageWrapper} onClick={handleImageClick}>
<div
className={`${style.flipCard} ${isFlipped ? style.flipped : ""}`}
>
<div className={`${style.front}`}>
<Image
className={`${style.profileImg}`}
src="/앞면_이미지.jpg"
alt="앞면에 보일 이미지"
fill
/>
</div>
<div className={`${style.back}`}>
<Image
className={`${style.profileImg}`}
src="/뒷면_이미지.jpg"
alt="뒷면에 보일 이미지"
fill
/>
</div>
</div>
</div>
)}
</div>
</section>
);
}
.container {
display: flex;
justify-content: center;
align-items: center;
height: 100dvh;
flex-direction: column;
}
.head2 {
font-size: 4rem;
margin-bottom: 2rem;
}
.textWrapper {
width: 30rem;
display: flex;
flex-direction: column;
min-height: 12rem;
}
@media screen and (min-width: 450px) {
.container {
padding-left: 2rem;
padding-right: 2rem;
}
.head2 {
font-size: 6rem;
font-weight: 800;
}
.textWrapper {
width: 30rem;
min-height: 25rem;
}
}
@media screen and (min-width: 1024px) {
.container {
padding-left: 2rem;
padding-right: 2rem;
max-width: 120rem;
}
.head2 {
font-size: 8rem;
font-weight: 800;
margin-bottom: 1rem;
}
.textWrapper {
width: 40rem;
min-height: 33rem;
}
.imageWrapper {
width: fit-content;
display: flex;
justify-content: center;
align-items: center;
perspective: 1000px;
}
.flipCard {
transition: 0.8s;
transform-style: preserve-3d;
position: relative;
width: 240px;
height: 240px;
}
.profileImg {
border-radius: 0.5rem;
border: 2px solid white;
object-fit: cover;
}
.front,
.back {
backface-visibility: hidden;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.back {
transform: rotateY(180deg);
}
.flipped {
transform: rotateY(180deg);
}
}
'Next.js > 개발 노트' 카테고리의 다른 글
[React/Next.js] 라이브러리 없이 구현하는 카드 조명 효과 (1) | 2023.12.31 |
---|---|
[React/Next.js] 라이브러리 없이 구현하는 3D carousel (0) | 2023.12.31 |
[React/Next.js] 여러 줄의 타이핑(multi line typing effect) 효과 (0) | 2023.12.31 |
Next.js 13에서 TypeScript를 사용한 WebSocket 구현 (2) | 2023.12.05 |
Next.js 개발 중, MongoDB 중복 접속 방지 TS 코드 (0) | 2023.04.29 |
댓글