diff --git a/src/components/Home/Home.tsx b/src/components/Home/Home.tsx index e786ada..3318d37 100644 --- a/src/components/Home/Home.tsx +++ b/src/components/Home/Home.tsx @@ -3,6 +3,7 @@ import { useEffect } from "react"; import styles from "@/components/Home/Home.module.scss"; import { AppBridgeMessageType } from "@/components/provider/AppBridgeProvider/AppBridgeMessage.types"; import { useAppBridge } from "@/components/provider/AppBridgeProvider/AppBridgeProvider"; +import AnimationText from "@/components/ui/AnimationText/AnimationText"; import IconButton from "@/components/ui/IconButton/IconButton"; import Text from "@/components/ui/Text/Text"; @@ -27,9 +28,7 @@ const Home = () => {
- - {`영수증으로\nAI 음식 리뷰 남겨요`} - + 손쉬운 음식 리뷰 작성 diff --git a/src/components/ui/AnimationText/AnimationText.tsx b/src/components/ui/AnimationText/AnimationText.tsx new file mode 100644 index 0000000..603baa1 --- /dev/null +++ b/src/components/ui/AnimationText/AnimationText.tsx @@ -0,0 +1,94 @@ +import React, { useEffect, useState } from "react"; + +import classNames from "classnames"; + +import styles from "@/components/ui/Text/Text.module.scss"; + +interface Letter { + char: string; + id: number; +} + +const AnimationText: React.FC = () => { + const [firstLineLetters, setFirstLineLetters] = useState([]); + const [secondLineLetters, setSecondLineLetters] = useState([]); + const [hasAnimated, setHasAnimated] = useState(false); + + useEffect(() => { + if (hasAnimated) return; + setHasAnimated(true); + + const firstLine = "영수증으로"; + const firstLetters = firstLine.split("").map((char, index) => ({ + char, + id: index, + })); + setFirstLineLetters(firstLetters); + + const firstLineDelay = firstLine.length * 20 + 100; + setTimeout(() => { + const secondLine = "AI 음식 리뷰 남겨요"; + const secondLetters = [...secondLine].map((char, index) => ({ + // split("") 대신 [...string] 사용 + char, + id: index, + })); + setSecondLineLetters(secondLetters); + }, firstLineDelay); + }, [hasAnimated]); + + return ( +
+

+ {firstLineLetters.map((letter, index) => ( + + {letter.char} + + ))} +

+

+ {secondLineLetters.map((letter, index) => ( + + {letter.char} + + ))} +

+
+ ); +}; + +export default AnimationText; diff --git a/src/components/ui/Text/Text.module.scss b/src/components/ui/Text/Text.module.scss index e3442af..96fed48 100644 --- a/src/components/ui/Text/Text.module.scss +++ b/src/components/ui/Text/Text.module.scss @@ -111,3 +111,48 @@ justify-content: center; } } + +.TitleWrapper { + height: 5.25rem; +} + +.word { + display: flex; + justify-content: center; + align-items: center; + text-align: center; + + .letter { + display: inline-block; + opacity: 0; + filter: blur(8px); + transform: translateY(20px); + transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1); + + &.appear { + opacity: 1; + filter: blur(0); + transform: translateY(0); + } + } +} + +@keyframes textBlur { + 0% { + opacity: 0; + filter: blur(8px); + transform: translateY(20px); + } + + 100% { + opacity: 1; + filter: blur(0); + transform: translateY(0); + } +} + +.space { + width: 0.4rem; + opacity: 1; + visibility: visible; +}