blob: c91ad99dd8282053a5424be02b2b62c422447d75 [file] [log] [blame]
Michail Schwab405002c2018-07-26 13:19:10 -04001// Copyright (C) 2018 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15export class Animation {
16 private running = false;
17 private runningStartedMs = 0;
18 private end = Infinity;
19 private requestedAnimationFrame = 0;
20
21 constructor(private onAnimationStep: (timeSinceLastMs: number) => void) {}
22
23 start(durationMs?: number) {
24 if (durationMs !== undefined) {
25 this.end = Date.now() + durationMs;
26 }
27 this.run();
28 }
29
30 stop() {
31 this.running = false;
32 cancelAnimationFrame(this.requestedAnimationFrame);
33 }
34
35 getStartTimeMs(): number {
36 return this.runningStartedMs;
37 }
38
39 private run() {
40 if (this.running) {
41 return;
42 }
43 let lastFrameTimeMs = 0;
44
45 const raf = (timestampMs: number) => {
46 if (!lastFrameTimeMs) {
47 lastFrameTimeMs = timestampMs;
48 }
49 this.onAnimationStep(timestampMs - lastFrameTimeMs);
50 lastFrameTimeMs = timestampMs;
51
52 if (this.running) {
53 if (Date.now() < this.end) {
54 this.requestedAnimationFrame = requestAnimationFrame(raf);
55 } else {
56 this.running = false;
57 }
58 }
59 };
60
61 this.running = true;
62 this.runningStartedMs = Date.now();
63
64 requestAnimationFrame(raf);
65 }
66}