commit
c7ec88cc13
@ -389,6 +389,9 @@ export default abstract class LeafletMap {
|
|||||||
const poly = this.polylines.get(name);
|
const poly = this.polylines.get(name);
|
||||||
if (poly) {
|
if (poly) {
|
||||||
this.map.removeLayer(poly.leafletPoly);
|
this.map.removeLayer(poly.leafletPoly);
|
||||||
|
if (poly.polylineDecorator) {
|
||||||
|
this.map.removeLayer(poly.polylineDecorator);
|
||||||
|
}
|
||||||
this.polylines.delete(name);
|
this.polylines.delete(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -164,9 +164,23 @@ export interface HistorySelectSettings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type TripAnimationSettings = {
|
export type TripAnimationSettings = {
|
||||||
|
showPoints: boolean;
|
||||||
pointColor: string;
|
pointColor: string;
|
||||||
pointSize: number;
|
pointSize: number;
|
||||||
pointTooltipOnRightPanel: boolean;
|
pointTooltipOnRightPanel: boolean;
|
||||||
|
usePointAsAnchor: boolean;
|
||||||
|
normalizationStep: number;
|
||||||
|
showPolygon: boolean;
|
||||||
|
latKeyName: string;
|
||||||
|
lngKeyName: string;
|
||||||
|
rotationAngle: number;
|
||||||
|
label: string;
|
||||||
|
tooltipPattern: string;
|
||||||
|
useTooltipFunction :boolean;
|
||||||
|
useLabelFunction:boolean;
|
||||||
|
pointAsAnchorFunction: GenericFunction;
|
||||||
|
tooltipFunction: GenericFunction;
|
||||||
|
labelFunction: GenericFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type actionsHandler = ($event: Event, datasource: Datasource) => void;
|
export type actionsHandler = ($event: Event, datasource: Datasource) => void;
|
||||||
|
|||||||
@ -41,6 +41,7 @@ import { AttributeScope, DataKeyType, LatestTelemetry } from '@shared/models/tel
|
|||||||
import { AttributeService } from '@core/http/attribute.service';
|
import { AttributeService } from '@core/http/attribute.service';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { UtilsService } from '@core/services/utils.service';
|
import { UtilsService } from '@core/services/utils.service';
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
// @dynamic
|
// @dynamic
|
||||||
export class MapWidgetController implements MapWidgetInterface {
|
export class MapWidgetController implements MapWidgetInterface {
|
||||||
@ -90,9 +91,9 @@ export class MapWidgetController implements MapWidgetInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static getProvidersSchema(mapProvider: MapProviders, ignoreImageMap = false) {
|
public static getProvidersSchema(mapProvider: MapProviders, ignoreImageMap = false) {
|
||||||
|
const providerSchema = _.cloneDeep(mapProviderSchema);
|
||||||
if (mapProvider)
|
if (mapProvider)
|
||||||
mapProviderSchema.schema.properties.provider.default = mapProvider;
|
providerSchema.schema.properties.provider.default = mapProvider;
|
||||||
const providerSchema = mapProviderSchema;
|
|
||||||
if (ignoreImageMap) {
|
if (ignoreImageMap) {
|
||||||
providerSchema.form[0].items = providerSchema.form[0]?.items.filter(item => item.value !== 'image-map');
|
providerSchema.form[0].items = providerSchema.form[0]?.items.filter(item => item.value !== 'image-map');
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,7 +19,7 @@ import tinycolor from 'tinycolor2';
|
|||||||
|
|
||||||
import { AfterViewInit, ChangeDetectorRef, Component, Input, OnInit, SecurityContext, ViewChild } from '@angular/core';
|
import { AfterViewInit, ChangeDetectorRef, Component, Input, OnInit, SecurityContext, ViewChild } from '@angular/core';
|
||||||
import { MapWidgetController, TbMapWidgetV2 } from '../lib/maps/map-widget2';
|
import { MapWidgetController, TbMapWidgetV2 } from '../lib/maps/map-widget2';
|
||||||
import { FormattedData, MapProviders } from '../lib/maps/map-models';
|
import { FormattedData, MapProviders, TripAnimationSettings } from '../lib/maps/map-models';
|
||||||
import { addCondition, addGroupInfo, addToSchema, initSchema } from '@app/core/schema-utils';
|
import { addCondition, addGroupInfo, addToSchema, initSchema } from '@app/core/schema-utils';
|
||||||
import { mapPolygonSchema, pathSchema, pointSchema, tripAnimationSchema } from '../lib/maps/schemes';
|
import { mapPolygonSchema, pathSchema, pointSchema, tripAnimationSchema } from '../lib/maps/schemes';
|
||||||
import { DomSanitizer } from '@angular/platform-browser';
|
import { DomSanitizer } from '@angular/platform-browser';
|
||||||
@ -56,17 +56,14 @@ export class TripAnimationComponent implements OnInit, AfterViewInit {
|
|||||||
historicalData: FormattedData[][];
|
historicalData: FormattedData[][];
|
||||||
normalizationStep: number;
|
normalizationStep: number;
|
||||||
interpolatedTimeData = [];
|
interpolatedTimeData = [];
|
||||||
intervals = [];
|
|
||||||
widgetConfig: WidgetConfig;
|
widgetConfig: WidgetConfig;
|
||||||
settings;
|
settings: TripAnimationSettings;
|
||||||
mainTooltip = '';
|
mainTooltip = '';
|
||||||
visibleTooltip = false;
|
visibleTooltip = false;
|
||||||
activeTrip: FormattedData;
|
activeTrip: FormattedData;
|
||||||
label;
|
label;
|
||||||
minTime: number;
|
minTime: number;
|
||||||
minTimeFormat: string;
|
|
||||||
maxTime: number;
|
maxTime: number;
|
||||||
maxTimeFormat: string;
|
|
||||||
anchors: number[] = [];
|
anchors: number[] = [];
|
||||||
useAnchors: boolean;
|
useAnchors: boolean;
|
||||||
currentTime: number;
|
currentTime: number;
|
||||||
@ -98,15 +95,15 @@ export class TripAnimationComponent implements OnInit, AfterViewInit {
|
|||||||
this.settings = { ...settings, ...this.ctx.settings };
|
this.settings = { ...settings, ...this.ctx.settings };
|
||||||
this.useAnchors = this.settings.showPoints && this.settings.usePointAsAnchor;
|
this.useAnchors = this.settings.showPoints && this.settings.usePointAsAnchor;
|
||||||
this.settings.pointAsAnchorFunction = parseFunction(this.settings.pointAsAnchorFunction, ['data', 'dsData', 'dsIndex']);
|
this.settings.pointAsAnchorFunction = parseFunction(this.settings.pointAsAnchorFunction, ['data', 'dsData', 'dsIndex']);
|
||||||
this.settings.fitMapBounds = true;
|
this.settings.tooltipFunction = parseFunction(this.settings.tooltipFunction, ['data', 'dsData', 'dsIndex']);
|
||||||
|
this.settings.labelFunction = parseFunction(this.settings.labelFunction, ['data', 'dsData', 'dsIndex']);
|
||||||
this.normalizationStep = this.settings.normalizationStep;
|
this.normalizationStep = this.settings.normalizationStep;
|
||||||
const subscription = this.ctx.subscriptions[Object.keys(this.ctx.subscriptions)[0]];
|
const subscription = this.ctx.subscriptions[Object.keys(this.ctx.subscriptions)[0]];
|
||||||
if (subscription) subscription.callbacks.onDataUpdated = () => {
|
if (subscription) subscription.callbacks.onDataUpdated = () => {
|
||||||
this.historicalData = parseArray(this.ctx.data).filter(arr => arr.length);
|
this.historicalData = parseArray(this.ctx.data).filter(arr => arr.length);
|
||||||
if (this.historicalData.length) {
|
if (this.historicalData.length) {
|
||||||
this.activeTrip = this.historicalData[0][0];
|
|
||||||
this.calculateIntervals();
|
this.calculateIntervals();
|
||||||
this.timeUpdated(this.minTime);
|
this.timeUpdated(this.currentTime && this.currentTime > this.minTime ? this.currentTime : this.minTime);
|
||||||
}
|
}
|
||||||
this.mapWidget.map.map?.invalidateSize();
|
this.mapWidget.map.map?.invalidateSize();
|
||||||
this.cd.detectChanges();
|
this.cd.detectChanges();
|
||||||
@ -122,12 +119,7 @@ export class TripAnimationComponent implements OnInit, AfterViewInit {
|
|||||||
this.currentTime = time;
|
this.currentTime = time;
|
||||||
const currentPosition = this.interpolatedTimeData
|
const currentPosition = this.interpolatedTimeData
|
||||||
.map(dataSource => dataSource[time])
|
.map(dataSource => dataSource[time])
|
||||||
.filter(ds => ds)
|
.filter(ds => ds);
|
||||||
.map(ds => {
|
|
||||||
ds.minTime = this.minTimeFormat;
|
|
||||||
ds.maxTime = this.maxTimeFormat;
|
|
||||||
return ds;
|
|
||||||
});
|
|
||||||
if (isUndefined(currentPosition[0])) {
|
if (isUndefined(currentPosition[0])) {
|
||||||
const timePoints = Object.keys(this.interpolatedTimeData[0]).map(item => parseInt(item, 10));
|
const timePoints = Object.keys(this.interpolatedTimeData[0]).map(item => parseInt(item, 10));
|
||||||
for (let i = 1; i < timePoints.length; i++) {
|
for (let i = 1; i < timePoints.length; i++) {
|
||||||
@ -145,7 +137,7 @@ export class TripAnimationComponent implements OnInit, AfterViewInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.calcLabel();
|
this.calcLabel();
|
||||||
this.calcTooltip();
|
this.calcTooltip(currentPosition.find(position => position.entityName === this.activeTrip.entityName));
|
||||||
if (this.mapWidget) {
|
if (this.mapWidget) {
|
||||||
this.mapWidget.map.updatePolylines(this.interpolatedTimeData.map(ds => _.values(ds)), this.activeTrip);
|
this.mapWidget.map.updatePolylines(this.interpolatedTimeData.map(ds => _.values(ds)), this.activeTrip);
|
||||||
if (this.settings.showPolygon) {
|
if (this.settings.showPolygon) {
|
||||||
@ -167,11 +159,14 @@ export class TripAnimationComponent implements OnInit, AfterViewInit {
|
|||||||
calculateIntervals() {
|
calculateIntervals() {
|
||||||
this.historicalData.forEach((dataSource, index) => {
|
this.historicalData.forEach((dataSource, index) => {
|
||||||
this.minTime = dataSource[0]?.time || Infinity;
|
this.minTime = dataSource[0]?.time || Infinity;
|
||||||
this.minTimeFormat = this.minTime !== Infinity ? moment(this.minTime).format('YYYY-MM-DD HH:mm:ss') : '';
|
const minTimeFormat = this.minTime !== Infinity ? moment(this.minTime).format('YYYY-MM-DD HH:mm:ss') : '';
|
||||||
this.maxTime = dataSource[dataSource.length - 1]?.time || -Infinity;
|
this.maxTime = dataSource[dataSource.length - 1]?.time || -Infinity;
|
||||||
this.maxTimeFormat = this.maxTime !== -Infinity ? moment(this.maxTime).format('YYYY-MM-DD HH:mm:ss') : '';
|
const maxTimeFormat = this.maxTime !== -Infinity ? moment(this.maxTime).format('YYYY-MM-DD HH:mm:ss') : '';
|
||||||
this.interpolatedTimeData[index] = this.interpolateArray(dataSource);
|
this.interpolatedTimeData[index] = this.interpolateArray(dataSource, minTimeFormat, maxTimeFormat);
|
||||||
});
|
});
|
||||||
|
if(!this.activeTrip){
|
||||||
|
this.activeTrip = this.interpolatedTimeData.map(dataSource => dataSource[this.minTime]).filter(ds => ds)[0];
|
||||||
|
}
|
||||||
if (this.useAnchors) {
|
if (this.useAnchors) {
|
||||||
const anchorDate = Object.entries(_.union(this.interpolatedTimeData)[0]);
|
const anchorDate = Object.entries(_.union(this.interpolatedTimeData)[0]);
|
||||||
this.anchors = anchorDate
|
this.anchors = anchorDate
|
||||||
@ -180,39 +175,26 @@ export class TripAnimationComponent implements OnInit, AfterViewInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
calcTooltip = (point?: FormattedData, setTooltip = true) => {
|
calcTooltip = (point?: FormattedData) => {
|
||||||
if (!point) {
|
const data = point ? point : this.activeTrip;
|
||||||
point = this.activeTrip;
|
|
||||||
}
|
|
||||||
const data = {
|
|
||||||
...this.activeTrip,
|
|
||||||
maxTime: this.maxTimeFormat,
|
|
||||||
minTime: this.minTimeFormat
|
|
||||||
}
|
|
||||||
const tooltipPattern: string = this.settings.useTooltipFunction ?
|
const tooltipPattern: string = this.settings.useTooltipFunction ?
|
||||||
safeExecute(this.settings.tooolTipFunction, [data, this.historicalData, point.dsIndex]) : this.settings.tooltipPattern;
|
safeExecute(this.settings.tooltipFunction, [data, this.historicalData, point.dsIndex]) : this.settings.tooltipPattern;
|
||||||
const tooltipText = parseWithTranslation.parseTemplate(tooltipPattern, data, true);
|
const tooltipText = parseWithTranslation.parseTemplate(tooltipPattern, data, true);
|
||||||
if (setTooltip) {
|
|
||||||
this.mainTooltip = this.sanitizer.sanitize(
|
this.mainTooltip = this.sanitizer.sanitize(
|
||||||
SecurityContext.HTML, tooltipText);
|
SecurityContext.HTML, tooltipText);
|
||||||
this.cd.detectChanges();
|
this.cd.detectChanges();
|
||||||
}
|
|
||||||
this.activeTrip = point;
|
this.activeTrip = point;
|
||||||
return tooltipText;
|
return tooltipText;
|
||||||
}
|
}
|
||||||
|
|
||||||
calcLabel() {
|
calcLabel() {
|
||||||
const data = {
|
const data = this.activeTrip;
|
||||||
...this.activeTrip,
|
|
||||||
maxTime: this.maxTimeFormat,
|
|
||||||
minTime: this.minTimeFormat
|
|
||||||
}
|
|
||||||
const labelText: string = this.settings.useLabelFunction ?
|
const labelText: string = this.settings.useLabelFunction ?
|
||||||
safeExecute(this.settings.labelFunction, [data, this.historicalData, data.dsIndex]) : this.settings.label;
|
safeExecute(this.settings.labelFunction, [data, this.historicalData, data.dsIndex]) : this.settings.label;
|
||||||
this.label = (parseWithTranslation.parseTemplate(labelText, data, true));
|
this.label = (parseWithTranslation.parseTemplate(labelText, data, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
interpolateArray(originData: FormattedData[]) {
|
interpolateArray(originData: FormattedData[], minTimeFormat?: string, maxTimeFormat?: string) {
|
||||||
const result = {};
|
const result = {};
|
||||||
const latKeyName = this.settings.latKeyName;
|
const latKeyName = this.settings.latKeyName;
|
||||||
const lngKeyName = this.settings.lngKeyName;
|
const lngKeyName = this.settings.lngKeyName;
|
||||||
@ -221,6 +203,8 @@ export class TripAnimationComponent implements OnInit, AfterViewInit {
|
|||||||
const normalizeTime = this.minTime + Math.ceil((currentTime - this.minTime) / this.normalizationStep) * this.normalizationStep;
|
const normalizeTime = this.minTime + Math.ceil((currentTime - this.minTime) / this.normalizationStep) * this.normalizationStep;
|
||||||
result[normalizeTime] = {
|
result[normalizeTime] = {
|
||||||
...data,
|
...data,
|
||||||
|
minTime: minTimeFormat,
|
||||||
|
maxTime: maxTimeFormat,
|
||||||
rotationAngle: this.settings.rotationAngle
|
rotationAngle: this.settings.rotationAngle
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user