mirror of
https://github.com/hiloteam/Hilo.git
synced 2025-12-08 20:35:59 +00:00
214 lines
5.7 KiB
JavaScript
214 lines
5.7 KiB
JavaScript
/**
|
||
* 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;
|
||
}
|
||
}); |