ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • ๋ฆฌ์•กํŠธ์—์„œ requestAnimationFrame ์‚ฌ์šฉ ์‹œ ์ฃผ์˜ํ•  ์ 
    TECH 2024. 3. 17. 20:41

    ๋ฆฌ์•กํŠธ์—์„œ 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

     

    ๋Œ“๊ธ€

Designed by Tistory.