Mercurial > hg > ugly-duckling
changeset 397:308ea1c2612e
Introduce a render loop service / singleton for work which needs to be animated with the play position. Use it for animating the cross-high. Much dupe with the live-play-head, which should be refactored.
author | Lucas Thompson <dev@lucas.im> |
---|---|
date | Fri, 02 Jun 2017 16:47:38 +0100 |
parents | 3eab26a629e1 |
children | 75cb17f28277 |
files | src/app/app.module.ts src/app/services/render-loop/render-loop.service.ts src/app/visualisations/cross-hair-inspector.component.ts src/app/visualisations/waves-base.component.ts |
diffstat | 4 files changed, 72 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/src/app/app.module.ts Thu Jun 01 23:04:39 2017 +0100 +++ b/src/app/app.module.ts Fri Jun 02 16:47:38 2017 +0100 @@ -38,6 +38,7 @@ import {GridComponent} from './visualisations/grid/grid.component'; import {VerticalScaleComponent} from './visualisations/vertical-scale.component'; import {CrossHairInspectorComponent} from './visualisations/cross-hair-inspector.component'; +import {RenderLoopService} from './services/render-loop/render-loop.service'; export function createAudioContext(): AudioContext { return new ( @@ -151,7 +152,8 @@ {provide: 'PiperRepoUri', useValue: 'assets/remote-extractors.json'}, {provide: 'UrlResourceLifetimeManager', useFactory: createUrlResourceManager}, {provide: 'ResourceReader', useFactory: createResourceReader}, - {provide: 'DimensionObservable', useFactory: createWindowDimensionObservable} + {provide: 'DimensionObservable', useFactory: createWindowDimensionObservable}, + RenderLoopService ], bootstrap: [AppComponent] })
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/app/services/render-loop/render-loop.service.ts Fri Jun 02 16:47:38 2017 +0100 @@ -0,0 +1,55 @@ +/** + * Created by lucast on 02/06/2017. + */ +import {Injectable, NgZone} from '@angular/core'; +import {AudioPlayerService} from '../audio-player/audio-player.service'; +import {Subscription} from 'rxjs/Subscription'; +import {OnSeekHandler} from '../../playhead/PlayHeadHelpers'; + +@Injectable() +export class RenderLoopService { + private playingStateSubscription: Subscription; + private seekedSubscription: Subscription; + private tasks: OnSeekHandler[]; + + constructor(private player: AudioPlayerService, + private zone: NgZone) { + this.tasks = []; + this.seekedSubscription = this.player.seeked$.subscribe(() => { + if (!this.player.isPlaying()) { + this.zone.runOutsideAngular(() => { + this.runTasks(); + }); + } + }); + this.playingStateSubscription = this.player.playingStateChange$.subscribe( + isPlaying => { + if (isPlaying) { + this.animate(); + } + }); + } + + addPlayingTask(task: OnSeekHandler): void { + this.tasks.push(task); + } + + private animate(): void { + this.zone.runOutsideAngular(() => { + const animateNextFrame = () => { + if (this.player.isPlaying()) { + this.runTasks(); + requestAnimationFrame(animateNextFrame); + } + }; + requestAnimationFrame(animateNextFrame); + }); + } + + private runTasks(): void { + const currentTime = this.player.getCurrentTime(); + for (const task of this.tasks) { + task(currentTime); + } + } +}
--- a/src/app/visualisations/cross-hair-inspector.component.ts Thu Jun 01 23:04:39 2017 +0100 +++ b/src/app/visualisations/cross-hair-inspector.component.ts Fri Jun 02 16:47:38 2017 +0100 @@ -13,6 +13,7 @@ VerticalValueInspectorRenderer } from './waves-base.component'; import {VerticalScaleComponent} from './vertical-scale.component'; +import {RenderLoopService} from '../services/render-loop/render-loop.service'; @Component({ selector: 'ugly-cross-hair-inspector', @@ -26,9 +27,14 @@ ) inspectorRenderers: QueryList<VerticalValueInspectorRenderer>; @Input() unit: string; + constructor(private renderLoop: RenderLoopService) { + super(); + } + ngAfterViewInit(): void { super.ngAfterViewInit(); this.inspectorRenderers.forEach(renderer => { + this.renderLoop.addPlayingTask(renderer.updatePosition); renderer.renderInspector(this.cachedRanged, this.unit); }); }
--- a/src/app/visualisations/waves-base.component.ts Thu Jun 01 23:04:39 2017 +0100 +++ b/src/app/visualisations/waves-base.component.ts Fri Jun 02 16:47:38 2017 +0100 @@ -23,6 +23,7 @@ extends VerticalScaleRenderer { // TODO how do I know these layers are actually 'describable'? abstract renderInspector(range: [number, number], unit?: string): void; + abstract get updatePosition(): OnSeekHandler; } export abstract class WavesComponent<T extends ShapedFeatureData | AudioBuffer> @@ -209,8 +210,14 @@ @Input() set onSeek(handler: OnSeekHandler) { this.wrappedSeekHandler = (x: number) => { handler(x); + this.updatePosition(x); + }; + } + + get updatePosition() { + return (currentTime: number): void => { if (this.highlight) { - this.highlight.currentPosition = x; + this.highlight.currentPosition = currentTime; this.highlight.update(); } };