This commit is contained in:
@@ -1,38 +1,70 @@
|
||||
import { playerConfig } from '../types';
|
||||
import { playerConfig, actionWithDelay } from '../types';
|
||||
|
||||
const FRAME_MS = 16;
|
||||
let _id = 1;
|
||||
const timerMap: Map<number, boolean> = new Map();
|
||||
export default class Timer {
|
||||
private actions: actionWithDelay[];
|
||||
private config: playerConfig;
|
||||
|
||||
export function later(
|
||||
cb: () => void,
|
||||
delayMs: number,
|
||||
config: playerConfig,
|
||||
): number {
|
||||
const now = performance.now();
|
||||
let lastStep = now;
|
||||
const id = _id++;
|
||||
timerMap.set(id, true);
|
||||
|
||||
function check(step: number) {
|
||||
if (!timerMap.has(id)) {
|
||||
return;
|
||||
}
|
||||
const stepDiff = step - lastStep;
|
||||
lastStep = step;
|
||||
delayMs -= config.speed * stepDiff;
|
||||
if (delayMs < FRAME_MS) {
|
||||
cb();
|
||||
clear(id);
|
||||
} else {
|
||||
requestAnimationFrame(check);
|
||||
}
|
||||
constructor(config: playerConfig, actions: actionWithDelay[] = []) {
|
||||
this.actions = actions;
|
||||
this.config = config;
|
||||
}
|
||||
/**
|
||||
* Add an action after the timer starts.
|
||||
* @param action
|
||||
*/
|
||||
public addAction(action: actionWithDelay) {
|
||||
const index = this.findActionIndex(action);
|
||||
this.actions.splice(index, 0, action);
|
||||
}
|
||||
/**
|
||||
* Add all actions before the timer starts
|
||||
* @param actions
|
||||
*/
|
||||
public addActions(actions: actionWithDelay[]) {
|
||||
this.actions.push(...actions);
|
||||
}
|
||||
|
||||
requestAnimationFrame(check);
|
||||
return id;
|
||||
}
|
||||
public start() {
|
||||
this.actions.sort((a1, a2) => a1.delay - a2.delay);
|
||||
let delayed = 0;
|
||||
const start = performance.now();
|
||||
const { actions, config } = this;
|
||||
function check(time: number) {
|
||||
delayed = time - start;
|
||||
while (actions.length) {
|
||||
const action = actions[0];
|
||||
const delayNeeded = action.delay / config.speed;
|
||||
if (delayed >= delayNeeded) {
|
||||
actions.shift();
|
||||
action.doAction();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (actions.length > 0) {
|
||||
requestAnimationFrame(check);
|
||||
}
|
||||
}
|
||||
requestAnimationFrame(check);
|
||||
}
|
||||
|
||||
export function clear(id: number) {
|
||||
timerMap.delete(id);
|
||||
public clear() {
|
||||
this.actions = [];
|
||||
}
|
||||
|
||||
private findActionIndex(action: actionWithDelay): number {
|
||||
let start = 0;
|
||||
let end = this.actions.length - 1;
|
||||
while (start <= end) {
|
||||
let mid = Math.floor((start + end) / 2);
|
||||
if (this.actions[mid].delay < action.delay) {
|
||||
start = mid + 1;
|
||||
} else if (this.actions[mid].delay > action.delay) {
|
||||
end = mid - 1;
|
||||
} else {
|
||||
return mid;
|
||||
}
|
||||
}
|
||||
return start;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user