changeset 354:a9ce5516c17d

Introduce an abstract base class for components using waves-ui.
author Lucas Thompson <dev@lucas.im>
date Fri, 26 May 2017 18:17:31 +0100
parents 02e7be2daf31
children 335bb6459fe8
files src/app/visualisations/waveform/waveform.component.ts src/app/visualisations/waveform/waves-ui-piper.d.ts src/app/visualisations/waves-base.component.ts
diffstat 3 files changed, 123 insertions(+), 107 deletions(-) [+]
line wrap: on
line diff
--- 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);
-      }
-    }
-  }
 }
--- 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;
--- /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);
+      }
+    }
+  }
+}