From a1b84834fc442964d221b678a1166d46810c02c5 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Mon, 18 May 2020 10:58:46 +0300 Subject: [PATCH] Update trip-animation widget --- .../data/json/system/widget_bundles/maps.json | 4 +- ui-ngx/package-lock.json | 8 -- ui-ngx/package.json | 1 - .../components/widget/lib/maps/maps-utils.ts | 13 ++ .../components/widget/lib/maps/schemes.ts | 87 ++++++------ .../trip-animation.component.html | 10 +- .../trip-animation.component.ts | 127 +++++++++++------- .../history-selector.component.html | 9 +- .../history-selector.component.ts | 52 +++---- 9 files changed, 169 insertions(+), 142 deletions(-) diff --git a/application/src/main/data/json/system/widget_bundles/maps.json b/application/src/main/data/json/system/widget_bundles/maps.json index 4d7d0f3b10..ee6dd3b6a9 100644 --- a/application/src/main/data/json/system/widget_bundles/maps.json +++ b/application/src/main/data/json/system/widget_bundles/maps.json @@ -130,7 +130,7 @@ "controllerScript": " self.onInit = function() {\n var $scope = self.ctx.$scope;\n $scope.self = self;\n }\n \n \n self.actionSources = function () {\n return {\n 'tooltipAction': {\n name: 'widget-action.tooltip-tag-action',\n multiple: false\n }\n }\n };\n \n self.getSettingsSchema = function() {\n return TbTripAnimationWidget.getSettingsSchema();\n}\n", "settingsSchema": "", "dataKeySettingsSchema": "{}", - "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"entityAliasId\":null,\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"latitude\",\"color\":\"#2196f3\",\"settings\":{\"showLines\":true,\"fillLines\":true,\"showPoints\":false},\"_hash\":0.8587686344902596,\"funcBody\":\"var gpsData = [\\n37.771210000, -122.510960000,\\n 37.771990000, -122.497070000,\\n 37.772730000, -122.480740000,\\n 37.773360000, -122.466870000,\\n 37.774270000, -122.458520000,\\n 37.771980000, -122.454110000,\\n 37.768250000, -122.453380000,\\n 37.765920000, -122.456810000,\\n 37.765930000, -122.467680000,\\n 37.765500000, -122.477180000,\\n 37.765300000, -122.481660000,\\n 37.764780000, -122.493350000,\\n 37.764120000, -122.508360000,\\n 37.766410000, -122.510260000,\\n 37.770010000, -122.510830000,\\n 37.770980000, -122.510930000\\n];\\n let value = gpsData.indexOf(prevValue); \\nreturn gpsData[(value == -1 ? 0 : value + 2)];\",\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"longitude\",\"color\":\"#ffc107\",\"settings\":{\"showLines\":true,\"fillLines\":false,\"showPoints\":false},\"_hash\":0.12775350966079668,\"funcBody\":\"var gpsData = [\\n37.771210000, -122.510960000,\\n 37.771990000, -122.497070000,\\n 37.772730000, -122.480740000,\\n 37.773360000, -122.466870000,\\n 37.774270000, -122.458520000,\\n 37.771980000, -122.454110000,\\n 37.768250000, -122.453380000,\\n 37.765920000, -122.456810000,\\n 37.765930000, -122.467680000,\\n 37.765500000, -122.477180000,\\n 37.765300000, -122.481660000,\\n 37.764780000, -122.493350000,\\n 37.764120000, -122.508360000,\\n 37.766410000, -122.510260000,\\n 37.770010000, -122.510830000,\\n 37.770980000, -122.510930000\\n];\\n let value = gpsData.indexOf(prevValue); \\nreturn gpsData[(value == -1 ? 1 : value + 2)];\",\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null}]}],\"timewindow\":{\"history\":{\"interval\":1000,\"timewindowMs\":60000},\"aggregation\":{\"type\":\"NONE\",\"limit\":500}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"mapProvider\":\"OpenStreetMap.Mapnik\",\"latKeyName\":\"latitude\",\"lngKeyName\":\"longitude\",\"showLabel\":true,\"label\":\"${entityName}\",\"showTooltip\":true,\"tooltipColor\":\"#fff\",\"tooltipFontColor\":\"#000\",\"tooltipOpacity\":1,\"tooltipPattern\":\"${entityName}

Latitude: ${latitude:7}
Longitude: ${longitude:7}
End Time: ${maxTime}
Start Time: ${minTime}\",\"strokeWeight\":2,\"strokeOpacity\":1,\"pointSize\":10,\"markerImageSize\":34,\"rotationAngle\":180,\"provider\":\"openstreet-map\",\"normalizationStep\":1000,\"polKeyName\":\"coordinates\",\"decoratorSymbol\":\"arrowHead\",\"decoratorSymbolSize\":10,\"decoratorCustomColor\":\"#000\",\"decoratorOffset\":\"20px\",\"endDecoratorOffset\":\"20px\",\"decoratorRepeat\":\"20px\",\"polygonTooltipPattern\":\"${entityName}

TimeStamp: ${ts:7}\",\"polygonOpacity\":0.5,\"polygonStrokeOpacity\":1,\"polygonStrokeWeight\":1,\"pointTooltipOnRightPanel\":true,\"autocloseTooltip\":true},\"title\":\"Trip Animation\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"mobileHeight\":null,\"widgetStyle\":{},\"useDashboardTimewindow\":false,\"showLegend\":false,\"actions\":{},\"legendConfig\":{\"position\":\"bottom\",\"showMin\":false,\"showMax\":false,\"showAvg\":false,\"showTotal\":false},\"displayTimewindow\":true}" + "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"entityAliasId\":null,\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"latitude\",\"color\":\"#2196f3\",\"settings\":{\"showLines\":true,\"fillLines\":true,\"showPoints\":false},\"_hash\":0.8587686344902596,\"funcBody\":\"var gpsData = [\\n37.771210000, -122.510960000,\\n 37.771990000, -122.497070000,\\n 37.772730000, -122.480740000,\\n 37.773360000, -122.466870000,\\n 37.774270000, -122.458520000,\\n 37.771980000, -122.454110000,\\n 37.768250000, -122.453380000,\\n 37.765920000, -122.456810000,\\n 37.765930000, -122.467680000,\\n 37.765500000, -122.477180000,\\n 37.765300000, -122.481660000,\\n 37.764780000, -122.493350000,\\n 37.764120000, -122.508360000,\\n 37.766410000, -122.510260000,\\n 37.770010000, -122.510830000,\\n 37.770980000, -122.510930000\\n];\\n let value = gpsData.indexOf(prevValue); \\nreturn gpsData[(value == -1 ? 0 : (value + 2) % gpsData.length)];\",\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"longitude\",\"color\":\"#ffc107\",\"settings\":{\"showLines\":true,\"fillLines\":false,\"showPoints\":false},\"_hash\":0.12775350966079668,\"funcBody\":\"var gpsData = [\\n37.771210000, -122.510960000,\\n 37.771990000, -122.497070000,\\n 37.772730000, -122.480740000,\\n 37.773360000, -122.466870000,\\n 37.774270000, -122.458520000,\\n 37.771980000, -122.454110000,\\n 37.768250000, -122.453380000,\\n 37.765920000, -122.456810000,\\n 37.765930000, -122.467680000,\\n 37.765500000, -122.477180000,\\n 37.765300000, -122.481660000,\\n 37.764780000, -122.493350000,\\n 37.764120000, -122.508360000,\\n 37.766410000, -122.510260000,\\n 37.770010000, -122.510830000,\\n 37.770980000, -122.510930000\\n];\\n let value = gpsData.indexOf(prevValue); \\nreturn gpsData[(value == -1 ? 1 : (value + 2) % gpsData.length)];\",\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null}]}],\"timewindow\":{\"history\":{\"interval\":1000,\"timewindowMs\":60000},\"aggregation\":{\"type\":\"NONE\",\"limit\":500}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"mapProvider\":\"OpenStreetMap.Mapnik\",\"latKeyName\":\"latitude\",\"lngKeyName\":\"longitude\",\"showLabel\":true,\"label\":\"${entityName}\",\"showTooltip\":true,\"tooltipColor\":\"#fff\",\"tooltipFontColor\":\"#000\",\"tooltipOpacity\":1,\"tooltipPattern\":\"${entityName}

Latitude: ${latitude:7}
Longitude: ${longitude:7}
End Time: ${maxTime}
Start Time: ${minTime}\",\"strokeWeight\":2,\"strokeOpacity\":1,\"pointSize\":10,\"markerImageSize\":34,\"rotationAngle\":180,\"provider\":\"openstreet-map\",\"normalizationStep\":1000,\"polKeyName\":\"coordinates\",\"decoratorSymbol\":\"arrowHead\",\"decoratorSymbolSize\":10,\"decoratorCustomColor\":\"#000\",\"decoratorOffset\":\"20px\",\"endDecoratorOffset\":\"20px\",\"decoratorRepeat\":\"20px\",\"polygonTooltipPattern\":\"${entityName}

TimeStamp: ${ts:7}\",\"polygonOpacity\":0.5,\"polygonStrokeOpacity\":1,\"polygonStrokeWeight\":1,\"pointTooltipOnRightPanel\":true,\"autocloseTooltip\":true},\"title\":\"Trip Animation\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"mobileHeight\":null,\"widgetStyle\":{},\"useDashboardTimewindow\":false,\"showLegend\":false,\"actions\":{},\"legendConfig\":{\"position\":\"bottom\",\"showMin\":false,\"showMax\":false,\"showAvg\":false,\"showTotal\":false},\"displayTimewindow\":true}" } }, { @@ -150,4 +150,4 @@ } } ] -} \ No newline at end of file +} diff --git a/ui-ngx/package-lock.json b/ui-ngx/package-lock.json index 184bc9337a..b0703908b8 100644 --- a/ui-ngx/package-lock.json +++ b/ui-ngx/package-lock.json @@ -7969,14 +7969,6 @@ "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.6.0.tgz", "integrity": "sha512-CPkhyqWUKZKFJ6K8umN5/D2wrJ2+/8UIpXppY7QDnUZW5bZL5+SEI2J7GBpwh4LIupOKqbNSQXgqmrEJopHVNQ==" }, - "leaflet-geometryutil": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/leaflet-geometryutil/-/leaflet-geometryutil-0.9.3.tgz", - "integrity": "sha512-Wi6YvfNx/Xu9q35AEfXpsUXmIFLen/MO+C2qimxHRnjyeyOxBhdcZa6kSiReaOX0cGK7yQInqrzz0dkIqZ8Dpg==", - "requires": { - "leaflet": ">=0.7.0" - } - }, "leaflet-polylinedecorator": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/leaflet-polylinedecorator/-/leaflet-polylinedecorator-1.6.0.tgz", diff --git a/ui-ngx/package.json b/ui-ngx/package.json index 4a5f62ea43..cc1debfb46 100644 --- a/ui-ngx/package.json +++ b/ui-ngx/package.json @@ -58,7 +58,6 @@ "jstree-bootstrap-theme": "^1.0.1", "jszip": "^3.4.0", "leaflet": "^1.6.0", - "leaflet-geometryutil": "^0.9.3", "leaflet-polylinedecorator": "^1.6.0", "leaflet-providers": "^1.9.1", "leaflet.gridlayer.googlemutant": "0.8.0", diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/maps-utils.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/maps-utils.ts index 7ab2dbabe5..cdb4662cbe 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/maps-utils.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/maps-utils.ts @@ -56,6 +56,19 @@ export function getRatio(firsMoment: number, secondMoment: number, intermediateM return (intermediateMoment - firsMoment) / (secondMoment - firsMoment); } +export function interpolateOnLineSegment( + pointA: FormattedData, + oointB: FormattedData, + latKeyName: string, + lngKeyName: string, + ratio: number +): { [key: string]: number } { + return { + [latKeyName]: (pointA[latKeyName] + (oointB[latKeyName] - pointA[latKeyName]) * ratio), + [lngKeyName]: (pointA[lngKeyName] + (oointB[lngKeyName] - pointA[lngKeyName]) * ratio) + }; +} + export function findAngle(startPoint: FormattedData, endPoint: FormattedData, latKeyName: string, lngKeyName: string): number { let angle = -Math.atan2(endPoint[latKeyName] - startPoint[latKeyName], endPoint[lngKeyName] - startPoint[lngKeyName]); angle = angle * 180 / Math.PI; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/schemes.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/schemes.ts index 411f55706e..fd8e9e5e8c 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/schemes.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/schemes.ts @@ -841,52 +841,57 @@ export const pathSchema = }; export const pointSchema = -{ + { schema: { - title: 'Trip Animation Path Configuration', - type: 'object', - properties: { - showPoints: { - title: 'Show points', - type: 'boolean', - default: false - }, - pointColor: { - title: 'Point color', - type: 'string' - }, - pointSize: { - title: 'Point size (px)', - type: 'number', - default: 10 - }, - usePointAsAnchor: { - title: 'Use point as anchor', - type: 'boolean', - default: false - }, - pointAsAnchorFunction: { - title: 'Point as anchor function: f(data, dsData, dsIndex)', - type: 'string' - }, - pointTooltipOnRightPanel: { - title: 'Independant point tooltip', - type: 'boolean', - default: true - }, + title: 'Trip Animation Path Configuration', + type: 'object', + properties: { + showPoints: { + title: 'Show points', + type: 'boolean', + default: false }, - required: [] + pointColor: { + title: 'Point color', + type: 'string' + }, + pointSize: { + title: 'Point size (px)', + type: 'number', + default: 10 + }, + // usePointAsAnchor: { + // title: 'Use point as anchor', + // type: 'boolean', + // default: false + // }, + // pointAsAnchorFunction: { + // title: 'Point as anchor function: f(data, dsData, dsIndex)', + // type: 'string' + // }, + pointTooltipOnRightPanel: { + title: 'Independant point tooltip', + type: 'boolean', + default: true + }, + }, + required: [] }, form: [ - 'showPoints', { - key: 'pointColor', - type: 'color' - }, 'pointSize', 'usePointAsAnchor', { - key: 'pointAsAnchorFunction', - type: 'javascript' - }, 'pointTooltipOnRightPanel', + 'showPoints', + { + key: 'pointColor', + type: 'color' + }, + 'pointSize', + // 'usePointAsAnchor', + // { + // key: 'pointAsAnchorFunction', + // type: 'javascript' + // }, + 'pointTooltipOnRightPanel', ] -}; + }; export const mapProviderSchema = { diff --git a/ui-ngx/src/app/modules/home/components/widget/trip-animation/trip-animation.component.html b/ui-ngx/src/app/modules/home/components/widget/trip-animation/trip-animation.component.html index 9449e3aba9..cc0429660a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/trip-animation/trip-animation.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/trip-animation/trip-animation.component.html @@ -32,6 +32,10 @@ [ngStyle]="{'background-color': settings.tooltipColor, 'opacity': settings.tooltipOpacity, 'color': settings.tooltipFontColor}"> - - \ No newline at end of file + + diff --git a/ui-ngx/src/app/modules/home/components/widget/trip-animation/trip-animation.component.ts b/ui-ngx/src/app/modules/home/components/widget/trip-animation/trip-animation.component.ts index b26c457547..5a293a3d58 100644 --- a/ui-ngx/src/app/modules/home/components/widget/trip-animation/trip-animation.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/trip-animation/trip-animation.component.ts @@ -14,10 +14,8 @@ /// limitations under the License. /// -import L from 'leaflet'; import _ from 'lodash'; import tinycolor from 'tinycolor2'; -import { interpolateOnPointSegment } from 'leaflet-geometryutil'; import { AfterViewInit, ChangeDetectorRef, Component, Input, OnInit, SecurityContext, ViewChild } from '@angular/core'; import { MapWidgetController, TbMapWidgetV2 } from '../lib/maps/map-widget2'; @@ -26,9 +24,17 @@ import { addCondition, addGroupInfo, addToSchema, initSchema } from '@app/core/s import { mapPolygonSchema, pathSchema, pointSchema, tripAnimationSchema } from '../lib/maps/schemes'; import { DomSanitizer } from '@angular/platform-browser'; import { WidgetContext } from '@app/modules/home/models/widget-component.models'; -import { findAngle, getRatio, parseArray, parseWithTranslation, safeExecute } from '../lib/maps/maps-utils'; +import { + findAngle, + getRatio, + interpolateOnLineSegment, + parseArray, + parseWithTranslation, + safeExecute +} from '../lib/maps/maps-utils'; import { JsonSettingsSchema, WidgetConfig } from '@shared/models/widget.models'; import moment from 'moment'; +import { isUndefined } from '@core/utils'; @Component({ @@ -46,20 +52,21 @@ export class TripAnimationComponent implements OnInit, AfterViewInit { @ViewChild('map') mapContainer; mapWidget: MapWidgetController; - historicalData; - intervals; - normalizationStep = 1000; - interpolatedData = []; + historicalData: FormattedData[][]; + normalizationStep: number; + interpolatedTimeData = []; widgetConfig: WidgetConfig; settings; mainTooltip = ''; visibleTooltip = false; - activeTrip; + activeTrip: FormattedData; label; - minTime; - maxTime; + minTime: number; + minTimeFormat: string; + maxTime: number; + maxTimeFormat: string; anchors = []; - useAnchors = false; + useAnchors: boolean; static getSettingsSchema(): JsonSettingsSchema { const schema = initSchema(); @@ -95,7 +102,7 @@ export class TripAnimationComponent implements OnInit, AfterViewInit { this.historicalData = parseArray(this.ctx.data); this.activeTrip = this.historicalData[0][0]; this.calculateIntervals(); - this.timeUpdated(this.intervals[0]); + this.timeUpdated(this.minTime); this.mapWidget.map.map?.invalidateSize(); this.cd.detectChanges(); } @@ -108,23 +115,37 @@ export class TripAnimationComponent implements OnInit, AfterViewInit { } timeUpdated(time: number) { - const currentPosition = this.interpolatedData.map(dataSource => dataSource[time]); + const currentPosition = this.interpolatedTimeData.map(dataSource => dataSource[time]); + if(isUndefined(currentPosition[0])){ + const timePoints = Object.keys(this.interpolatedTimeData[0]).map(item => parseInt(item, 10)); + for (let i = 1; i < timePoints.length; i++) { + if (timePoints[i - 1] < time && timePoints[i] > time) { + const beforePosition = this.interpolatedTimeData[0][timePoints[i - 1]]; + const afterPosition = this.interpolatedTimeData[0][timePoints[i]]; + const ratio = getRatio(timePoints[i - 1], timePoints[i], time); + currentPosition[0] = { + ...beforePosition, + time, + ...interpolateOnLineSegment(beforePosition, afterPosition, this.settings.latKeyName, this.settings.lngKeyName, ratio) + } + break; + } + } + } this.activeTrip = currentPosition[0]; - this.minTime = moment(this.intervals[this.intervals.length - 1]).format('YYYY-MM-DD HH:mm:ss') - this.maxTime = moment(this.intervals[0]).format('YYYY-MM-DD HH:mm:ss') this.calcLabel(); this.calcTooltip(); if (this.mapWidget) { - this.mapWidget.map.updatePolylines(this.interpolatedData.map(ds => _.values(ds))); + this.mapWidget.map.updatePolylines(this.interpolatedTimeData.map(ds => _.values(ds))); if (this.settings.showPolygon) { - this.mapWidget.map.updatePolygons(this.interpolatedData); + this.mapWidget.map.updatePolygons(this.interpolatedTimeData); } if (this.settings.showPoints) { - this.mapWidget.map.updatePoints(this.historicalData[0], this.calcTooltip); - this.anchors = this.historicalData[0] - .filter(data => - this.settings.usePointAsAnchor || - safeExecute(this.settings.pointAsAnchorFunction, [this.historicalData, data, data.dsIndex])).map(data => data.time); + this.mapWidget.map.updatePoints(this.interpolatedTimeData, this.calcTooltip); + // this.anchors = this.interpolatedTimeData + // .filter(data => + // this.settings.usePointAsAnchor || + // safeExecute(this.settings.pointAsAnchorFunction, [this.interpolatedTimeData, data, data.dsIndex])).map(data => data.time); } this.mapWidget.map.updateMarkers(currentPosition); } @@ -135,12 +156,11 @@ export class TripAnimationComponent implements OnInit, AfterViewInit { calculateIntervals() { this.historicalData.forEach((dataSource, index) => { - this.intervals = []; - for (let time = dataSource[0]?.time; time < dataSource[dataSource.length - 1]?.time; time += this.normalizationStep) { - this.intervals.push(time); - } - this.intervals.push(dataSource[dataSource.length - 1]?.time); - this.interpolatedData[index] = this.interpolateArray(dataSource, this.intervals); + this.minTime = dataSource[0]?.time || Infinity; + this.minTimeFormat = this.minTime !== Infinity ? moment(this.minTime).format('YYYY-MM-DD HH:mm:ss') : ''; + this.maxTime = dataSource[dataSource.length - 1]?.time || -Infinity; + this.maxTimeFormat = this.maxTime !== -Infinity ? moment(this.maxTime).format('YYYY-MM-DD HH:mm:ss') : ''; + this.interpolatedTimeData[index] = this.interpolateArray(dataSource); }); } @@ -149,9 +169,13 @@ export class TripAnimationComponent implements OnInit, AfterViewInit { if (!point) { point = this.activeTrip; } - const data = { ...point, maxTime: this.maxTime, minTime: this.minTime } + const data = { + ...this.activeTrip, + maxTime: this.maxTimeFormat, + minTime: this.minTimeFormat + } const tooltipPattern: string = this.settings.useTooltipFunction ? - safeExecute(this.settings.tooolTipFunction, [data, this.historicalData, 0]) : this.settings.tooltipPattern; + safeExecute(this.settings.tooolTipFunction, [data, this.historicalData, point.dsIndex]) : this.settings.tooltipPattern; const tooltipText = parseWithTranslation.parseTemplate(tooltipPattern, data, true); if (setTooltip) { this.mainTooltip = this.sanitizer.sanitize( @@ -162,34 +186,37 @@ export class TripAnimationComponent implements OnInit, AfterViewInit { } calcLabel() { - const data = { ...this.activeTrip, maxTime: this.maxTime, minTime: this.minTime } + const data = { + ...this.activeTrip, + maxTime: this.maxTimeFormat, + minTime: this.minTimeFormat + } const labelText: string = this.settings.useLabelFunction ? - safeExecute(this.settings.labelFunction, [data, this.historicalData, 0]) : this.settings.label; + safeExecute(this.settings.labelFunction, [data, this.historicalData, data.dsIndex]) : this.settings.label; this.label = (parseWithTranslation.parseTemplate(labelText, data, true)); } - interpolateArray(originData, interpolatedIntervals) { + interpolateArray(originData: FormattedData[]) { const result = {}; - for (let i = 1, j = 0; i < originData.length && j < interpolatedIntervals.length;) { - const currentTime = interpolatedIntervals[j]; - while (originData[i].time < currentTime) i++; - const before = originData[i - 1]; - const after = originData[i]; - const interpolation = interpolateOnPointSegment( - new L.Point(before[this.settings.latKeyName], before[this.settings.lngKeyName]), - new L.Point(after[this.settings.latKeyName], after[this.settings.lngKeyName]), - getRatio(before.time, after.time, currentTime)); - result[currentTime] = ({ - ...originData[i], - rotationAngle: findAngle(before, after, this.settings.latKeyName, this.settings.lngKeyName) + this.settings.rotationAngle, - latitude: interpolation.x, - longitude: interpolation.y - }); - j++; + const latKeyName = this.settings.latKeyName; + const lngKeyName = this.settings.lngKeyName; + for (let i = 0; i < originData.length; i++) { + const currentTime = originData[i].time; + const normalizeTime = this.minTime + Math.ceil((currentTime - this.minTime) / this.normalizationStep) * this.normalizationStep; + if (i !== originData.length - 1) { + result[normalizeTime] = { + ...originData[i], + rotationAngle: this.settings.rotationAngle + findAngle(originData[i], originData[i + 1], latKeyName, lngKeyName) + }; + } else { + result[normalizeTime] = { + ...originData[i], + rotationAngle: findAngle(originData[i - 1], originData[i], latKeyName, lngKeyName) + this.settings.rotationAngle + }; + } } return result; } } export let TbTripAnimationWidget = TripAnimationComponent; - diff --git a/ui-ngx/src/app/shared/components/time/history-selector/history-selector.component.html b/ui-ngx/src/app/shared/components/time/history-selector/history-selector.component.html index 54bba32bae..78c8957f44 100644 --- a/ui-ngx/src/app/shared/components/time/history-selector/history-selector.component.html +++ b/ui-ngx/src/app/shared/components/time/history-selector/history-selector.component.html @@ -27,8 +27,8 @@
- {{ this.intervals[this.index] | date:'medium'}} - {{ "widget.no-data-found" | translate}} + {{ this.currentTime | date:'medium'}} + {{ "widget.no-data-found" | translate}}
- {{speedValue}} - \ No newline at end of file + + diff --git a/ui-ngx/src/app/shared/components/time/history-selector/history-selector.component.ts b/ui-ngx/src/app/shared/components/time/history-selector/history-selector.component.ts index a15b892349..d881eca805 100644 --- a/ui-ngx/src/app/shared/components/time/history-selector/history-selector.component.ts +++ b/ui-ngx/src/app/shared/components/time/history-selector/history-selector.component.ts @@ -14,7 +14,7 @@ /// limitations under the License. /// -import { Component, OnInit, OnChanges, Input, Output, EventEmitter, ChangeDetectorRef } from '@angular/core'; +import { ChangeDetectorRef, Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core'; import { interval } from 'rxjs'; import { filter } from 'rxjs/operators'; import { HistorySelectSettings } from '@app/modules/home/components/widget/lib/maps/map-models'; @@ -27,13 +27,12 @@ import { HistorySelectSettings } from '@app/modules/home/components/widget/lib/m export class HistorySelectorComponent implements OnInit, OnChanges { @Input() settings: HistorySelectSettings - @Input() intervals = []; - @Input() anchors = []; - @Input() useAnchors = false; + @Input() minTime: number; + @Input() maxTime: number; + @Input() step = 1000; @Output() timeUpdated: EventEmitter = new EventEmitter(); - animationTime; minTimeIndex = 0; maxTimeIndex = 0; speed = 1; @@ -41,6 +40,7 @@ export class HistorySelectorComponent implements OnInit, OnChanges { playing = false; interval; speeds = [1, 5, 10, 25]; + currentTime = null; constructor(private cd: ChangeDetectorRef) { } @@ -49,7 +49,8 @@ export class HistorySelectorComponent implements OnInit, OnChanges { } ngOnChanges() { - this.maxTimeIndex = this.intervals?.length - 1; + this.maxTimeIndex = Math.ceil((this.maxTime - this.minTime) / this.step); + this.currentTime = this.minTime === Infinity ? null : this.minTime; } play() { @@ -59,17 +60,18 @@ export class HistorySelectorComponent implements OnInit, OnChanges { .pipe( filter(() => this.playing)).subscribe(() => { this.index++; - if (this.index < this.maxTimeIndex) { + this.currentTime = this.minTime + this.index * this.step; + if (this.index <= this.maxTimeIndex) { this.cd.detectChanges(); - this.timeUpdated.emit(this.intervals[this.index]); + this.timeUpdated.emit(this.currentTime); } else { this.interval.complete(); } }, err => { - console.log(err); + console.error(err); }, () => { - this.index = this.minTimeIndex; + this.currentTime = this.index = this.minTimeIndex; this.playing = false; this.interval = null; this.cd.detectChanges(); @@ -87,30 +89,21 @@ export class HistorySelectorComponent implements OnInit, OnChanges { pause() { this.playing = false; + this.currentTime = this.minTime + this.index * this.step; this.cd.detectChanges(); - this.timeUpdated.emit(this.intervals[this.index]); + this.timeUpdated.emit(this.currentTime); } moveNext() { - if (this.index < this.maxTimeIndex) { - if (this.useAnchors) { - const anchorIndex = this.findIndex(this.intervals[this.index], this.anchors)+1; - this.index = this.findIndex(this.anchors[anchorIndex], this.intervals); - } - else - this.index++; + if (this.index <= this.maxTimeIndex) { + this.index++; } this.pause(); } movePrev() { if (this.index > this.minTimeIndex) { - if (this.useAnchors) { - const anchorIndex = this.findIndex(this.intervals[this.index], this.anchors) - 1; - this.index = this.findIndex(this.anchors[anchorIndex], this.intervals); - } - else - this.index--; + this.index--; } this.pause(); } @@ -125,15 +118,8 @@ export class HistorySelectorComponent implements OnInit, OnChanges { this.pause(); } - findIndex(value, array: any[]) { - let i = 0; - while (array[i] < value) { - i++; - }; - return i; - } - changeIndex() { - this.timeUpdated.emit(this.intervals[this.index]); + this.currentTime = this.minTime + this.index * this.step; + this.timeUpdated.emit(this.currentTime); } }