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 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 613 if (this.points) {
613   - this.map.removeLayer(this.points);
  614 + this.map.removeLayer(this.points);
614 615 }
615 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 634 this.map.addLayer(this.points);
630 635 }
  636 + }
631 637
632 638 // Polyline
633 639
... ...
... ... @@ -28,8 +28,12 @@
28 28 </button>
29 29 </div>
30 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 37 </div>
34 38 </div>
35 39 <tb-history-selector *ngIf="historicalData"
... ...
... ... @@ -73,6 +73,9 @@
73 73 }
74 74
75 75 .trip-animation-tooltip {
  76 + display: flex;
  77 + overflow: auto;
  78 + max-height: 90%;
76 79 position: absolute;
77 80 top: 30px;
78 81 right: 0;
... ... @@ -86,4 +89,4 @@
86 89 }
87 90 }
88 91 }
89   -}
\ No newline at end of file
  92 +}
... ...
... ... @@ -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();
... ... @@ -140,32 +143,39 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy
140 143 this.currentTime = time;
141 144 const 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 }
  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 169 this.calcLabel();
161   - this.calcTooltip(currentPosition.find(position => position.entityName === this.activeTrip.entityName));
  170 + this.calcMainTooltip(currentPosition);
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.map(ds => _.union(ds)), 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,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 225 const data = point ? point : this.activeTrip;
199 226 const tooltipPattern: string = this.settings.useTooltipFunction ?
200 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 239 calcLabel() {
... ...