Commit 77d5e6c44fda131038ca2bf21ad6943b5209a763

Authored by Igor Kulikov
Committed by GitHub
2 parents 452090b9 fd3208cf

Merge pull request #3701 from Dmitriymush/master

[3.2.1] bug-fix: Trip-animation
@@ -608,26 +608,32 @@ export default abstract class LeafletMap { @@ -608,26 +608,32 @@ export default abstract class LeafletMap {
608 return polygon; 608 return polygon;
609 } 609 }
610 610
611 - updatePoints(pointsData: FormattedData[], getTooltip: (point: FormattedData, setTooltip?: boolean) => string) { 611 + updatePoints(pointsData: FormattedData[][], getTooltip: (point: FormattedData) => string) {
  612 + if(pointsData.length) {
612 if (this.points) { 613 if (this.points) {
613 - this.map.removeLayer(this.points); 614 + this.map.removeLayer(this.points);
614 } 615 }
615 this.points = new FeatureGroup(); 616 this.points = new FeatureGroup();
616 - pointsData.filter(pdata => !!this.convertPosition(pdata)).forEach(data => {  
617 - const point = L.circleMarker(this.convertPosition(data), {  
618 - color: this.options.pointColor,  
619 - radius: this.options.pointSize  
620 - });  
621 - if (!this.options.pointTooltipOnRightPanel) {  
622 - point.on('click', () => getTooltip(data));  
623 - }  
624 - else {  
625 - createTooltip(point, this.options, data.$datasource, getTooltip(data, false));  
626 - }  
627 - this.points.addLayer(point); 617 + }
  618 + for(let i = 0; i < pointsData.length; i++) {
  619 + const pointsList = pointsData[i];
  620 + pointsList.filter(pdata => !!this.convertPosition(pdata)).forEach(data => {
  621 + const point = L.circleMarker(this.convertPosition(data), {
  622 + color: this.options.pointColor,
  623 + radius: this.options.pointSize
  624 + });
  625 + if (!this.options.pointTooltipOnRightPanel) {
  626 + point.on('click', () => getTooltip(data));
  627 + } else {
  628 + createTooltip(point, this.options, data.$datasource, getTooltip(data));
  629 + }
  630 + this.points.addLayer(point);
628 }); 631 });
  632 + }
  633 + if(pointsData.length) {
629 this.map.addLayer(this.points); 634 this.map.addLayer(this.points);
630 } 635 }
  636 + }
631 637
632 // Polyline 638 // Polyline
633 639
@@ -28,8 +28,12 @@ @@ -28,8 +28,12 @@
28 </button> 28 </button>
29 </div> 29 </div>
30 <div class="trip-animation-tooltip md-whiteframe-z4" fxLayout="column" 30 <div class="trip-animation-tooltip md-whiteframe-z4" fxLayout="column"
31 - [ngClass]="{'trip-animation-tooltip-hidden':!visibleTooltip}" [innerHTML]="mainTooltip"  
32 - [ngStyle]="{'background-color': settings.tooltipColor, 'opacity': settings.tooltipOpacity, 'color': settings.tooltipFontColor}"> 31 + [ngClass]="{'trip-animation-tooltip-hidden':!visibleTooltip}"
  32 + [ngStyle]="{'background-color': settings.tooltipColor, 'opacity': settings.tooltipOpacity, 'color': settings.tooltipFontColor}">
  33 + <div *ngFor="let mainTooltip of mainTooltips"
  34 + [innerHTML]="mainTooltip"
  35 + style="padding: 10px 0">
  36 + </div>
33 </div> 37 </div>
34 </div> 38 </div>
35 <tb-history-selector *ngIf="historicalData" 39 <tb-history-selector *ngIf="historicalData"
@@ -73,6 +73,9 @@ @@ -73,6 +73,9 @@
73 } 73 }
74 74
75 .trip-animation-tooltip { 75 .trip-animation-tooltip {
  76 + display: flex;
  77 + overflow: auto;
  78 + max-height: 90%;
76 position: absolute; 79 position: absolute;
77 top: 30px; 80 top: 30px;
78 right: 0; 81 right: 0;
@@ -86,4 +89,4 @@ @@ -86,4 +89,4 @@
86 } 89 }
87 } 90 }
88 } 91 }
89 -}  
  92 +}
@@ -47,6 +47,9 @@ import moment from 'moment'; @@ -47,6 +47,9 @@ import moment from 'moment';
47 import { isUndefined } from '@core/utils'; 47 import { isUndefined } from '@core/utils';
48 import { ResizeObserver } from '@juggle/resize-observer'; 48 import { ResizeObserver } from '@juggle/resize-observer';
49 49
  50 +interface dataMap {
  51 + [key: string] : FormattedData
  52 +}
50 53
51 @Component({ 54 @Component({
52 // tslint:disable-next-line:component-selector 55 // tslint:disable-next-line:component-selector
@@ -70,7 +73,7 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy @@ -70,7 +73,7 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy
70 interpolatedTimeData = []; 73 interpolatedTimeData = [];
71 widgetConfig: WidgetConfig; 74 widgetConfig: WidgetConfig;
72 settings: TripAnimationSettings; 75 settings: TripAnimationSettings;
73 - mainTooltip = ''; 76 + mainTooltips = [];
74 visibleTooltip = false; 77 visibleTooltip = false;
75 activeTrip: FormattedData; 78 activeTrip: FormattedData;
76 label: string; 79 label: string;
@@ -115,7 +118,7 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy @@ -115,7 +118,7 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy
115 this.historicalData = parseArray(this.ctx.data).filter(arr => arr.length); 118 this.historicalData = parseArray(this.ctx.data).filter(arr => arr.length);
116 if (this.historicalData.length) { 119 if (this.historicalData.length) {
117 this.calculateIntervals(); 120 this.calculateIntervals();
118 - this.timeUpdated(this.currentTime && this.currentTime > this.minTime ? this.currentTime : this.minTime); 121 + this.timeUpdated(this.minTime);
119 } 122 }
120 this.mapWidget.map.map?.invalidateSize(); 123 this.mapWidget.map.map?.invalidateSize();
121 this.cd.detectChanges(); 124 this.cd.detectChanges();
@@ -140,32 +143,39 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy @@ -140,32 +143,39 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy
140 this.currentTime = time; 143 this.currentTime = time;
141 const currentPosition = this.interpolatedTimeData 144 const currentPosition = this.interpolatedTimeData
142 .map(dataSource => dataSource[time]) 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 }
  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 + }
160 this.calcLabel(); 169 this.calcLabel();
161 - this.calcTooltip(currentPosition.find(position => position.entityName === this.activeTrip.entityName)); 170 + this.calcMainTooltip(currentPosition);
162 if (this.mapWidget && this.mapWidget.map && this.mapWidget.map.map) { 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 if (this.settings.showPolygon) { 174 if (this.settings.showPolygon) {
165 this.mapWidget.map.updatePolygons(this.interpolatedTimeData); 175 this.mapWidget.map.updatePolygons(this.interpolatedTimeData);
166 } 176 }
167 if (this.settings.showPoints) { 177 if (this.settings.showPoints) {
168 - this.mapWidget.map.updatePoints(_.values(_.union(this.interpolatedTimeData)[0]), this.calcTooltip); 178 + this.mapWidget.map.updatePoints(formattedInterpolatedTimeData.map(ds => _.union(ds)), this.calcTooltip);
169 } 179 }
170 this.mapWidget.map.updateMarkers(currentPosition, true, (trip) => { 180 this.mapWidget.map.updateMarkers(currentPosition, true, (trip) => {
171 this.activeTrip = trip; 181 this.activeTrip = trip;
@@ -177,6 +187,23 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy @@ -177,6 +187,23 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy
177 setActiveTrip() { 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 calculateIntervals() { 207 calculateIntervals() {
181 this.historicalData.forEach((dataSource, index) => { 208 this.historicalData.forEach((dataSource, index) => {
182 this.minTime = dataSource[0]?.time || Infinity; 209 this.minTime = dataSource[0]?.time || Infinity;
@@ -194,16 +221,19 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy @@ -194,16 +221,19 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy
194 } 221 }
195 } 222 }
196 223
197 - calcTooltip = (point?: FormattedData): string => { 224 + calcTooltip = (point: FormattedData): string => {
198 const data = point ? point : this.activeTrip; 225 const data = point ? point : this.activeTrip;
199 const tooltipPattern: string = this.settings.useTooltipFunction ? 226 const tooltipPattern: string = this.settings.useTooltipFunction ?
200 safeExecute(this.settings.tooltipFunction, [data, this.historicalData, point.dsIndex]) : this.settings.tooltipPattern; 227 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;  
206 - return tooltipText; 228 + return parseWithTranslation.parseTemplate(tooltipPattern, data, true);
  229 + }
  230 +
  231 + private calcMainTooltip(points: FormattedData[]): void {
  232 + const tooltips = [];
  233 + for (let point of points) {
  234 + tooltips.push(this.sanitizer.sanitize(SecurityContext.HTML, this.calcTooltip(point)));
  235 + }
  236 + this.mainTooltips = tooltips;
207 } 237 }
208 238
209 calcLabel() { 239 calcLabel() {