Hilo/docs/api-zh/code/util/Ticker.js
2018-04-19 15:39:32 +08:00

214 lines
5.7 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Hilo
* Copyright 2015 alibaba.com
* Licensed under the MIT License
*/
/**
* @class Ticker是一个定时器类。它可以按指定帧率重复运行从而按计划执行代码。
* @param {Number} fps 指定定时器的运行帧率。默认60。
* @module hilo/util/Ticker
* @requires hilo/core/Class
* @requires hilo/util/browser
*/
var Ticker = Class.create(/** @lends Ticker.prototype */{
constructor: function(fps){
this._targetFPS = fps || 60;
this._interval = 1000 / this._targetFPS;
this._tickers = [];
},
_paused: false,
_targetFPS: 0,
_interval: 0,
_intervalId: null,
_tickers: null,
_lastTime: 0,
_tickCount: 0,
_tickTime: 0,
_measuredFPS: 0,
/**
* 启动定时器。
* @param {Boolean} userRAF 是否使用requestAnimationFrame默认为true。
*/
start: function(useRAF){
if(useRAF === undefined){
useRAF = true;
}
if(this._intervalId) return;
this._lastTime = +new Date();
var self = this, interval = this._interval,
raf = window.requestAnimationFrame ||
window[browser.jsVendor + 'RequestAnimationFrame'];
var runLoop;
if(useRAF && raf && interval < 17){
this._useRAF = true;
runLoop = function(){
self._intervalId = raf(runLoop);
self._tick();
};
}else{
runLoop = function(){
self._intervalId = setTimeout(runLoop, interval);
self._tick();
};
}
this._paused = false;
runLoop();
},
/**
* 停止定时器。
*/
stop: function(){
if(this._useRAF){
var cancelRAF = window.cancelAnimationFrame ||
window[browser.jsVendor + 'CancelAnimationFrame'];
cancelRAF(this._intervalId);
}
else{
clearTimeout(this._intervalId);
}
this._intervalId = null;
this._lastTime = 0;
this._paused = true;
},
/**
* 暂停定时器。
*/
pause: function(){
this._paused = true;
},
/**
* 恢复定时器。
*/
resume: function(){
this._paused = false;
},
/**
* @private
*/
_tick: function(){
if(this._paused) return;
var startTime = +new Date(),
deltaTime = startTime - this._lastTime,
tickers = this._tickers;
//calculates the real fps
if(++this._tickCount >= this._targetFPS){
this._measuredFPS = 1000 / (this._tickTime / this._tickCount) + 0.5 >> 0;
this._tickCount = 0;
this._tickTime = 0;
}else{
this._tickTime += startTime - this._lastTime;
}
this._lastTime = startTime;
var tickersCopy = tickers.slice(0);
for(var i = 0, len = tickersCopy.length; i < len; i++){
tickersCopy[i].tick(deltaTime);
}
},
/**
* 获得测定的运行时帧率。
*/
getMeasuredFPS: function(){
return Math.min(this._measuredFPS, this._targetFPS);
},
/**
* 添加定时器对象。定时器对象必须实现 tick 方法。
* @param {Object} tickObject 要添加的定时器对象。此对象必须包含 tick 方法。
*/
addTick: function(tickObject){
if(!tickObject || typeof(tickObject.tick) != 'function'){
throw new Error('Ticker: The tick object must implement the tick method.');
}
this._tickers.push(tickObject);
},
/**
* 删除定时器对象。
* @param {Object} tickObject 要删除的定时器对象。
*/
removeTick: function(tickObject){
var tickers = this._tickers,
index = tickers.indexOf(tickObject);
if(index >= 0){
tickers.splice(index, 1);
}
},
/**
* 下次tick时回调
* @param {Function} callback
* @return {tickObj}
*/
nextTick:function(callback){
var that = this;
var tickObj = {
tick:function(dt){
that.removeTick(tickObj);
callback();
}
};
that.addTick(tickObj);
return tickObj;
},
/**
* 延迟指定的时间后调用回调, 类似setTimeout
* @param {Function} callback
* @param {Number} duration 延迟的毫秒数
* @return {tickObj}
*/
timeout:function(callback, duration){
var that = this;
var targetTime = new Date().getTime() + duration;
var tickObj = {
tick:function(){
var nowTime = new Date().getTime();
var dt = nowTime - targetTime;
if(dt >= 0){
that.removeTick(tickObj);
callback();
}
}
};
that.addTick(tickObj);
return tickObj;
},
/**
* 指定的时间周期来调用函数, 类似setInterval
* @param {Function} callback
* @param {Number} duration 时间周期,单位毫秒
* @return {tickObj}
*/
interval:function(callback, duration){
var that = this;
var targetTime = new Date().getTime() + duration;
var tickObj = {
tick:function(){
var nowTime = new Date().getTime();
var dt = nowTime - targetTime;
if(dt >= 0){
if(dt < duration){
nowTime -= dt;
}
targetTime = nowTime + duration;
callback();
}
}
};
that.addTick(tickObj);
return tickObj;
}
});