UI: Simplify Animation class
The Animation class had too much complexity and IMHO too hard to read:
- The running state is superfluous, it can be inferred by the
start/end times. Superfluous state is unnecessary.
- Nothing was using the default 0 argument for start()
- The raf being an inner lambda was quite hard to follow.
- performance.now() is preferrable for animations vs Date.now()
That is what is passed as argument to RAF.
Change-Id: Idfca10e751f6a11ee5bb57d24b2e48a807aada81
diff --git a/ui/src/frontend/animation.ts b/ui/src/frontend/animation.ts
index c91ad99..040d936 100644
--- a/ui/src/frontend/animation.ts
+++ b/ui/src/frontend/animation.ts
@@ -13,54 +13,41 @@
// limitations under the License.
export class Animation {
- private running = false;
- private runningStartedMs = 0;
- private end = Infinity;
- private requestedAnimationFrame = 0;
+ private startMs = 0;
+ private endMs = 0;
+ private lastFrameMs = 0;
+ private rafId = 0;
constructor(private onAnimationStep: (timeSinceLastMs: number) => void) {}
- start(durationMs?: number) {
- if (durationMs !== undefined) {
- this.end = Date.now() + durationMs;
+ start(durationMs: number) {
+ const nowMs = performance.now();
+
+ // If the animation is already happening, just update its end time.
+ if (nowMs <= this.endMs) {
+ this.endMs = nowMs + durationMs;
+ return;
}
- this.run();
+ this.lastFrameMs = 0;
+ this.startMs = nowMs;
+ this.endMs = nowMs + durationMs;
+ this.rafId = requestAnimationFrame(this.onAnimationFrame.bind(this));
}
stop() {
- this.running = false;
- cancelAnimationFrame(this.requestedAnimationFrame);
+ this.endMs = 0;
+ cancelAnimationFrame(this.rafId);
}
- getStartTimeMs(): number {
- return this.runningStartedMs;
+ get startTimeMs(): number {
+ return this.startMs;
}
- private run() {
- if (this.running) {
- return;
+ private onAnimationFrame(nowMs: number) {
+ if (nowMs < this.endMs) {
+ this.rafId = requestAnimationFrame(this.onAnimationFrame.bind(this));
}
- let lastFrameTimeMs = 0;
-
- const raf = (timestampMs: number) => {
- if (!lastFrameTimeMs) {
- lastFrameTimeMs = timestampMs;
- }
- this.onAnimationStep(timestampMs - lastFrameTimeMs);
- lastFrameTimeMs = timestampMs;
-
- if (this.running) {
- if (Date.now() < this.end) {
- this.requestedAnimationFrame = requestAnimationFrame(raf);
- } else {
- this.running = false;
- }
- }
- };
-
- this.running = true;
- this.runningStartedMs = Date.now();
-
- requestAnimationFrame(raf);
+ this.onAnimationStep(nowMs - (this.lastFrameMs || nowMs));
+ this.lastFrameMs = nowMs;
}
-}
\ No newline at end of file
+}