diff src/app/visualisations/notes/notes.component.ts @ 380:b81ed55fdee3

Basic notes component in place. Room for reducing dupe across these WaveComponent derived components, but will wait until all of them are implemented to see the common logic.
author Lucas Thompson <dev@lucas.im>
date Wed, 31 May 2017 15:15:55 +0100
parents
children 1241ca979fd9
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/visualisations/notes/notes.component.ts	Wed May 31 15:15:55 2017 +0100
@@ -0,0 +1,78 @@
+/**
+ * Created by lucast on 31/05/2017.
+ */
+import {WavesComponent} from '../waves-base.component';
+import {
+  AfterViewInit,
+  ChangeDetectionStrategy,
+  Component,
+  ElementRef,
+  Input,
+  ViewChild
+} from '@angular/core';
+import {Note} from '../FeatureUtilities';
+import Waves from 'waves-ui-piper';
+
+@Component({
+  selector: 'ugly-notes',
+  templateUrl: '../waves-template.html',
+  styleUrls: ['../waves-template.css'],
+  changeDetection: ChangeDetectionStrategy.OnPush
+})
+export class NotesComponent extends WavesComponent implements AfterViewInit {
+
+  @ViewChild('track') trackDiv: ElementRef;
+
+  private mFeature: Note[];
+  private height: number; // As it stands, height is fixed. Store once onInit.
+
+  @Input() set notes(notes: Note[]) {
+    this.mFeature = notes;
+    this.update();
+  }
+
+  get notes(): Note[] {
+    return this.mFeature;
+  }
+
+  ngAfterViewInit(): void {
+    this.height = this.trackDiv.nativeElement.getBoundingClientRect().height;
+    this.renderTimeline(this.trackDiv);
+    this.update();
+  }
+
+  update(): void {
+    if (!this.waveTrack || !this.notes) { return; }
+    this.clearTimeline(this.trackDiv);
+
+    this.addLayer(
+      new Waves.helpers.PianoRollLayer(
+        this.notes,
+        {
+          height: this.height,
+          color: this.colour,
+          yDomain: findVerticalRange(this.notes)
+        }
+      ),
+      this.waveTrack,
+      this.timeline.timeContext
+    );
+  }
+}
+
+// TODO there might be scope to create a generic utility function like this
+function findVerticalRange(notes: Note[]): [number, number] {
+  let [min, max] = notes.reduce((acc, note) => {
+    const [min, max] = acc;
+    return [Math.min (min, note.pitch), Math.max (max, note.pitch)];
+  }, [Infinity, -Infinity]);
+  if (min === Infinity || min < 0 || max < 0) {
+    min = 0;
+    max = 127;
+  }
+  // round min and max to octave boundaries (starting at C as in MIDI)
+  return [
+    12 * Math.floor(min / 12),
+    12 * Math.ceil(max / 12)
+  ];
+}