1、小談 requestAnimationFrame:css
提及 requestAnimationFrame,咱們先看幅圖:html
至關一部分的瀏覽器的顯示頻率是16.7ms
, 就是上圖第一行的節奏,表現就是「我和你一步兩步三步四步往前走……」。若是咱們火力搞猛一點,例如搞個10ms
setTimeout
,就會是下面一行的模樣——每第三個圖形都沒法繪製(紅色箭頭指示),表現就是「我和你一步兩步 坑四步往前走……」。css3
想象國慶北京高速,最多每16.7s
經過一輛車,結果,忽然插入一批 setTimeout
的軍車,強行要10s
經過。顯然,這是超負荷的,要想順利進行,只能讓第三輛車直接消失(正如顯示繪製第三幀的丟失)。然,這是不現實的,因而就有了會堵車!git
一樣的,顯示器16.7ms
刷新間隔以前發生了其餘繪製請求(setTimeout
),致使全部第三幀丟失,繼而致使動畫斷續顯示(堵車的感受),這就是過分繪製帶來的問題。不只如此,這種計時器頻率的下降也會對電池使用壽命形成負面影響,並會下降其餘應用的性能。github
這也是爲什麼setTimeout
的定時器值推薦最小使用16.7ms
的緣由(16.7 = 1000 / 60, 即每秒60幀)。web
而我requestAnimationFrame
就是爲了這個而出現的。它所作的事情很簡單,跟着瀏覽器的繪製走,若是瀏覽設備繪製間隔是16.7ms
,那我就這個間隔繪製;若是瀏覽設備繪製間隔是10ms
, 我就10ms
繪製。這樣就不會存在過分繪製的問題,動畫不會掉幀,天然流暢的說~~canvas
內部是這麼運做的:
瀏覽器(如頁面)每次要洗澡(重繪),就會通知我(requestAnimationFrame
):小丸子,我要洗澡了,你能夠跟我一塊兒洗哦!promise
這是資源很是高效的一種利用方式。怎麼講呢?瀏覽器
setTimeout
貌似是多個獨立繪製。2、兼容性:異步
因此,requestAnimationFrame 一個簡單的兼容性代碼以下:
(function() { var lastTime = 0; var vendors = ['webkit', 'moz']; for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame']; window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] || // Webkit中此取消方法的名字變了 window[vendors[x] + 'CancelRequestAnimationFrame']; } if (!window.requestAnimationFrame) { window.requestAnimationFrame = function(callback, element) { var currTime = new Date().getTime(); var timeToCall = Math.max(0, 16.7 - (currTime - lastTime)); var id = window.setTimeout(function() { callback(currTime + timeToCall); }, timeToCall); lastTime = currTime + timeToCall; return id; }; } if (!window.cancelAnimationFrame) { window.cancelAnimationFrame = function(id) { clearTimeout(id); }; } }());
3、動畫效果:
css3 能夠實現不少動畫效果,貝塞爾曲線是一個標準3次方曲線(詳見:貝塞爾曲線與CSS3動畫、SVG和canvas的基情),所以,只能是:Linear
, Sine
, Quad
, Cubic
, Expo
等,以下圖:
但 css3 對於 Back
, Bounce
等緩動則只可觀望而不可褻玩焉。
先看一個效果:小球彈起落地效果 (此例結合了 Tweenjs 庫)
動畫核心代碼以下:
funFall = function() { var start = 0, during = 100; var _run = function() { start++; var top = Tween.Bounce.easeOut(start, objBall.top, 500 - objBall.top, during); ball.css("top", top); shadowWithBall(top); // 投影跟隨小球的動 if (start < during) requestAnimationFrame(_run); }; _run(); };
4、深究 requestAnimationFrame:
事件循環和任務隊列機制裏邊,牽扯到 setTimeout
,在討論瀏覽器刷新頻率的時候,常常將 setTimeout
和 requestAnimationFarme
做比較。
那麼,requestAnimationFarme
是否也屬於異步任務,若是是的話,是屬於macro-task
仍是micro-task
?
關於macro-task 和 micro-task:
一、macrotasks包含:主js、UI渲染、setTimeout、setInterval、setImmediate、requestAnimationFarme、I/O等
二、microtasks包含:process.nextTick、promise、Object.observe等
具體詳見:
從Promise來看JavaScript中的Event Loop、Tasks和Microtasks