Commit 643563ec6a8cdce5df02b1e4adfc8d7a8d9c00ae
1 parent
c3623be8
bug-fix: trip animation for multiple devices
Showing
2 changed files
with
99 additions
and
50 deletions
... | ... | @@ -599,26 +599,32 @@ export default abstract class LeafletMap { |
599 | 599 | return polygon; |
600 | 600 | } |
601 | 601 | |
602 | - updatePoints(pointsData: FormattedData[], getTooltip: (point: FormattedData, setTooltip?: boolean) => string) { | |
603 | - if (this.points) { | |
602 | + updatePoints(pointsData: FormattedData[][], getTooltip: (point: FormattedData[], setTooltip?: boolean) => string) { | |
603 | + for(let i = 0; i < pointsData.length; i++) { | |
604 | + let pointsList = pointsData[i]; | |
605 | + if(i === 0) { | |
606 | + if (this.points) { | |
604 | 607 | this.map.removeLayer(this.points); |
608 | + } | |
609 | + this.points = new FeatureGroup(); | |
605 | 610 | } |
606 | - this.points = new FeatureGroup(); | |
607 | - pointsData.filter(pdata => !!this.convertPosition(pdata)).forEach(data => { | |
608 | - const point = L.circleMarker(this.convertPosition(data), { | |
609 | - color: this.options.pointColor, | |
610 | - radius: this.options.pointSize | |
611 | - }); | |
612 | - if (!this.options.pointTooltipOnRightPanel) { | |
613 | - point.on('click', () => getTooltip(data)); | |
614 | - } | |
615 | - else { | |
616 | - createTooltip(point, this.options, data.$datasource, getTooltip(data, false)); | |
617 | - } | |
618 | - this.points.addLayer(point); | |
611 | + pointsList.filter(pdata => !!this.convertPosition(pdata)).forEach(data => { | |
612 | + const point = L.circleMarker(this.convertPosition(data), { | |
613 | + color: this.options.pointColor, | |
614 | + radius: this.options.pointSize | |
615 | + }); | |
616 | + if (!this.options.pointTooltipOnRightPanel) { | |
617 | + point.on('click', () => getTooltip([data])); | |
618 | + } else { | |
619 | + createTooltip(point, this.options, data.$datasource, getTooltip([data], false)); | |
620 | + } | |
621 | + this.points.addLayer(point); | |
619 | 622 | }); |
620 | - this.map.addLayer(this.points); | |
623 | + if(i === 0) { | |
624 | + this.map.addLayer(this.points); | |
625 | + } | |
621 | 626 | } |
627 | + } | |
622 | 628 | |
623 | 629 | // Polyline |
624 | 630 | ... | ... |
... | ... | @@ -47,6 +47,9 @@ import moment from 'moment'; |
47 | 47 | import { isUndefined } from '@core/utils'; |
48 | 48 | import { ResizeObserver } from '@juggle/resize-observer'; |
49 | 49 | |
50 | +interface dataMap { | |
51 | + [key: string] : FormattedData | |
52 | +} | |
50 | 53 | |
51 | 54 | @Component({ |
52 | 55 | // tslint:disable-next-line:component-selector |
... | ... | @@ -70,7 +73,7 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy |
70 | 73 | interpolatedTimeData = []; |
71 | 74 | widgetConfig: WidgetConfig; |
72 | 75 | settings: TripAnimationSettings; |
73 | - mainTooltip = ''; | |
76 | + mainTooltips = []; | |
74 | 77 | visibleTooltip = false; |
75 | 78 | activeTrip: FormattedData; |
76 | 79 | label: string; |
... | ... | @@ -115,7 +118,7 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy |
115 | 118 | this.historicalData = parseArray(this.ctx.data).filter(arr => arr.length); |
116 | 119 | if (this.historicalData.length) { |
117 | 120 | this.calculateIntervals(); |
118 | - this.timeUpdated(this.currentTime && this.currentTime > this.minTime ? this.currentTime : this.minTime); | |
121 | + this.timeUpdated(this.minTime); | |
119 | 122 | } |
120 | 123 | this.mapWidget.map.map?.invalidateSize(); |
121 | 124 | this.cd.detectChanges(); |
... | ... | @@ -138,34 +141,41 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy |
138 | 141 | |
139 | 142 | timeUpdated(time: number) { |
140 | 143 | this.currentTime = time; |
141 | - const currentPosition = this.interpolatedTimeData | |
144 | + let currentPosition = this.interpolatedTimeData | |
142 | 145 | .map(dataSource => dataSource[time]) |
143 | - .filter(ds => ds); | |
144 | - if (isUndefined(currentPosition[0])) { | |
145 | - const timePoints = Object.keys(this.interpolatedTimeData[0]).map(item => parseInt(item, 10)); | |
146 | - for (let i = 1; i < timePoints.length; i++) { | |
147 | - if (timePoints[i - 1] < time && timePoints[i] > time) { | |
148 | - const beforePosition = this.interpolatedTimeData[0][timePoints[i - 1]]; | |
149 | - const afterPosition = this.interpolatedTimeData[0][timePoints[i]]; | |
150 | - const ratio = getRatio(timePoints[i - 1], timePoints[i], time); | |
151 | - currentPosition[0] = { | |
152 | - ...beforePosition, | |
153 | - time, | |
154 | - ...interpolateOnLineSegment(beforePosition, afterPosition, this.settings.latKeyName, this.settings.lngKeyName, ratio) | |
146 | + for(let j = 0; j < this.interpolatedTimeData.length; j++) { | |
147 | + if (isUndefined(currentPosition[j])) { | |
148 | + const timePoints = Object.keys(this.interpolatedTimeData[j]).map(item => parseInt(item, 10)); | |
149 | + for (let i = 1; i < timePoints.length; i++) { | |
150 | + if (timePoints[i - 1] < time && timePoints[i] > time) { | |
151 | + const beforePosition = this.interpolatedTimeData[j][timePoints[i - 1]]; | |
152 | + const afterPosition = this.interpolatedTimeData[j][timePoints[i]]; | |
153 | + const ratio = getRatio(timePoints[i - 1], timePoints[i], time); | |
154 | + currentPosition[j] = { | |
155 | + ...beforePosition, | |
156 | + time, | |
157 | + ...interpolateOnLineSegment(beforePosition, afterPosition, this.settings.latKeyName, this.settings.lngKeyName, ratio) | |
158 | + } | |
159 | + break; | |
155 | 160 | } |
156 | - break; | |
157 | 161 | } |
158 | 162 | } |
159 | 163 | } |
160 | - this.calcLabel(); | |
161 | - this.calcTooltip(currentPosition.find(position => position.entityName === this.activeTrip.entityName)); | |
164 | + for(let j = 0; j < this.interpolatedTimeData.length; j++) { | |
165 | + if (isUndefined(currentPosition[j])) { | |
166 | + currentPosition[j] = this.calculateLastPoints(this.interpolatedTimeData[j], time); | |
167 | + } | |
168 | + } | |
169 | + this.calcLabel(currentPosition); | |
170 | + this.calcTooltip(currentPosition, true); | |
162 | 171 | if (this.mapWidget && this.mapWidget.map && this.mapWidget.map.map) { |
163 | - this.mapWidget.map.updatePolylines(this.interpolatedTimeData.map(ds => _.values(ds)), true, this.activeTrip); | |
172 | + const formattedInterpolatedTimeData = this.interpolatedTimeData.map(ds => _.values(ds)); | |
173 | + this.mapWidget.map.updatePolylines(formattedInterpolatedTimeData, true); | |
164 | 174 | if (this.settings.showPolygon) { |
165 | 175 | this.mapWidget.map.updatePolygons(this.interpolatedTimeData); |
166 | 176 | } |
167 | 177 | if (this.settings.showPoints) { |
168 | - this.mapWidget.map.updatePoints(_.values(_.union(this.interpolatedTimeData)[0]), this.calcTooltip); | |
178 | + this.mapWidget.map.updatePoints(formattedInterpolatedTimeData, this.calcTooltip); | |
169 | 179 | } |
170 | 180 | this.mapWidget.map.updateMarkers(currentPosition, true, (trip) => { |
171 | 181 | this.activeTrip = trip; |
... | ... | @@ -177,6 +187,23 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy |
177 | 187 | setActiveTrip() { |
178 | 188 | } |
179 | 189 | |
190 | + private calculateLastPoints(dataSource: dataMap, time: number): FormattedData { | |
191 | + const timeArr = Object.keys(dataSource); | |
192 | + let index = timeArr.findIndex((dtime, index) => { | |
193 | + return Number(dtime) >= time; | |
194 | + }); | |
195 | + | |
196 | + if(index !== -1) { | |
197 | + if(Number(timeArr[index]) !== time && index !== 0) { | |
198 | + index--; | |
199 | + } | |
200 | + } else { | |
201 | + index = timeArr.length - 1; | |
202 | + } | |
203 | + | |
204 | + return dataSource[timeArr[index]]; | |
205 | + } | |
206 | + | |
180 | 207 | calculateIntervals() { |
181 | 208 | this.historicalData.forEach((dataSource, index) => { |
182 | 209 | this.minTime = dataSource[0]?.time || Infinity; |
... | ... | @@ -194,23 +221,39 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy |
194 | 221 | } |
195 | 222 | } |
196 | 223 | |
197 | - calcTooltip = (point?: FormattedData): string => { | |
198 | - const data = point ? point : this.activeTrip; | |
199 | - const tooltipPattern: string = this.settings.useTooltipFunction ? | |
200 | - safeExecute(this.settings.tooltipFunction, [data, this.historicalData, point.dsIndex]) : this.settings.tooltipPattern; | |
201 | - const tooltipText = parseWithTranslation.parseTemplate(tooltipPattern, data, true); | |
202 | - this.mainTooltip = this.sanitizer.sanitize( | |
203 | - SecurityContext.HTML, tooltipText); | |
204 | - this.cd.detectChanges(); | |
205 | - this.activeTrip = point; | |
224 | + calcTooltip = (points?: FormattedData[], isMainTooltip: boolean = false): string => { | |
225 | + let tooltipText; | |
226 | + if(isMainTooltip) { | |
227 | + this.mainTooltips = [] | |
228 | + } | |
229 | + for (let point of points) { | |
230 | + const data = point ? point : this.activeTrip; | |
231 | + const tooltipPattern: string = this.settings.useTooltipFunction ? | |
232 | + safeExecute(this.settings.tooltipFunction, [data, this.historicalData, point.dsIndex]) : this.settings.tooltipPattern; | |
233 | + tooltipText = parseWithTranslation.parseTemplate(tooltipPattern, data, true); | |
234 | + if(isMainTooltip) { | |
235 | + this.mainTooltips.push(this.sanitizer.sanitize(SecurityContext.HTML, tooltipText)); | |
236 | + } | |
237 | + this.cd.detectChanges(); | |
238 | + this.activeTrip = point; | |
239 | + } | |
206 | 240 | return tooltipText; |
207 | 241 | } |
208 | 242 | |
209 | - calcLabel() { | |
210 | - const data = this.activeTrip; | |
211 | - const labelText: string = this.settings.useLabelFunction ? | |
212 | - safeExecute(this.settings.labelFunction, [data, this.historicalData, data.dsIndex]) : this.settings.label; | |
213 | - this.label = (parseWithTranslation.parseTemplate(labelText, data, true)); | |
243 | + calcLabel(formattedDataArr: FormattedData[]) { | |
244 | + // const data = this.activeTrip; | |
245 | + // const labelText: string = this.settings.useLabelFunction ? | |
246 | + // safeExecute(this.settings.labelFunction, [data, this.historicalData, data.dsIndex]) : this.settings.label; | |
247 | + // this.label = (parseWithTranslation.parseTemplate(labelText, data, true)); | |
248 | + // console.log(this.label, 'this.label'); | |
249 | + this.label = ''; | |
250 | + for (let formattedData of formattedDataArr) { | |
251 | + const data = formattedData; | |
252 | + const labelText: string = this.settings.useLabelFunction ? | |
253 | + safeExecute(this.settings.labelFunction, [data, this.historicalData, data.dsIndex]) : this.settings.label; | |
254 | + const label = (parseWithTranslation.parseTemplate(labelText, data, true)); | |
255 | + this.label = this.label.length ? this.label + ',' + label : label; | |
256 | + } | |
214 | 257 | } |
215 | 258 | |
216 | 259 | interpolateArray(originData: FormattedData[]) { | ... | ... |