Mercurial > hg > ugly-duckling
comparison src/app/visualisations/curve/curve.component.ts @ 368:a8a6e8a4ec70
Refactor the curve reshaping stuff to a utility function.
author | Lucas Thompson <dev@lucas.im> |
---|---|
date | Tue, 30 May 2017 22:15:42 +0100 |
parents | f967cb22a37a |
children | 3fa0c8cab919 |
comparison
equal
deleted
inserted
replaced
367:f967cb22a37a | 368:a8a6e8a4ec70 |
---|---|
10 Input, | 10 Input, |
11 ViewChild | 11 ViewChild |
12 } from "@angular/core"; | 12 } from "@angular/core"; |
13 import {VectorFeature} from "piper/HigherLevelUtilities"; | 13 import {VectorFeature} from "piper/HigherLevelUtilities"; |
14 import Waves from 'waves-ui-piper'; | 14 import Waves from 'waves-ui-piper'; |
15 | 15 import {generatePlotData, PlotLayerData} from "../FeatureUtilities"; |
16 interface PlotData { | |
17 cx: number; | |
18 cy: number; | |
19 } | |
20 | |
21 interface PlotLayerData { | |
22 data: PlotData[]; | |
23 color: string; | |
24 height: number; | |
25 yDomain: [number, number]; | |
26 startTime: number; | |
27 duration: number; | |
28 } | |
29 | 16 |
30 @Component({ | 17 @Component({ |
31 selector: 'ugly-curve', | 18 selector: 'ugly-curve', |
32 templateUrl: '../waves-template.html', | 19 templateUrl: '../waves-template.html', |
33 styleUrls: ['../waves-template.css'], | 20 styleUrls: ['../waves-template.css'], |
37 | 24 |
38 @ViewChild('track') trackDiv: ElementRef; | 25 @ViewChild('track') trackDiv: ElementRef; |
39 | 26 |
40 private mFeature: VectorFeature; | 27 private mFeature: VectorFeature; |
41 private currentState: PlotLayerData[]; | 28 private currentState: PlotLayerData[]; |
29 private height: number; // As it stands, height is fixed. Store once onInit. | |
42 | 30 |
43 @Input() set feature(input: VectorFeature) { | 31 @Input() set feature(input: VectorFeature) { |
44 this.mFeature = input; | 32 this.mFeature = input; |
45 this.currentState = this.generatePlotData([input], '', 'black'); | 33 this.currentState = generatePlotData([input]); |
46 this.update(); | 34 this.update(); |
47 } | 35 } |
36 @Input() colour: string; | |
48 | 37 |
49 get feature(): VectorFeature { | 38 get feature(): VectorFeature { |
50 return this.mFeature; | 39 return this.mFeature; |
51 } | 40 } |
52 | 41 |
53 ngAfterViewInit(): void { | 42 ngAfterViewInit(): void { |
43 this.height = this.trackDiv.nativeElement.getBoundingClientRect().height; | |
54 this.renderTimeline(this.trackDiv); | 44 this.renderTimeline(this.trackDiv); |
55 this.update(); | 45 this.update(); |
56 } | 46 } |
57 | 47 |
58 update(): void { | 48 update(): void { |
59 if (this.waveTrack) { | 49 if (this.waveTrack) { |
60 this.clearTimeline(this.trackDiv); | 50 this.clearTimeline(this.trackDiv); |
61 for (const feature of this.currentState) { | 51 for (const feature of this.currentState) { |
62 const lineLayer = new Waves.helpers.LineLayer(feature.data, { | 52 const lineLayer = new Waves.helpers.LineLayer(feature.data, { |
63 color: feature.color, | 53 color: this.colour, |
64 height: feature.height, | 54 height: this.height, |
65 yDomain: feature.yDomain | 55 yDomain: feature.yDomain |
66 }); | 56 }); |
67 this.addLayer( | 57 this.addLayer( |
68 lineLayer, | 58 lineLayer, |
69 this.waveTrack, | 59 this.waveTrack, |
75 lineLayer.start = feature.startTime; | 65 lineLayer.start = feature.startTime; |
76 lineLayer.duration = feature.duration; | 66 lineLayer.duration = feature.duration; |
77 } | 67 } |
78 } | 68 } |
79 } | 69 } |
80 | |
81 private generatePlotData(features: VectorFeature[], | |
82 unit: string, | |
83 colour: string): PlotLayerData[] { | |
84 | |
85 // Winnow out empty features | |
86 features = features.filter(feature => (feature.data.length > 0)); | |
87 | |
88 // First establish a [min,max] range across all of the features | |
89 let [min, max] = features.reduce((acc, feature) => { | |
90 return feature.data.reduce((acc, val) => { | |
91 const [min, max] = acc; | |
92 return [Math.min(min, val), Math.max(max, val)]; | |
93 }, acc); | |
94 }, [Infinity, -Infinity]); | |
95 | |
96 if (min === Infinity) { | |
97 min = 0; | |
98 max = 1; | |
99 } | |
100 | |
101 if (min !== min || max !== max) { | |
102 console.log('WARNING: min or max is NaN'); | |
103 min = 0; | |
104 max = 1; | |
105 } | |
106 | |
107 const height = this.trackDiv.nativeElement.getBoundingClientRect().height; | |
108 return features.map(feature => { | |
109 let duration = 0; | |
110 | |
111 // Give the plot items positions relative to the start of the | |
112 // line, rather than relative to absolute time 0. This is | |
113 // because we'll be setting the layer timeline start property | |
114 // later on and these will be positioned relative to that | |
115 | |
116 const plotData = [...feature.data].map((val, i) => { | |
117 const t = i * feature.stepDuration; | |
118 duration = t + feature.stepDuration; | |
119 return { | |
120 cx: t, | |
121 cy: val | |
122 }; | |
123 }); | |
124 | |
125 return { | |
126 data: plotData, | |
127 color: colour, | |
128 height: height, | |
129 yDomain: [min, max] as [number, number], | |
130 startTime: feature.startTime, | |
131 duration: duration | |
132 }; | |
133 }); | |
134 } | |
135 } | 70 } |