123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460 |
- class Ticker {
- static _ticker: Ticker = new Ticker();
- private _isPause: boolean = false;//暂停中
- _running: boolean = false; // 正在运行
- _systemTime: number = 0; // 系统时间
- _lastTime: number = 0; // 上次执行时间
- _timerId; // 计时器id
- _delay: number = 10; // 延时设定
- // _funcs: Array<Function> = []; // 钩子函数队列
- _tickFuncs: Array<ExecuteTick> = []; // 钩子函数队列//: {} Function
- _executeFuncs: Array<ExecuteValue> = []; // 定时执行函数队列,按执行时间升序排序
- /**暂停期间的时间 */
- private _pauseTime: number = 0;
- /**暂停开始时间 */
- private _pauseStartTime;
- constructor() {
- // console.error(" constructor _ticker ");
- }
- /**
- * 查找第一个大于目标值的值的下标
- * @param time
- */
- _searchIndex(time: number) {
- let funcs: Array<ExecuteValue> = this._executeFuncs;
- let low: number = 0;
- let high: number = funcs.length;
- let mid: number = 0;
- while (low < high) {
- mid = Math.floor(low + (high - low) / 2);
- if (time >= funcs[mid].time) {
- low = mid + 1;
- } else {
- high = mid - 1;
- }
- }
- return low;
- }
- /**
- * 注册钩子函数(每次tick执行)
- * @param func 执行函数
- */
- _register(func: Function, caller):string {
- for (let i = 0; i < this._tickFuncs.length; i++) {
- const element = this._tickFuncs[i];
- if (element.caller == caller && element.func == func) {
- console.error("重复的tick监听");
- return element.id;
- }
- }
-
- let id = Util.GetUUID(6);
-
-
- let value: ExecuteTick = { func: func, caller: caller, id: id };
- this._tickFuncs.push(value);
- return id;
- // if (!this._tickFuncs[caller]) {
- // this._tickFuncs[caller] = [];
- // }
- // let arr = this._tickFuncs[caller];
- // if (arr.indexOf(func)) {
- // console.error("重复监听:" + caller + " " + func);
- // return;
- // }
- // this._tickFuncs[caller].push(func);
- // if (this._tickFuncs.indexOf(func) > -1) {
- // return;
- // }
- // this._tickFuncs.push(func);
- }
- /**
- * 注册一个函数,在一段时间之后执行
- * @param func 执行函数
- * @param delay 延时
- * @param time 执行时系统时间
- * @param loop 循环次数
- */
- _registerDelay(func: Function, delay: number, time: number, loop: number, id: string, count: number) {
- //判断是否已经注册过
- // 先查找后插入
- let index: number = this._searchIndex(time);
- let value: ExecuteValue = { func: func, time: time, delay: delay, loop: loop, id: id, count: count };
- this._executeFuncs.splice(index, 0, value);
- }
- /**
- * 注册一个函数,在某个时间点执行
- * @param func 执行函数
- * @param time 执行时间
- */
- _registerTimer(func: Function, time: number) {
- // 先查找后插入
- let index: number = this._searchIndex(time);
- let id = Util.GetUUID(6);
- let value: ExecuteValue = { func: func, time: time, id: id, count: 0 };
- this._executeFuncs.splice(index, 0, value);
- return id;
- }
- /**
- * 移除tick函数
- * @param func 执行函数
- */
- _unregister(func: Function,caller) {
- this._tickFuncs.map((value: ExecuteTick, index: number) => {
- if (value.caller==caller && func === value.func) {
- this._tickFuncs.splice(index, 1);
- }
- });
- // for (let i = 0; i < this._tickFuncs.length; i++) {
- // const element = this._tickFuncs[i];
- // if (element.caller == caller && element.func == func) {
- // console.error("重复的tick监听");
- // return element.id;
- // }
- // }
-
- }
- /**
- * 移除tick函数
- * @param func 执行函数
- */
- _unregisterById(id) {
- this._tickFuncs.map((value: ExecuteTick, index: number) => {
- if (value.id == id) {
- this._tickFuncs.splice(index, 1);
- }
- });
- }
- // /**
- // * 移除钩子函数
- // * @param func 执行函数
- // */
- // _unregisterDelay (func: Function) {
- // this._executeFuncs.map((value: ExecuteValue, index: number) => {
- // if (func === value.func) {
- // this._executeFuncs.splice(index, 1);
- // }
- // });
- // }
- /**
- * 移除钩子函数
- * @param func 执行函数
- */
- _unregisterDelay(id: string) {
- if (id) {
- this._executeFuncs.map((value: ExecuteValue, index: number) => {
- if (id === value.id) {
- this._executeFuncs.splice(index, 1);
- }
- });
- }
- }
- _unregisterAll() {
- // this._funcs.map((value: Function, index: number) => {
- // this._funcs.splice(index, 1);
- // });
- this._tickFuncs = [];
- this._executeFuncs = [];
- // if (this._timerId) {
- // clearTimeout(this._timerId);
- // this._timerId = null;
- // }
- this._stop();
- }
- /**
- * 启动Ticker,并设置当前系统时间,通常与服务器时间同步
- * @param systemTime 系统时间
- */
- _start(systemTime: number = 0) {
- if (this._running) {
- return;
- }
- // console.error("ticker start");
- this._isPause = false;
- this._running = true;
- this._systemTime = systemTime;
- this._lastTime = new Date().getTime();
- this._pauseTime = 0;
- this._update();
- }
- /**
- * 链式执行定时器,钩子函数队列为每次调用必执行,定时执行函数队列为系统时间大于执行时间时调用并移出队列
- */
- _update() {
- if (!this._running) {
- return;
- }
- let currentTime: number = new Date().getTime();
- if (this._pauseTime) {
- currentTime -= this._pauseTime;
- // this._pauseTime = undefined;
- }
-
- let delay: number = currentTime - this._lastTime;
- this._systemTime += delay;
- // tick函数队列,依次执行即可
- this._tickFuncs.forEach((value: ExecuteTick) => {
- // value(delay);
- value.func.call(value.caller, delay*0.001);
- });
- this._executeFunc();
- this._lastTime = currentTime;
- this._timerId = setTimeout(this._update.bind(this), this._delay);
- // console.log("tick");
- }
- /**
- * 执行定时函数
- */
- _executeFunc() {
- // 取数组首项进行时间校验
- if (this._executeFuncs[0] && this._executeFuncs[0].time < this._systemTime) {
- // 取出数组首项并执行
- let value: ExecuteValue = this._executeFuncs.shift();
- value.func(++value.count);
- // 递归执行下一项
- this._executeFunc();
- // 判断重复执行次数
- if (value.hasOwnProperty('loop')) {
- if (value.loop > 0 && --value.loop === 0) {
- return;
- }
- // 计算下次执行时间,插入队列
- let fixTime: number =this._systemTime+value.delay;// value.time + value.delay;
- this._registerDelay(value.func, value.delay, fixTime, value.loop, value.id, value.count);
- }
- }
- }
- /**
- * 停止Ticker
- */
- _stop() {
- if (this._timerId) {
- // console.error("clearTimeout:"+this._timerId);
- clearTimeout(this._timerId);
- this._timerId = null;
- }
- this._running = false;
- }
- _pause() {
- if (!this._running) { return; }
- this._isPause = true;
- this._running = false;
- this._pauseStartTime = new Date().getTime();
- }
- _repause() {
- if (this._running) { return; }
- this._isPause = false;
- this._running = true;
- this._pauseTime += new Date().getTime() - this._pauseStartTime;
- this._update();
- }
- private _registerCount(call, count): number {
- let me = this;
- let realCount = 0
- let t = function () {
- if (me._isPause) { return; }
- realCount++;
- call(realCount);
- if (realCount >= count) {
- clearInterval(tid);
- }
- }
- let tid = setInterval(t, 1000)
- return tid;
- }
- private _unregistCount(id) {
- clearInterval(id);
- }
- /**
- * 公开的钩子函数注册方法
- * @param func 执行函数
- * @param func 调用者
- */
- static register(func: Function, caller): string {
-
- return this._ticker._register(func, caller);
- }
- /**
- * 公开的钩子函数移除方法
- * @param func 执行函数
- */
- static unregister(func: Function, caller) {
- this._ticker._unregister(func, caller);
- }
- /**
- * 公开的钩子函数移除方法
- * @param func 执行函数
- */
- static unregisterById(id: string) {
- this._ticker._unregisterById(id);
- }
- // /**
- // * 公开的钩子函数移除方法
- // * @param func 执行函数
- // */
- // static unregisterDelay (func: Function) {
- // this._ticker._unregisterDelay(func);
- // }
- /**
- * 公开的钩子函数移除方法
- * @param func 执行函数
- */
- static unregisterDelay(id: string) {
- this._ticker._unregisterDelay(id);
- }
- static unregisterAll() {
- this._ticker._unregisterAll();
- }
- /**
- * 公开的延时执行函数方法,用户可设置执行次数,loop为0时无限循环
- * @param func 执行函数
- * @param delay 延时毫秒
- * @param loop 循环次数
- */
- static registerDelay(func: Function, delay: number, loop: number = 1): string {
- let time: number = this._ticker._systemTime + delay;
- let id = Util.GetUUID(6);
- this._ticker._registerDelay(func, delay, time, loop, id, 0);
- return id
- }
- /**
- * 公开的定时执行函数方法
- * @param func 执行函数
- * @param time 执行时间
- */
- static registerTimer(func: Function, time: number) {
- this._ticker._registerTimer(func, time);
- }
- public static registerCount(call, count): number {
- return this._ticker._registerCount(call,count);
- }
- public static unregistCount(id) {
- this._ticker._unregistCount(id);
- }
- /**
- * 公开的启动方法
- * @param systemTime 系统时间如:new Date().getTime()
- */
- static start(systemTime: number = 0) {
- // console.log("Tick->start:"+DateTime.formatDate());
- this._ticker._start(systemTime);
- }
- /**
- * 公开的停止方法:只是暂停调用。重新开始后,会全部调用停用的次数。
- * 需要移除所有监听,使用:unregisterAll
- */
- static stop() {
- // console.log("Tick->stop:"+DateTime.formatDate());
- this._ticker._stop();
- }
- static pause() {
- this._ticker._pause();
- }
- static resume() {
- this._ticker._repause();
- }
- static tooglePause() {
- if (this._ticker._isPause) {
- this.resume();
- } else {
- this.pause();
- }
- }
- static get isPause(): boolean {
- return this._ticker._isPause;
- }
- /**
- * 系统时间
- */
- static get systemTime(): number {
- return this._ticker._systemTime;
- }
- /**
- * 正在运行
- */
- static get running(): boolean {
- return this._ticker._running;
- }
- }
- interface ExecuteValue {
- id: string;
- func: Function;
- time: number;
- delay?: number;
- loop?: number;
- count: number;
- }
- interface ExecuteTick {
- id: string;
- func: Function;
- caller;
- // dt: number;
- // sumTime:number
- }
- (<any>window).Ticker = Ticker;
|