requestAnimationFrame() ํด๋ฆฌํ
requestAnimationFrame()
๋?
requestAnimationFrame (์ดํ rAF)์ ๋ธ๋ผ์ฐ์ ์๊ฒ ์ํํ๊ธฐ๋ฅผ ์ํ๋ ์ ๋๋ฉ๋์ ์ ์๋ฆฌ๊ณ ๋ค์ ๋ฆฌํ์ธํธ๊ฐ ์งํ๋๊ธฐ ์ ์ ํด๋น ์ ๋๋ฉ์ด์ ์ ์ ๋ฐ์ดํธํ๋ ์ฝ๋ฐฑ ํจ์๋ฅผ ํธ์ถํ๋ค. ์ด ํจ์๋ ๋ฆฌํ์ธํธ ์ด์ ์ ์คํํ ์ฝ๋ฐฑ ํจ์๋ฅผ ์ธ์๋ก ๋ฐ๋๋ค.
let start = null;
const element = document.getElementById('SomeElementYouWantToAnimate');
element.style.position = 'absolute';
const step = timestamp => {
if (!start) start = timestamp;
const progress = timestamp - start;
element.style.left = Math.min(progress / 10, 200) + 'px';
if (progress < 2000) {
window.requestAnimationFrame(step);
}
}
window.requestAnimationFrame(step);
์ด ํจ์๋ ์ ์์ ์ฝ๋์ ๊ฐ์ด ์์๋ฅผ ์์ง์ด๊ฑฐ๋, ๋น๋๊ธฐ์ ์ธ ๋ฐ๋ณต์์ ์ ํ ๋์ ์ฌ์ฉํ๊ฒ ๋๋ค. ํ์ง๋ง ๊ตฌํ ๋ธ๋ผ์ฐ์ ์์๋ ์ด๋ฅผ ์ง์ํ์ง ์๊ธฐ ๋๋ฌธ์ ํด๋ฆฌํ๋ง์ด ํ์ํ๋ค. rAF์ ๋์์ ๋ํด ์กฐ๊ธ ๋ ํ์คํ๊ฒ ์ดํดํ๊ธฐ ์ํด ์ง์ ๋ง๋ค์ด ๋ณด์๋ค.
timestamp
window.requestAnimationFrame()
์ ์ธ์๋ก๋ ๋ค์ ๋ฆฌํ์ธํธ๋ฅผ ์ํ ์ ๋๋ฉ์ด์
์ ์
๋ฐ์ดํธํ ๋ ํธ์ถํ ์ฝ๋ฐฑํจ์๋ฅผ ๋ฐ๋๋ค. ์ด ์ฝ ๋ฐฑํจ์์๋ ํจ์๋ฅผ ์คํํ ๋ ์์ ์ ๋ํ๋ด๋ performance.now()
์ ๋ฐํ๊ฐ๊ณผ ์ ์ฌํ DOMHighResTimeStamp
๊ฐ ์ ๋ฌ๋๋ค.
(function(global){
var nowOffest = Date.now(); // ๋ธ๋ผ์ฐ์ ์ ์คํ์์
var timeStamp = function(){
// performance๊ฐ ์๋์ง ํ์ธ
if(global.performance &&
typeof global.performance.now &&
typeof global.performance.now === 'function'
){
return global.performance.now();
}
// fallback
return Date.now() - nowOffest;
}
})(window);
prefix
๋ชจ๋ ๋ธ๋ผ์ฐ์ ๋ค์ ๋๋ถ๋ถ raf๋ฅผ ์ง์ํ๋ค. ๋ฐ๋ผ์ ๋ธ๋ผ์ฐ์ ๋ณ๋ก ํ๋ฆฌํฝ์ค๊ฐ ๋ถ์ด์๋ ํจ์๋ค์ ๊ฐ์ธ์ฃผ๋๊ฒ์ผ๋ก ์ถฉ๋ถํ๋ค.
(function(global){
// timeStamp...
var prefix='';
if('mozRequestAnimationFrame' in global){
prefix = 'moz';
}else if ('webkitRequestAnimationFrame' in global){
prefix = 'webkit';
}
if(!!prefix){
global.requestAnimationFrame = function(callback){
return global[prefix + 'RequestAnimationFrame'](function(){
callback(timeStamp());
});
}
global.cancelAnimationFrame = global[prefix + 'CancelAnimationFrame'];
}
})(window);
raf๋ฅผ ์ง์ํ๊ณ ์์ง ์์ ๊ตฌํ ๋ธ๋ผ์ฐ์ ๋ค์ setTimeout()
ํจ์๋ฅผ ์ฌ์ฉํด ํด๋ฆฌํ๋งํ๋ค.
if(!!prefix){
// raf๋ฅผ ์ง์ํ๋๊ฒฝ์ฐ
}else{
var lastTime = Date.now(); // ํด๋ก์
global.requestAnimationFrame = function(callback){
var currentTime = Date.now();
var delay = lastTime - currentTime + 16;
if(delay < 0){
delay = 0;
}
lastTime = currentTime;
return setTimeout(function(){
lastTime = Date.now();
callback(timeStamp());
}, delay);
};
global.cancelAnimation = clearTimout;
}
๊ฒฐ๊ณผ
(function(global){
// timeStamp...
var nowOffest = Date.now(); // ๋ธ๋ผ์ฐ์ ์ ์คํ์์
var timeStamp = function(){
// performance๊ฐ ์๋์ง ํ์ธ
if(global.performance &&
typeof global.performance.now &&
typeof global.performance.now === 'function'
){
return global.performance.now();
}
// fallback
return Date.now() - nowOffest;
}
var prefix='';
if('mozRequestAnimationFrame' in global){
prefix = 'moz';
}else if ('webkitRequestAnimationFrame' in global){
prefix = 'webkit';
}
if(!!prefix){
global.requestAnimationFrame = function(callback){
return global[prefix + 'RequestAnimationFrame'](function(){
callback(timeStamp());
});
}
global.cancelAnimationFrame = global[prefix + 'CancelAnimationFrame'];
}else{
var lastTime = Date.now(); // ํด๋ก์
global.requestAnimationFrame = function(callback){
var currentTime = Date.now(),
delay = lastTime - currentTime + 16;
if(delay < 0){
delay = 0;
}
lastTime = currentTime;
return setTimeout(function(){
lastTime = Date.now();
callback(timeStamp());
}, delay);
};
global.cancelAnimation = clearTimout;
}
})(window);