Understanding JavaScript's requestAnimationFrame() method for smooth animations - Lee-hyuna/33-js-concepts-kr GitHub Wiki
์๋ฌธ : http://www.javascriptkit.com/javatutors/requestanimationframe.shtml
์์ฑ์ผ(์์ ์ผ) 2017-11-01
- animation : ์ ๋๋งค์ด์
- interaction : ์ธํฐ๋ ์ (์ํธ ์์ฉ)
- logic : ๋ก์ง
- recursively : ์ฌ๊ท์ ์ผ๋ก
- element : ์๋ฆฌ๋จผํธ
- delay : ์ง์ฐ ์๊ฐ
- function : ํจ์
- frame : ํ๋ ์
- resource : ์์
- reflow : ๋ฆฌํ๋ก์ฐ
- cardiac arrest : ์ฌ์ ์ง๋ฅผ ๋ปํ์ฌ ๋ฉ์ถฐ์์์ผ๋ก ๋ฒ์ญ
- layout thrashing : ๋ ์ด์์ ์ค๋ ์ฑ
- janky page : ์ ์ฑ๋ฅ์ ํ์ด์ง
- method : ๋ฉ์๋
- repaint : ๋ฆฌํ์ธํธ
- vendor prefix : ๋ฒค๋ ํ๋ฆฌํฝ์ค
- sync : ๋๊ธฐํ
- fallback : ํด๋ฐฑ
- nemesis counterpart : ์์ญ;์ฝ๋ฐฑ ํจ์ ์คํ์ ์์ํ ๋์ ์์ ์ฐธ๊ณ : MDN
- callback : ์ฝ๋ฐฑ
- parameter : ๋งค๊ฐ๋ณ์
- variable : ๋ณ์
- return : ๋ฐํ
์ค๋๋ ์ ์น์ ๋ชจ๋ ํ์ด์ง์์ ๋ค์ํ ๋ณผ๊ฑฐ๋ฆฌ๋ก ๊ฐ๋ ์ฐจ ์์ต๋๋ค. ๋ฉ๋ด๊ฐ ์ฌ๋ผ์ด๋ ๋๊ฑฐ๋ ๋ณด์ด์ง ์๊ฒ ๋๊ณ , ๋ด์ฉ์ด ๋ถ๋๋ฝ๊ฒ ์ฌ๋ผ์ง๊ณ , ์ฌ์ฉ์๊ฐ ํ์ด์ง๋ฅผ ์คํฌ๋กค ํ ๋ ์ฃผ์๋ก ์ ๋๋ฉ์ด์ ์ด ์๊น๋๋ค. CSS3๋ Javascript๋ฅผ ๋์ ํ์ฌ ์ด๋ฌํ ๋ง์ ์ ๋๋ฉ์ด์ ์ ์ง๊ด์ ์ด๊ณ ์ต์ ํ๋ ํํ๋ก ์คํ๋๋๋ก ๋์์ ์ฃผ์์ต๋๋ค. ํ์ง๋ง ์ฌ์ฉ์์ ์ธํฐ๋ ์ ์ด๋ ๋น์ ํ ๋ก์ง์ด ํฌํจ๋ ๋ณด๋ค ๋ณต์กํ ์๋๋ฆฌ์ค์์๋ Javascript๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์๋ํ๋ฉด Javascript์ requestAnimationFrame() ๋ฉ์๋๋ก ์ธํด ์ฌ์ฉ์์ ํ๋ฉด์ ํจ์จ์ ์ด๊ณ , ์ต์ ํ ๋ ๋ฐฉ์์ผ๋ก ๋ณ๊ฒฝํ๋ ์ ๋๋ฉ์ด์ ๊ด๋ จ ์ฝ๋๋ฅผ ์คํํ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค. ๋ง์ ์ฌ๋์ด ํํ์ ์ ๋๋ก ์ดํดํ์ง ๋ชปํ๊ฑฐ๋ ์ ์ ํ๊ฒ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ๊ณผ๋ ๋ฌ๋ฆฌ, ์์ ์๋ ์ด ๋ฐฉ๋ฒ์ ๋ํด์๋ ๋ค์ ์ ์์์ต๋๋ค. ์ด ํํ ๋ฆฌ์ผ์์ ์ฐ๋ฆฌ๋ requestAnimationFrame ()์ ํ์ฉํ์ฌ ์คํฌ๋ฆฝํธ์์ ์ต์ ์ ์ ๋๋ฉ์ด์ ์ ์ํํ ์ ์์ต๋๋ค.
์ฐ์ requestAnimationFrame()์ ๋ํ ์์ด๋์ด์ ์ ๊ทธ ๋ฉ์๋๊ฐ ํ์ํ์ง ์ด์ผ๊ธฐํด ๋ณด๊ฒ ์ต๋๋ค. ์ ํต์ ์ธ ๋ฐฉ๋ฒ์ผ๋ก Javascript๋ก ์ ๋๋ฉ์ด์ ์ ๋ง๋ค๋ ค๋ฉด ์ฌ๊ท์ ์ผ๋ก setTimeout()์ ํธ์ถํ๊ฑฐ๋, ๋ฐ๋ณต์ ์ผ๋ก setInterval()์ ์คํํ๋๋ก ํ์ฌ ์๋ฆฌ๋จผํธ๋ฅผ ํ๋ ์ ๋จ์๋ก ๋ณ๊ฒฝ(์: 50๋ฐ๋ฆฌ์ด๋ง๋ค ํ ๋ฒ์ฉ)ํ๋ ์ฝ๋๋ฅผ ์์ฑํด์ผ ํฉ๋๋ค.
var adiv = document.getElementById('mydiv')
var leftpos = 0
setInterval(function(){
leftpos += 5
adiv.style.left = leftpos + 'px' // move div by 5 pixels each time
}, 50) // run code every 50 milliseconds
์์ ์ฝ๋๊ฐ ๋ก์ง์ ์ผ๋ก๋ ๋ง์ ๋ณด์ด์ง๋ง ์ค์ ๋ก ์คํํด๋ณด๋ฉด ์๋ฒฝํ์ง ์์ต๋๋ค. ํ๋ฉด์์ ๋ฌด์ธ๊ฐ๋ฅผ ๋ณ๊ฒฝํ๋ ์ฝ๋๋ฅผ ์คํํ๊ธฐ ์ํด setTmeout/setInterval์ ์ฌ์ฉํ ๋ ๋๊ฐ์ง์ ๋ฌธ์ ์ ์ด ์์ต๋๋ค.
-
์ด ํจ์๋ค์ด ๋ด๋ถ์ ์ผ๋ก ์ง์ฐ ์๊ฐ(์, 50 milliseconds)์ ๊ฐ์ ์ฃผ์์ง๋ง ์ฌ์ฉ์ ์์คํ ์์๋ค์ ๋ณํ๋ก ์ธํด ์ข ์ข ์คํ๋์ง ์์ ์ ๋๋ฉ์ด์ ํ๋ ์ ๊ฐ์ ์ผ๊ด์ฑ์๋ ์ง์ฐ ์๊ฐ์ ๊ฐ๊ฒฉ์ด ์๊น๋๋ค.
-
์ฌ์ง์ด ๋์ฑ ์ข์ง ์์ ๊ฒ์ setTimeout() or setInterval()์ ์ฌ์ฉํ์ฌ ์ฌ์ฉ์์ ํ๋ฉด์ ๊ณ์ ๋ณ๊ฒฝํ๋ฉด ์ข ์ข ์ฌ์ฉ์์ ํ๋ฉด์ด ๋ฌผ๋ฆฌ์ ์ผ๋ก ํํ๋๊ธฐ ์ ์ ๋ถํ์ํ ๋ฆฌํ๋ก์ฐ๋ฅผ ์ํํด์ผ ํ๋ ๋ธ๋ผ์ฐ์ ๊ฐ ๋ฉ์ถฐ ์์ ๋ "๋ ์ด์์ ์ค๋ ์ฑ"์ ์ ๋ฐํ์ฌ ๋ณ๊ฒฝ ์ฌํญ์ ํ์ํฉ๋๋ค. ์ด๊ฒ์ ํ์ด์ง ๋ฆฌํ๋ก์ฐ์ ๊ณผ๋ํ ํน์ง์ผ๋ก ํนํ ์ ์ฑ๋ฅ์ ๋ชจ๋ฐ์ผ ํ์ด์ง ๋ก๋ ๋๋ ๋ฒ ํฐ๋ฆฌ ์๋ชจ๊ฐ ๋ฐ์ํ์ฌ ๋งค์ฐ ์ข์ง ์์ ์ํฅ์ ์ค๋๋ค.
์์ ๋ ๊ฐ์ง ๋จ์ ์ผ๋ก ์ธํด requestAnimationFrame()์ด ๋์ ๋์์ต๋๋ค. ์์ฝํ๋ฉด ์ด ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ๋ค์๋ฒ์ ์ฌ์ฉํ ํ๋ฉด์ ๋ฆฌํ์ธํธ ์ ์ฝ๋๋ฅผ ์คํํ ์ ์๊ธฐ ๋๋ฌธ์ ์ฌ์ฉ์์ ๋ธ๋ผ์ฐ์ ์ ๋๊ธฐํ๋์ง ์์ ์์ ์ ๋ํ ์ถ์ธก๊ณผ ํ๋ฉด์ ๋ณ๊ฒฝํ๊ธฐ ์ํ ํ๋์จ์ด์ ์ค๋น ์ํ๊ฐ ์ฌ๋ผ์ง๋๋ค. requestAnimationFrame()์ ๋ฐ๋ณต์ ์ผ๋ก ํธ์ถํ์ฌ ์ ๋๋ฉ์ด์ ์ ๋ง๋ค๋ฉด ์ฌ์ฉ์์ ์ปดํจํฐ๊ฐ ๋งค๋ฒ ํ๋ฉด์ ๋ณ๊ฒฝํ ์ค๋น๊ฐ ๋์์ ๋ ์ ๋๋ฉ์ด์ ์ฝ๋๊ฐ ํธ์ถ๋์ด ๋ ๋ถ๋๋ฝ๊ณ ํจ์จ์ ์ธ ์ ๋๋ฉ์ด์ ์ ๋ง๋ค ์ ์์ต๋๋ค. ๋ํ requestAnimationFrame()์ ํตํด ํธ์ถ๋๊ณ ๋ธ๋ผ์ฐ์ ์ ๋ฐฑ๊ทธ๋ผ์ด๋ ํญ์์ ์คํ๋๋ ์ฝ๋๋ ์ผ์ ์ค์ง๋๊ฑฐ๋ ์ฌ์ฉ์ ์์คํ ๋ฆฌ์์ค๋ฅผ ์ถ๊ฐ๋ก ์ ์ฅํ๊ธฐ ์ํด 2ํ๋ ์ ์ดํ๋ก ๋๋ ค์ง๊ธฐ ๋๋ฌธ์ ์ ๋๋ฉ์ด์ ์ ์คํํ๋ ๋ฐ ์๋ฌด๋ฐ ์๋ฏธ๊ฐ ์์ต๋๋ค.
๋ฐ๋ผ์ ์ ๋๋ฉ์ด์ ์ ๊ฒฝ์ฐ setTimeout/ setInterval ๋์ requestAnimationFrame()์ ์ฌ์ฉํด์ผ ํฉ๋๋ค. ๊ทธ๋ฐ๋ฐ ์ ํํ ์ด๋ป๊ฒ ํด์ผํ ๊น์? ๋จผ์ ๋ธ๋ผ์ฐ์ ์ง์ ๋ฒ์์ ์ดํด๋ณด์ธ์. requestAnimationFrame()์ ์ค๋๋ IE10 +, FF11 +, Chrome ๋ฐ Safari ๋ฑ์ ์ต์ ๋ธ๋ผ์ฐ์ ๋ฅผ ๊ด๋ฒ์ํ๊ฒ ์ง์ํ๊ณ ์์ต๋๋ค. ์ด๋ฌํ ๋ธ๋ผ์ฐ์ ์ ์ผ๋ถ ์ด์ ๋ฒ์ ์์๋ ์ด๋ฅผ ์คํํ๊ฒ ํ๊ธฐ ์ํด ๋ฉ์๋ ์ด๋ฆ ์์ ๋ฒค๋ ํ๋ฆฌํฝ์ค๊ฐ ํ์ํฉ๋๋ค. ์ด ๋ฉ์๋๋ฅผ ์ง์ํ์ง ์๋ ์ด๋ ํ ํ๊ฒฝ์์์ ๋ธ๋ผ์ฐ์ ๋ ํน์ ์ง์ฐ ์๊ฐ ์ด ํ์ ์ฝ๋๋ฅผ ํธ์ถํ๊ธฐ ์ํด setTimeout()์ ํด๋ฐฑํ ์ ์์ต๋๋ค. ๋ค์ ์ฝ๋๋ ๋ฒ์ฉ์ ์ผ๋ก ์ฌ์ฉํ ์ ์๋ requestAnimationFrame() ํจ์์ cancelAnimationFrame() ํจ์์ ๋๋ค ์ด ํจ์๋ ํด๋ฐฑ์ด ๋ด์ฅ๋์ด ์์ต๋๋ค.
window.requestAnimationFrame = window.requestAnimationFrame
|| window.mozRequestAnimationFrame
|| window.webkitRequestAnimationFrame
|| window.msRequestAnimationFrame
|| function(f){return setTimeout(f, 1000/60)} // simulate calling code 60
window.cancelAnimationFrame = window.cancelAnimationFrame
|| window.mozCancelAnimationFrame
|| function(requestID){clearTimeout(requestID)} //fall back
๋์ฒด setTimeout() ์ฝ๋์ ๊ฒฝ์ฐ ์ง์ฐ์ด 1000/60 ๋๋ 16.7 ๋ฐ๋ฆฌ์ด๋ก ์ค์ ๋ฉ๋๋ค. ์ด๊ฒ์ ์ฌ์ฉ์์ ํ๋ฉด ์๋ก ๊ณ ์นจ ์๋์ธ ์ด๋น 60ํ๋ ์์ ๊ธฐ๋ฐ์ผ๋ก ๋ธ๋ผ์ฐ์ ๊ฐ ํธ์ถํ ๋๋ง๋ค ์ค์ requestAnimationFrame()์ด ์ผ๋ฐ์ ์ผ๋ก ์ผ๋ง๋ ์์ฃผ ํธ์ถ๋๋์ง ์๋ฎฌ๋ ์ดํธํฉ๋๋ค.
requestAnimationFrame์ ๊ตฌ๋ฌธ์ ๋งค์ฐ ๊ฐ๋จํฉ๋๋ค.
requestAnimationFrame(callback)
์ฐ๋ฆฌ๊ฐ ์คํํ๊ณ ์ ํ๋ ์ฝ๋๋ฅผ ํฌํจํ๋ ์ฝ๋ฐฑ ํจ์๋ฅผ ์ ๋ ฅํ๊ณ requestAnimationFrame()์ ํ๋ฉด์ด ๋ค์ ํ๋ฉด์ ๋ฆฌํ์ธํธ๋ฅผ ๋ฐ์๋ค์ผ ์ค๋น๊ฐ ๋๋ฉด ์ฝ๋ฐฑ ํจ์๋ฅผ ์คํํฉ๋๋ค.
์ฃผ๋ชฉํ ๋งํ ๋ช ๊ฐ์ง ์ฌํญ์ด ์์ต๋๋ค.
-
์ฝ๋ฐฑ ํจ์์๋ requestAnimationFrame()์ด ํธ์ถ๋ ์ ํํ ์๊ฐ์ ๋ํ๋ด๋ ํ์ ์คํฌํ๊ฐ ์๋์ผ๋ก ์ ๋ฌ๋ฉ๋๋ค.
-
requestAnimationFrame()์ ์ฝ๋ฐฑ ํจ์ ์คํ์ ์์ํ ๋์ ์์ (nemesis counterpart ์์ญ)์ด cancelAnimationFrame()์ ์ ๋ฌ๋์ด requestAnimationFrame() ํธ์ถ์ ์ทจ์ํ ์ ์๋ 0์ด ์๋ ์ ์๋ฅผ ๋ฐํํฉ๋๋ค. (requestAnimationFrame() returns a non 0 integer that can be passed into its nemesis counterpart cancelAnimationFrame() to cancel a requestAnimationFrame() call)
requestAnimationFrame ()์ ํ ๋ฒ ํธ์ถํ์ฌ DIV๋ฅผ ํ๋ฉด์ ์๋ ์์น์์ ๋จ์ง 5ํฝ์ ์ด๋์ํค๋ ์์ ๋๋ค.
var adiv = document.getElementById('mydiv')
var leftpos = 0
requestAnimationFrame(function(timestamp){
leftpos += 5
adiv.style.left = leftpos + 'px'
})
์์ ์ฝ๋๋ setTimeout()์ ์ฌ์ฉํ์ฌ ๋์ผํ ์ฝ๋๋ฅผ ์คํํ๋ ๊ฒ๊ณผ ๋งค์ฐ ์ ์ฌํฉ๋๋ค. ์ฌ์ฉ์๊ฐ ์ ์ํ ์ง์ฐ ์๊ฐ ์ดํ์ ํธ์ถํ๋ ๊ฒ์ด ์๋ ๋ค์ ์ฌ์ฉ ๊ฐ๋ฅํ ํ๋ฉด์ ๋ฆฌํ์ธํธํ ๋ ์ฝ๋๋ฅผ ํธ์ถํฉ๋๋ค. (์ผ๋ฐ์ ์ผ๋ก 60fps, ํ๋ฉด ์๋ก ๊ณ ์นจ ๋น๋์ ๋ฐ๋ผ ์ฝ 16.7 ๋ฐ๋ฆฌ ์ด) ์ ํํ ์์น๋ ๋ณ๋์ด ๋ ์ ์์ผ๋ฉฐ ์ค์ํ์ง๋ ์์ต๋๋ค. ์ฌ๊ธฐ์ ์ค์ํ๊ฒ ๋ด์ผํ ๋ถ๋ถ์ ๋ธ๋ผ์ฐ์ ๊ฐ ์๋ ์ด์ ํ๋ฉด์ ๋ณ๊ฒฝํ ์ค๋น๊ฐ ๋์์ ๋๋ง ๋ธ๋ผ์ฐ์ ๊ฐ ์ง๋ฅ์ ์ผ๋ก ์ฝ๋๋ฅผ ํธ์ถํ๋ค๋ ๊ฒ์ ๋๋ค.
requestAnimationFrame()์ ํ ๋ฒ ํธ์ถํ๋ฉด ๋๋ถ๋ถ ๋ฌด์๋ฏธํด์ง๋๋ค. ์ด๊ฒ์ "์ฌ๊ท์ ์ด๊ฒ" ํธ์ถ๋ ๋๋ง๋ค ํ๋ ์๋ณ๋ก ์ํ๋ ์ ๋๋ฉ์ด์ ํ๋ ์์ ์์ฑํ ๋ ๋น๋ก์ ์๋ฏธ๊ฐ ์์ด์ง๋๋ค. ๊ฐ ํ๋ ์์ ๋ธ๋ผ์ฐ์ ๊ฐ ์ค๋น๋ ๋๋ง ํธ์ถ๋ฉ๋๋ค. ์ด๊ฒ์ ์ ๋๋ฉ์ด์ ๊ด๋ จ ์ฝ๋๋ฅผ ํจ์จ์ ์ผ๋ก ์ฒ๋ฆฌํ ๋ requestAnimationFrame ()์ด setTimeout ๋๋ setInterval๋ณด๋ค ์ฐ์ํ ๋ฐฉ๋ฒ์ ๋๋ค. requestAnimationFrame()์ ์ฌ์ฉํ์ฌ ํ๋ฉด์์ DIV๋ฅผ ํ ๋ฒ์ 5ํฝ์ ์ฉ ์ด๋ํ๋ ์ด๊ธฐ ์์ ๋ฅผ ๋ค์ ์์ฑํฉ๋๋ค.
var adiv = document.getElementById('mydiv')
var leftpos = 0
function movediv(timestamp){
leftpos += 5
adiv.style.left = leftpos + 'px'
requestAnimationFrame(movediv) // call requestAnimationFrame again to animate next frame
}
requestAnimationFrame(movediv) // call requestAnimationFrame and pass into it animation function
์์ ์ฝ๋๋ requestAnimationFrame()์ ์ฌ์ฉํ์ฌ ํจ์ ๋ด์์ ์ ๋๋ฉ์ด์ ์ ์ ์ํ ๋ค์ requestAnimationFrame()์ ํตํด ์ค์ค๋ก ์ฌ๊ท์ ์ผ๋ก ํธ์ถํ์ฌ ์ ๋๋ฉ์ด์ ์ ๊ฐ ํ๋ ์์ ์์ฑํ๊ธฐ ์ํ ๊ธฐ๋ณธ blueprint๋ฅผ ๋ณด์ฌ์ค๋ค. ์ ๋๋ฉ์ด์ ์ ์์ํ๋ ค๋ฉด, ํด๋น ํจ์๋ฅผ ๋งค๊ฐ ๋ณ์๋ก ์ฌ์ฉํ์ฌ ํจ์ ๋ฐ์์ requestAnimationFrame()์ ํธ์ถํฉ๋๋ค.
๋ฐ๋ผ์ requestAnimationFrame()์ ์ฌ์ฉํ์ฌ ๋ฐ๋ณต์ ์ผ๋ก ์ ๋๋ฉ์ด์ ํจ์๋ฅผ ํธ์ถํ๋ ๊ฒ๋งํผ ๊ฐ๋จํ์ง๋ง ๋๋ถ๋ถ์ ์ ๋๋ฉ์ด์ ์ ํน์ ๊ธฐ๋ฅ์ ์ํํ ํ ์ด๋ ์์ ์์ ๋ฉ์ถฐ์ผ ํ ๋๊ฐ ๊น๋ค๋กญ์ต๋๋ค. ์์ DIV๋ฅผ ์์ง์ด๋ ์๋ฅผ ๋ฐํ์ผ๋ก ์ค์ ๋ก ๊ตฌํํ ๋ฒํ ์๋๋ฆฌ์ค๋ฅผ 'DIV๋ฅผ 2์ด ์ ๋์ ์๊ฐ ๋์ 400ํฝ์ ์ค๋ฅธ์ชฝ์ผ๋ก ์ด๋'์ผ๋ก ์ ์ํด๋ณด๊ฒ ์ต๋๋ค. requestAnimationFrame()์ ์ฌ์ฉํ์ฌ ์์ ์ ์ํํ๋ ค๋ฉด ์ฝ๋ฐฑ ํจ์์ ์ ๋ฌ๋ timestamp ๋งค๊ฐ ๋ณ์๋ฅผ ํ์ฉํ ์ ์์ต๋๋ค. ์์ movediv ์ฝ๋๋ฅผ ๋ค์ ์์ ํ์ฌ DIV๋ฅผ ์ผ์ ์๊ฐ ๋์ ์ผ์ ํ ๊ฑฐ๋ฆฌ๋งํผ ์ด๋ ์ํค๋ฉด ์ด๊ฒ์ด ์ด๋ป๊ฒ ์๋ํ๋์ง ๋ณผ ์ ์์ต๋๋ค.
var adiv = document.getElementById('mydiv')
var starttime
function moveit(timestamp, el, dist, duration){
//if browser doesn't support requestAnimationFrame, generate our own timestamp using Date:
var timestamp = timestamp || new Date().getTime()
var runtime = timestamp - starttime
var progress = runtime / duration
progress = Math.min(progress, 1)
el.style.left = (dist * progress).toFixed(2) + 'px'
if (runtime < duration){ // if duration not met yet
requestAnimationFrame(function(timestamp){ // call requestAnimationFrame again with parameters
moveit(timestamp, el, dist, duration)
})
}
}
requestAnimationFrame(function(timestamp){
starttime = timestamp || new Date().getTime() //if browser doesn't support requestAnimationFrame, generate our own timestamp using Date
moveit(timestamp, adiv, 400, 2000) // 400px over 1 second
})
์ด๊ฒ์ด ์ด๋ป๊ฒ ์คํ๋๋์ง ์ดํด๋ณด๊ฒ ์ต๋๋ค.
-
์ ๋๋ฉ์ด์ ์ด ์คํ๋๊ธฐ ์ง์ ์ requestAnimationFrame์ timestamp ๋งค๊ฐ ๋ณ์๋ฅผ ์ฌ์ฉํ์ฌ starttime ๋ณ์๋ฅผ ํ์ฌ ์๊ฐ์ผ๋ก ์ค์ ํ๊ฑฐ๋ requestAnimationFrame์ด ์ง์๋์ง ์๋ ๊ฒฝ์ฐ ์ ํ์ฑ์ด ๋จ์ด์ง๋ new Date().getTime()์ ๋์ ์ฌ์ฉํฉ๋๋ค. ์ ๋๋ฉ์ด์ ์ด ์คํ๋๊ธฐ ์ง์ ์ requestAnimationFrame์ ์ฝ๋ฐฑ ํจ์์ ์ฒซ ๋ฒ์งธ ๋งค๊ฐ๋ณ์์ธ ์๋์ผ๋ก ์ ๋ฌ๋ ๊ฐ์ด ํ์ฌ ์๊ฐ์ ๋ฐ๋ฆฌ ์ด ๋จ์๋ก ์ ํํ๊ฒ ํ์ํฉ๋๋ค. (์ ํํ 5๋ง์ดํฌ๋ก ์ด). ์ด๋ฅผ ํตํด ์ ๋๋ฉ์ด์ ์ด ์ธ์ ์์๋์๋์ง ์ ์ ์์ต๋๋ค.
-
์ ๋๋ฉ์ด์ ํจ์ moveit() ๋ด์์ ๋ณ์ timestamp๋ฅผ ์ฌ์ฉํ์ฌ ํ์ฌ "ํ๋ ์"์ ํ์ฌ ์๊ฐ์ ์บก์ฒํฉ๋๋ค. ์ฐ๋ฆฌ๋ ์ ๋๋ฉ์ด์ ์์ ์์ ๊ณผ์ ์ฐจ์ด์ ์ ์ฌ์ฉํ์ฌ ํ์ฌ ์ ๋๋ฉ์ด์ ์ ์๋ "์ง์ "์ ํ์ ํ๊ณ ์ด ๊ฑฐ๋ฆฌ (์ฆ : 400ํฝ์ )์์ DIV์ ์์น๋ฅผ ๋ณ๊ฒฝํฉ๋๋ค.
ํ์ค requestAnimationFrame์ ์ด์์ ์ธ ์กฐ๊ฑด์์ ์ฝ 60fps (๋๋ 16.7ms๋ง๋ค ํ ๋ฒ)์์ ์ผ๋ฐ ๋ชจ๋ํฐ์ ์ฌ์ ๋น๋์ ๋๊ธฐํ๋์ด ์คํ๋ฉ๋๋ค. ์ ๋๋ฉ์ด์ ์ด ์ด๋น ๋ค๋ฅธ ํ๋ ์ (์ต๋ 60fps)์ ํ์๋ก ํ๊ฑฐ๋ ๊ฐ๋จํ ๋์ ์ฌ์ ๋น๋๋ฅผ ์๊ตฌํ์ง ์์ผ๋ฉด setTimeout() ๋ด requestAnimationFrame์ ํธ์ถํ์ฌ ๋๋ ค์ง ์ ์์ต๋๋ค.
์๋์ ๊ฐ์ ๋ฐฉ๋ฒ์ผ๋ก ์ ์ฉํ๋ฉด requestAnimationFrame์ ์ด์ ์ ๋๋ฆฌ๋ ๋์ ์ํ๋ ํ๋ ์ ์๋๋ฅผ ์ป์ ์ ์์ต๋๋ค
var adiv = document.getElementById('mydiv')
var leftpos = 0
var fps = 20
function movediv(timestamp){
setTimeout(function(){ //throttle requestAnimationFrame to 20fps
leftpos += 5
adiv.style.left = leftpos + 'px'
requestAnimationFrame(movediv)
}, 1000/fps)
}
requestAnimationFrame(movediv)
DIV๋ฅผ ์ํ์ผ๋ก ์์ง์ด๋ ์ด ๋ฒ์ ์์๋ ๋งค๋ฒ setTimeout () ๋ด์ requestAnimationFrame์ ํธ์ถํ์ฌ ์ด๋น ํ๋ ์์ ์ฝ 20๊ฐ๋ก ์กฐ์ ํฉ๋๋ค.
setTimeout/ setInterval๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก requestAnimationFrame ํธ์ถ์ ์ทจ์ ํ ์ ์์ผ๋ฉฐ ๋์ผํ ๋ฐฉ์์ผ๋ก ํธ์ถํ ์ ์์ต๋๋ค. requestAnimationFrame์ด ํธ์ถ๋๋ฉด ๋ณ์ ๋ด์์ ์บก์ณํ ๊ฐ์ธ ์ฝ๋ฐฑ ํจ์ ์คํ์ ์์ํ ๋์ ์์ ์ ๊ฐ์ cancelAnimationFrame()์ ์ ๋ฌํ์ฌ ์ฝ๋ฐฑ ์์ฒญ์ ์ทจ์ ํ๋ 0์ด ์๋ ์ ์๊ฐ ๋ฐํ๋ฉ๋๋ค.(requestAnimationFrame when called returns a non 0 integer that can be captured inside a variable and passed into its nemesis counterpart cancelAnimationFrame() to stop it from being invoked again) ์๋์ ์ฝ๋๋ cancelAnimationFrame์ ์ฌ์ฉํ์ฌ ์ฝ๋ฐฑ์ ์ค์งํ๊ธฐ ์ํด requestAnimationFrame์ timestamp ๋งค๊ฐ ๋ณ์ ๊ฐ์ 2์ด ๋์ ๊ธฐ๋กํ๋ ์ฝ๋์ ๋๋ค.
var reqanimationreference
function logtimestamp(timestamp){
console.log(timestamp)
reqanimationreference = requestAnimationFrame(logtimestamp)
}
requestAnimationFrame(logtimestamp)
setTimeout(function(){ // cancel requestAnimationFrame after 2 seconds
cancelAnimationFrame(reqanimationreference)
}, 2000)
๋ฐ๋ชจ์ ๋ํ ์ค๋ช ๋ค์์ ๋ง์ฐ์ค๊ฐ ๋ถ๋ชจ ์ปจํ ์ด๋(onmouseenter)์ ๋ค์ด๊ฐ ๋ requestAnimationFrame์ ์ฌ์ฉํ์ฌ DIV์ ๋๋น๋ฅผ ๊ณ์ ๋ณ๊ฒฝํ๊ณ onmouseleave๋ฅผ ์ทจ์๋ฅผ ํ๋ ์ ๊ตํ ์์ ์ ๋๋ค.
requestAnimationFrame()์ ์ค์ ๋ก ๋ชฉ์ ๊ณผ ๊ณตํต ํจํด์ ์ดํดํ๋ฉด ๊ฐ๋ ๊ณผ ๊ตฌํ์ด ๋งค์ฐ ๊ฐ๋จํฉ๋๋ค. jQuery 3.0๊ณผ ๊ฐ์ ๋ง์ ํ๋ ์ ์ํฌ๋ requestAnimationFrame()์ ๋ชจ๋ ์ ๋๋ฉ์ด์ ๊ด๋ จ ํจ์์ ๋ด๋ถ์ ์ผ๋ก ํ์ฉํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ด ๋ฉ์๋๊ฐ ๊ธฐ๋ณธ์ ์ผ๋ก ์๋ํ๋ ๋ฐฉ์์ ์ดํดํ๋ฉด ๋ชจ๋ JavaScript ํ๊ฒฝ์์์ด ๋ฉ์๋๋ฅผ ํ์ฉํ ์ ์์ต๋๋ค.