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

214 lines
5.6 KiB
JavaScript

/**
* Hilo
* Copyright 2015 alibaba.com
* Licensed under the MIT License
*/
/**
* @class Ticker is a Timer. It can run the code at specified framerate.
* @param {Number} fps The fps of ticker.Default is 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,
/**
* Start the ticker.
* @param {Boolean} userRAF Whether or not use requestAnimationFrame, default is 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 the ticker.
*/
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 the ticker.
*/
pause: function(){
this._paused = true;
},
/**
* Resume the ticker.
*/
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);
}
},
/**
* Get the fps.
*/
getMeasuredFPS: function(){
return Math.min(this._measuredFPS, this._targetFPS);
},
/**
* Add tickObject. The tickObject must implement the tick method.
* @param {Object} tickObject The tickObject to add.It must implement the tick method.
*/
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);
},
/**
* Remove the tickObject
* @param {Object} tickObject The tickObject to remove.
*/
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;
}
});