|
@@ -160,47 +160,56 @@ namespace display {
|
|
|
export class TrackProgressController {
|
|
|
totalBar: HTMLElement;
|
|
|
intervalBar: HTMLElement;
|
|
|
- listener: ((event: AnimationEvent) => void) | null;
|
|
|
+ listener: ((event: AnimationPlaybackEvent) => void) | null;
|
|
|
|
|
|
- constructor(private element: HTMLElement, lines: level.Line[]) {
|
|
|
+ constructor(private element: HTMLElement, private lines: level.Line[]) {
|
|
|
this.totalBar = util.getElement(element, '.total .shade');
|
|
|
this.intervalBar = util.getElement(element, '.interval .shade');
|
|
|
this.listener = null;
|
|
|
+ }
|
|
|
|
|
|
- let totalDuration = lines[lines.length - 1].end;
|
|
|
- this.totalBar.style.animationName = 'progress';
|
|
|
- this.totalBar.style.animationDuration = totalDuration + 's';
|
|
|
+ start(start: number = 0): void {
|
|
|
+ this.clearAnimations();
|
|
|
+ const end = this.lines[this.lines.length - 1].end!;
|
|
|
+ const progress = start / end;
|
|
|
+ this.totalBar.animate({ width: [`${progress * 100}%`, '100%'] }, {
|
|
|
+ duration: (end - start) * 1000
|
|
|
+ });
|
|
|
|
|
|
- let names = lines.map(line => 'progress').join(',');
|
|
|
- let delays = lines.map(line => line.start + 's').join(',');
|
|
|
- let durations = lines.map(line => (line.end! - line.start!) + 's').join(',');
|
|
|
- this.intervalBar.style.animationName = names;
|
|
|
- this.intervalBar.style.animationDelay = delays;
|
|
|
- this.intervalBar.style.animationDuration = durations;
|
|
|
+ for (const line of this.lines) {
|
|
|
+ if (line.end! <= start) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ const segmentStart = Math.max(line.start!, start);
|
|
|
+ const segmentLength = line.end! - segmentStart;
|
|
|
+ const fullSegmentLength = line.end! - line.start!;
|
|
|
+ const progress = 1 - segmentLength / fullSegmentLength;
|
|
|
+ const animation = this.intervalBar.animate({ width: [`${progress * 100}%`, '100%'] }, {
|
|
|
+ delay: (segmentStart - start) * 1000,
|
|
|
+ duration: segmentLength * 1000,
|
|
|
+ });
|
|
|
+ if (this.listener) {
|
|
|
+ animation.addEventListener('finish', this.listener);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- start(): void {
|
|
|
- this.intervalBar.style.width = '100%';
|
|
|
- this.totalBar.style.width = '100%';
|
|
|
-
|
|
|
- this.intervalBar.style.animationPlayState = 'running';
|
|
|
- this.totalBar.style.animationPlayState = 'running';
|
|
|
+ pause(): void {
|
|
|
+ this.totalBar.getAnimations().forEach(anim => anim.pause());
|
|
|
+ this.intervalBar.getAnimations().forEach(anim => anim.pause());
|
|
|
}
|
|
|
|
|
|
- setListener(func: (event: AnimationEvent) => void): void {
|
|
|
- if (this.listener) {
|
|
|
- this.intervalBar.removeEventListener('animationend', func);
|
|
|
- }
|
|
|
- this.intervalBar.addEventListener('animationend', func);
|
|
|
+ setListener(func: (event: AnimationPlaybackEvent) => void): void {
|
|
|
this.listener = func;
|
|
|
}
|
|
|
|
|
|
destroy(): void {
|
|
|
- if (this.listener) {
|
|
|
- this.intervalBar.removeEventListener('animationend', this.listener);
|
|
|
- }
|
|
|
- this.intervalBar.style.animationName = '';
|
|
|
- this.totalBar.style.animationName = '';
|
|
|
+ this.clearAnimations();
|
|
|
+ }
|
|
|
+
|
|
|
+ private clearAnimations() {
|
|
|
+ this.totalBar.getAnimations().forEach(anim => anim.cancel());
|
|
|
+ this.intervalBar.getAnimations().forEach(anim => anim.cancel());
|
|
|
}
|
|
|
}
|
|
|
|