1 /** 2 * Hilo 3 * Copyright 2015 alibaba.com 4 * Licensed under the MIT License 5 */ 6 7 /** 8 * @language=en 9 * @class Ticker is a Timer. It can run the code at specified framerate. 10 * @param {Number} fps The fps of ticker. 11 * @module hilo/util/Ticker 12 * @requires hilo/core/Class 13 * @requires hilo/core/Hilo 14 */ 15 var Ticker = Class.create(/** @lends Ticker.prototype */{ 16 constructor: function(fps){ 17 this._targetFPS = fps || 30; 18 this._interval = 1000 / this._targetFPS; 19 this._tickers = []; 20 }, 21 22 _paused: false, 23 _targetFPS: 0, 24 _interval: 0, 25 _intervalId: null, 26 _tickers: null, 27 _lastTime: 0, 28 _tickCount: 0, 29 _tickTime: 0, 30 _measuredFPS: 0, 31 32 /** 33 * @language=en 34 * Start the ticker. 35 * @param {Boolean} userRAF Whether or not use requestAnimationFrame, default is not. 36 */ 37 start: function(useRAF){ 38 if(this._intervalId) return; 39 this._lastTime = +new Date(); 40 41 var self = this, interval = this._interval, 42 raf = window.requestAnimationFrame || 43 window[Hilo.browser.jsVendor + 'RequestAnimationFrame']; 44 45 if(useRAF && raf){ 46 var tick = function(){ 47 self._tick(); 48 } 49 var runLoop = function(){ 50 self._intervalId = setTimeout(runLoop, interval); 51 raf(tick); 52 }; 53 }else{ 54 runLoop = function(){ 55 self._intervalId = setTimeout(runLoop, interval); 56 self._tick(); 57 }; 58 } 59 60 runLoop(); 61 }, 62 63 /** 64 * @language=en 65 * Stop the ticker. 66 */ 67 stop: function(){ 68 clearTimeout(this._intervalId); 69 this._intervalId = null; 70 this._lastTime = 0; 71 }, 72 73 /** 74 * @language=en 75 * Pause the ticker. 76 */ 77 pause: function(){ 78 this._paused = true; 79 }, 80 81 /** 82 * @language=en 83 * Resume the ticker. 84 */ 85 resume: function(){ 86 this._paused = false; 87 }, 88 89 /** 90 * @private 91 */ 92 _tick: function(){ 93 if(this._paused) return; 94 var startTime = +new Date(), 95 deltaTime = startTime - this._lastTime, 96 tickers = this._tickers; 97 98 //calculates the real fps 99 if(++this._tickCount >= this._targetFPS){ 100 this._measuredFPS = 1000 / (this._tickTime / this._tickCount) + 0.5 >> 0; 101 this._tickCount = 0; 102 this._tickTime = 0; 103 }else{ 104 this._tickTime += startTime - this._lastTime; 105 } 106 this._lastTime = startTime; 107 108 for(var i = 0, len = tickers.length; i < len; i++){ 109 tickers[i].tick(deltaTime); 110 } 111 }, 112 113 /** 114 * @language=en 115 * Get the fps. 116 */ 117 getMeasuredFPS: function(){ 118 return this._measuredFPS; 119 }, 120 121 /** 122 * @language=en 123 * Add tickObject. The tickObject must implement the tick method. 124 * @param {Object} tickObject The tickObject to add.It must implement the tick method. 125 */ 126 addTick: function(tickObject){ 127 if(!tickObject || typeof(tickObject.tick) != 'function'){ 128 throw new Error('Ticker: The tick object must implement the tick method.'); 129 } 130 this._tickers.push(tickObject); 131 }, 132 133 /** 134 * @language=en 135 * Remove the tickObject 136 * @param {Object} tickObject The tickObject to remove. 137 */ 138 removeTick: function(tickObject){ 139 var tickers = this._tickers, 140 index = tickers.indexOf(tickObject); 141 if(index >= 0){ 142 tickers.splice(index, 1); 143 } 144 } 145 146 });