Javascript動畫(一)

killnger發表於2018-12-22

Javascript定時執行程式碼塊方式

number:setInterval(func, msec)

此方法是每隔一定的時間(msec引數值)呼叫一次傳給它的函式(func引數),若不主動呼叫clearInterval(number)取消定時器,則會一直執行下去。

function animate(){
	// 需執行的程式碼
}
// 每秒60幀速率執行
let timerId = setInterval(animate, 1000 / 60);
// 取消定時器
clearInterval(timerId)

number:setTimeout(func, msec)

此方法是在一定時間(msec引數)後,呼叫一次傳給它的函式(func引數),若需重複執行,則需在重複呼叫setTimeout

function animate(){
	let start = +new Date(), end;
	// 需執行的程式碼
	
	end = +new Date()
	// 重複執行
	setTimeout(animate, 1000 / 60 - (end - start));		// 做次時間上的補償,使之更接近1秒60幀的速率
}
animate()

提示: setInterval與setTimeout中的msec引數可不填寫或填寫不為正數的值,意思是使瀏覽器以它所允許的最小時間間隔來呼叫func函式。

HTML5 出的number:requestAnimationFrame(func)

setInterval與setTimeout都是開發者告訴瀏覽器,在某個大致的時間點上執行程式碼。若是在繪製動畫,我們其實並不清楚繪製下一幀的最佳時機,相反,瀏覽器肯定比我們更瞭解繪製下一幀動畫的最佳時機。
requestAnimationFrame為此而生!
瀏覽器會在最佳時機呼叫func函式,若需一直執行下去,則需在func內再次呼叫requestAnimationFrame(func)
,瀏覽器會給func傳遞一個從程式啟動(頁面載入)到呼叫func函式時的時間間隔(chrome瀏覽器)

let handleId = 0;
let lasttime = undefined;
// 瀏覽器會給函式傳遞一個從程式啟動(頁面載入)到呼叫animate函式時的時間間隔
function animate(time){
	if (lasttime === undefined) {		// 拋棄第一幀
		lasttime = time;
	} else {
		let dt = time - lasttime;	// 此幀距上一幀的時間間隔
		lasttime = time;
		// 需執行的程式碼
		
	}
	
	// 重複執行
	handleId  = requestAnimationFram(animate);		// 做次時間上的補償,使之更接近1秒60幀的速率
}
// 使瀏覽在最佳時機執行第一幀動畫
handleId  = requestAnimationFram(animate);

// ==== 取消 ====
cancelAnimationFrame(handleId);

提示: Chrome 瀏覽器呼叫動畫回撥函式的最大速率不超過每秒60次。

requestAnimationFrame的polyfill

(function (win) {
  'use strict';
  var startTime = +new Date();        //程式啟動時的時間點
  win.requestAnimationFrame = (function () {
    return win.requestAnimationFrame ||
      win.webkitRequestAnimationFrame ||
      win.mozRequestAnimationFrame ||
      win.msRequestAnimationFrame ||
      function (callback) {
        var self = this,
          start, finish;
        return win.setTimeout(function () {
          start = +new Date();
          callback(start - startTime);        //將程式執行的總時長返回給回撥函式
          finish = +new Date();
          self.timeout = 1000 / 60 - (finish - start);
        }, self.timeout);
      }
  })();

  win.cancelAnimationFrame = (function () {
    return win.cancelAnimationFrame ||
      win.webkitCancelAnimationFrame ||
      win.mozCancelAnimationFrame ||
      win.msCancelAnimationFrame ||
      function (id) {
        win.clearTimeout(id);
      }
  })();
})(window)
下一節:動起來了的小球

相關文章