리μ‘νΈμμ requestAnimationFrame μ¬μ© μ μ£Όμν μ
리μ‘νΈμμ requestAnimationFrame
APIλ₯Ό μ¬μ©νλ©΄μ κ²ͺμλ λ¬Έμ λ₯Ό 곡μ ν΄ λ³΄λ €κ³ ν©λλ€.
π λ¬Έμ κ° λμλ μ½λ
function AnimationSection() {
const [count, setCount] = useState(0);
const text = 'welcome to ttaerrim world'.toUpperCase();
const textRef = useRef<HTMLDivElement>(null);
const animate = () => {
const width = textRef.current?.scrollWidth;
if (width) {
if (count > width) {
setCount(0);
} else {
setCount((c) => c + 10);
}
}
requestRef.current = requestAnimationFrame(animate);
};
useEffect(() => {
requestRef.current = requestAnimationFrame(animate);
return () => cancelAnimationFrame(requestRef.current);
}, []);
// ... μλ΅
}
μ νλΈμμ λ³Έ λ§μλ μ½λ©λμ μλ°μ€ν¬λ¦½νΈλ‘ 5λΆλ§μ ν μ€νΈ μ€ν¬λ‘€ μ λλ©μ΄μ ν¨κ³Ό(text marquee effect) λ§μ€ν°νκΈ°λ₯Ό λ³΄κ³ μλ°μ€ν¬λ¦½νΈ μμ λ₯Ό 리μ‘νΈ μ½λλ‘ μμ±νμ¬ μ λλ©μ΄μ μ λμνκ³ μΆμμ΅λλ€.
μμμμ μ€λͺ
νλ λ°©μλλ‘ element
μ width
κ° count
λ₯Ό μ΄κ³Όνκ² λλ©΄ count
λ₯Ό 0μΌλ‘ λ³κ²½νμ¬ λμμμ΄ νλ₯΄λ κ²μ²λΌ 보μ΄λ μ λλ©μ΄μ
μ λ§λλ κ²μ΄ λͺ©νμμΌλ μμλλ‘ λμνμ§ μμμ΅λλ€.
μ΄μ λ useEffect
λ΄μμλ μ¬μ©νλ count
λ³μκ° setCount
λ‘ λ³κ²½νλλΌλ μ΄κΈ°κ° 0μμ λ³κ²½λμ§ μλ νμμ΄ μμμ΅λλ€.
κ·Έλ κΈ° λλ¬Έμ ifλ¬Έμ (count > width)
쑰건μ μ ν μ μμλ ꡬ쑰μμ΅λλ€.
β useEffect
κ° μ΄λ κ² λμνλ μ΄μ λ 무μμΌκΉμ?
useEffect
μ λ λ²μ§Έ μΈμλ‘ λΉ λ°°μ΄μ μ λ¬νλ©΄ useEffect
λ‘ μ λ¬νλ μ½λ°±ν¨μλ₯Ό ν λ²λ§ μ€νν μ μμ΅λλ€.
κ·Έλ°λ° μ΄λ κ² νλ©΄ μ λλ©μ΄μ μ€μ μ¬λ°λ₯Έ μνλ₯Ό μ μ§ν μ μμ΅λλ€.
useEffect
μ dependencyλ‘ λΉ λ°°μ΄μ μ λ¬νλ κ²μ 리μ‘νΈλ μνλ₯Ό μ΅μ μΌλ‘ μ μ§ν νμκ° μλ€λ μλ―Έλ‘ ν΄μνκΈ° λλ¬Έμ
λλ€.
λ°λΌμ λΉ λ°°μ΄μ dependecyλ‘ κ°μ§λ useEffect
λ΄μμ stateμ κ°μ κ°μ Έμ€λ©΄ νμ μ΄κΈ°κ°μλ§ μ κ·Όν μ μμ΅λλ€.
λ°λΌμ λ€μκ³Ό κ°μ΄ μ λλ©μ΄μ μ½λλ₯Ό μμ νμ΅λλ€.
function AnimationSection() {
const [count, setCount] = useState(0);
const text = 'welcome to ttaerrim world'.toUpperCase();
const textRef = useRef<HTMLDivElement>(null);
const requestRef = useRef<number>(0);
const previousTimeRef = useRef<number>(0);
const animate = (time: DOMHighResTimeStamp) => {
const width = textRef.current?.scrollWidth;
if (previousTimeRef.current !== undefined && width) {
const deltaTime = Math.floor(time - previousTimeRef.current);
setCount((prevCount) => (prevCount + deltaTime * 0.2) % width);
}
previousTimeRef.current = time;
requestRef.current = requestAnimationFrame(animate);
};
useEffect(() => {
requestRef.current = requestAnimationFrame(animate);
return () => cancelAnimationFrame(requestRef.current);
}, []);
// μλ΅
}
useEffect
λ΄μμλ stateμ μ΄κΈ°κ°μ κ°μ Έμ€κΈ° λλ¬Έμ setCount
ν¨μλ setCount((count + deltaTime * 0.2) % width)
μ²λΌ μ¬μ©νλ©΄ λ λκ°μ κ°μ count
λ‘ μ§μ νλ κ²κ³Ό κ°μ΅λλ€.
μ΅μ μ μν κ°μ μ¬μ©νλ €λ©΄ setState
λ‘ ν¨μλ₯Ό λ겨 μ€λλ€.
setState(prevState ⇒ prevState + value)
μ΄λ° μμΌλ‘, νμ¬ μνλ₯Ό κΈ°μ€μΌλ‘ κ°μ μ λ¬νμ¬ μ μ©νλ©΄ μν κ°μ΄ λ³κ²½λ©λλ€.
μ λλ©μ΄μ
λμμ μ¬μ©λλ μν κ° μ€ κ°μ΄ λ³κ²½λλλΌλ λ λλ§μν€μ§ μκ³ μΆμ λκ° μμ΅λλ€. μ΄ κ²½μ°μλ useRef
λ₯Ό μ¬μ©ν©λλ€. useRef
λ λ³κ²½λλλΌλ λ λλ§μ μν₯μ λ―ΈμΉμ§ μμ΅λλ€.
μ λλ©μ΄μ
μ cleanup ν λ κ³μ λ³κ²½λλ reqeustAnimationFrame
μ idλ₯Ό μ μ₯ν΄ λμ΄μΌ νκ³ , κ²½κ³Όλ μκ°μ κΈ°μ€μΌλ‘ μ λλ©μ΄μ
μ μ μ©νλ κ²½μ° νμμ€ν¬νλ₯Ό κΈ°μ΅ν΄μΌ ν©λλ€. μ΄ λ λ³μλ₯Ό useRef
λ₯Ό μ¬μ©ν΄ requestRef
μ previousTimeRef
μ μ μ₯ν΄ μ¬μ©νμ΅λλ€.
π μ°Έκ³
Using requestAnimationFrame with React Hooks | CSS-Tricks - CSS-Tricks