Mercurial > hg > ugly-duckling
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) + ]; +}