Files
Eduardo Speroni 2aa6e9bf92 feat: support requestAnimationFrame (#8112)
* feat: support requestAnimationFrame

* add native helpers to measure time

* test(animation-frame): add tests

* chore: refactor animation-frame to its own module

* chore: fix tslint
2019-11-29 11:17:26 +02:00

63 lines
1.7 KiB
TypeScript

import { FPSCallback } from "../fps-meter/fps-native";
import { getTimeInFrameBase } from "./animation-native";
export interface FrameRequestCallback {
(time: number): void;
}
let animationId = 0;
let nextFrameAnimationCallbacks: { [key: string]: FrameRequestCallback } = {};
let shouldStop = true;
let inAnimationFrame = false;
let fpsCallback: FPSCallback;
let lastFrameTime = 0;
function getNewId() {
return animationId++;
}
function ensureNative() {
if (fpsCallback) {
return;
}
fpsCallback = new FPSCallback(doFrame);
}
function doFrame(currentTimeMillis: number) {
lastFrameTime = currentTimeMillis;
shouldStop = true;
const thisFrameCbs = nextFrameAnimationCallbacks;
nextFrameAnimationCallbacks = {};
inAnimationFrame = true;
for (const animationId in thisFrameCbs) {
if (thisFrameCbs[animationId]) {
thisFrameCbs[animationId](lastFrameTime);
}
}
inAnimationFrame = false;
if (shouldStop) {
fpsCallback.stop(); // TODO: check performance without stopping to allow consistent frame times
}
}
export function requestAnimationFrame(cb: FrameRequestCallback): number {
if (!inAnimationFrame) {
inAnimationFrame = true;
zonedCallback(cb)(getTimeInFrameBase()); // TODO: store and use lastFrameTime
inAnimationFrame = false;
return getNewId();
}
ensureNative();
const animId = getNewId();
nextFrameAnimationCallbacks[animId] = zonedCallback(cb) as FrameRequestCallback;
shouldStop = false;
fpsCallback.start();
return animId;
}
export function cancelAnimationFrame(id: number) {
delete nextFrameAnimationCallbacks[id];
}