# HG changeset patch # User Lucas Thompson # Date 1495819051 -3600 # Node ID a9ce5516c17d35826d1dea387f17e8f8a4308089 # Parent 02e7be2daf31f15b072c1762c770f4ae80eb2ee1 Introduce an abstract base class for components using waves-ui. diff -r 02e7be2daf31 -r a9ce5516c17d src/app/visualisations/waveform/waveform.component.ts --- a/src/app/visualisations/waveform/waveform.component.ts Fri May 26 13:10:18 2017 +0100 +++ b/src/app/visualisations/waveform/waveform.component.ts Fri May 26 18:17:31 2017 +0100 @@ -1,37 +1,21 @@ import { Component, - ViewChild, + Input, + ChangeDetectorRef, ElementRef, - Input, - ChangeDetectorRef + ViewChild } from '@angular/core'; import wavesUI from 'waves-ui-piper'; -import {attachTouchHandlerBodges} from '../WavesJunk'; -import {OnSeekHandler} from '../../playhead/PlayHeadHelpers'; +import {WavesComponent} from '../waves-base.component'; -type Layer = any; -type Track = any; @Component({ selector: 'ugly-waveform', templateUrl: './waveform.component.html', styleUrls: ['./waveform.component.css'] }) -export class WaveformComponent { - +export class WaveformComponent extends WavesComponent { @ViewChild('track') trackDiv: ElementRef; - @Input() set width(width: number) { - if (this.timeline) { - requestAnimationFrame(() => { - this.timeline.timeContext.visibleWidth = width; - this.timeline.tracks.update(); - }); - } - } - @Input() timeline: Timeline; - @Input() trackIdPrefix: string; - @Input() onSeek: OnSeekHandler; - @Input() set audioBuffer(buffer: AudioBuffer) { this._audioBuffer = buffer || undefined; if (this.audioBuffer) { @@ -44,53 +28,9 @@ } private _audioBuffer: AudioBuffer; - private layers: Layer[]; - private zoomOnMouseDown: number; - private offsetOnMouseDown: number; - private waveTrack: Track; constructor(private ref: ChangeDetectorRef) { - this.layers = []; - } - - renderTimeline(duration: number = 1.0): Timeline { - const track: HTMLElement = this.trackDiv.nativeElement; - track.innerHTML = ''; - const height: number = track.getBoundingClientRect().height; - const width: number = track.getBoundingClientRect().width; - this.timeline.pixelsPerSecond = width / duration; - this.timeline.visibleWidth = width; - this.waveTrack = this.timeline.createTrack( - track, - height, - `wave-${this.trackIdPrefix || 'default'}` - ); - - if ('ontouchstart' in window) { - attachTouchHandlerBodges(this.trackDiv.nativeElement, this.timeline); - } - } - - // TODO can likely be removed, or use waves-ui methods - clearTimeline(): void { - // loop through layers and remove them, waves-ui provides methods for this but it seems to not work properly - const timeContextChildren = this.timeline.timeContext._children; - for (const track of this.timeline.tracks) { - if (track.layers.length === 0) { continue; } - const trackLayers = Array.from(track.layers); - while (trackLayers.length) { - const layer: Layer = trackLayers.pop(); - if (this.layers.includes(layer)) { - track.remove(layer); - this.layers.splice(this.layers.indexOf(layer), 1); - const index = timeContextChildren.indexOf(layer.timeContext); - if (index >= 0) { - timeContextChildren.splice(index, 1); - } - layer.destroy(); - } - } - } + super(); } renderWaveform(buffer: AudioBuffer): void { @@ -104,7 +44,7 @@ this.timeline.pixelsPerSecond = width / buffer.duration; this.waveTrack.height = height; } else { - this.renderTimeline(buffer.duration); + this.renderTimeline(this.trackDiv, buffer.duration); } this.timeline.timeContext.offset = 0.5 * this.timeline.timeContext.visibleDuration; @@ -134,44 +74,4 @@ this.waveTrack.update(); this.ref.markForCheck(); } - - // TODO can likely use methods in waves-ui directly - private addLayer(layer: Layer, - track: Track, - timeContext: any, - isAxis: boolean = false): void { - timeContext.zoom = 1.0; - if (!layer.timeContext) { - layer.setTimeContext(isAxis ? - timeContext : new wavesUI.core.LayerTimeContext(timeContext)); - } - track.add(layer); - this.layers.push(layer); - layer.render(); - layer.update(); - } - - seekStart(): void { - this.zoomOnMouseDown = this.timeline.timeContext.zoom; - this.offsetOnMouseDown = this.timeline.timeContext.offset; - } - - seekEnd(x: number): void { - const hasSameZoom: boolean = this.zoomOnMouseDown === - this.timeline.timeContext.zoom; - const hasSameOffset: boolean = this.offsetOnMouseDown === - this.timeline.timeContext.offset; - if (hasSameZoom && hasSameOffset) { - this.seek(x); - } - } - - seek(x: number): void { - if (this.timeline) { - const timeContext: any = this.timeline.timeContext; - if (this.onSeek) { - this.onSeek(timeContext.timeToPixel.invert(x) - timeContext.offset); - } - } - } } diff -r 02e7be2daf31 -r a9ce5516c17d src/app/visualisations/waveform/waves-ui-piper.d.ts --- a/src/app/visualisations/waveform/waves-ui-piper.d.ts Fri May 26 13:10:18 2017 +0100 +++ b/src/app/visualisations/waveform/waves-ui-piper.d.ts Fri May 26 18:17:31 2017 +0100 @@ -38,6 +38,7 @@ stretchRatio: number; yDomain: number[]; opacity: number; + timeContext: any; // TODO readonly timeToPixel: () => (time: number) => number; readonly valueToPixel: () => (value: number) => number; readonly items: Element[]; @@ -95,6 +96,7 @@ } type Timeline = any; +type Track = any; // TODO interface Core { Layer: LayerConstructor; diff -r 02e7be2daf31 -r a9ce5516c17d src/app/visualisations/waves-base.component.ts --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/app/visualisations/waves-base.component.ts Fri May 26 18:17:31 2017 +0100 @@ -0,0 +1,114 @@ +/** + * Created by lucast on 26/05/2017. + */ +import {ElementRef, Input} from '@angular/core'; +import {OnSeekHandler} from '../playhead/PlayHeadHelpers'; +import {attachTouchHandlerBodges} from './WavesJunk'; +import Waves from 'waves-ui-piper'; + +export abstract class WavesComponent { + @Input() set width(width: number) { + if (this.timeline) { + requestAnimationFrame(() => { + this.timeline.timeContext.visibleWidth = width; + this.timeline.tracks.update(); + }); + } + } + @Input() timeline: Timeline; + @Input() trackIdPrefix: string; + @Input() onSeek: OnSeekHandler; + + protected layers: Layer[]; + protected zoomOnMouseDown: number; + protected offsetOnMouseDown: number; + protected waveTrack: Track; + + constructor() { + this.layers = []; + } + + protected renderTimeline($el: ElementRef, duration: number = 1.0): Timeline { + const track: HTMLElement = $el.nativeElement; + track.innerHTML = ''; + const height: number = track.getBoundingClientRect().height; + const width: number = track.getBoundingClientRect().width; + this.timeline.pixelsPerSecond = width / duration; + this.timeline.visibleWidth = width; + this.waveTrack = this.timeline.createTrack( + track, + height, + `wave-${this.trackIdPrefix || 'default'}` + ); + + if ('ontouchstart' in window) { + attachTouchHandlerBodges( + $el.nativeElement, + this.timeline + ); + } + } + + // TODO can likely be removed, or use waves-ui methods + protected clearTimeline(): void { + // loop through layers and remove them, waves-ui provides methods for this but it seems to not work properly + const timeContextChildren = this.timeline.timeContext._children; + for (const track of this.timeline.tracks) { + if (track.layers.length === 0) { continue; } + const trackLayers: Layer[] = Array.from(track.layers as Layer[]); + while (trackLayers.length) { + const layer: Layer = trackLayers.pop(); + if (this.layers.includes(layer)) { + track.remove(layer); + this.layers.splice(this.layers.indexOf(layer), 1); + const index = timeContextChildren.indexOf(layer.timeContext); + if (index >= 0) { + timeContextChildren.splice(index, 1); + } + layer.destroy(); + } + } + } + } + + + // TODO can likely use methods in waves-ui directly + protected addLayer(layer: Layer, + track: Track, + timeContext: any, + isAxis: boolean = false): void { + timeContext.zoom = 1.0; + if (!layer.timeContext) { + layer.setTimeContext(isAxis ? + timeContext : new Waves.core.LayerTimeContext(timeContext)); + } + track.add(layer); + this.layers.push(layer); + layer.render(); + layer.update(); + } + + seekStart(): void { + this.zoomOnMouseDown = this.timeline.timeContext.zoom; + this.offsetOnMouseDown = this.timeline.timeContext.offset; + } + + seekEnd(x: number): void { + const hasSameZoom: boolean = this.zoomOnMouseDown === + this.timeline.timeContext.zoom; + const hasSameOffset: boolean = this.offsetOnMouseDown === + this.timeline.timeContext.offset; + if (hasSameZoom && hasSameOffset) { + this.seek(x); + } + } + + seek(x: number): void { + if (this.timeline) { + const timeContext: any = this.timeline.timeContext; + if (this.onSeek) { + this.onSeek(timeContext.timeToPixel.invert(x) - timeContext.offset); + } + } + } +}