Browse Source

trip-animation map provider & custom markers

pull/2535/head
Artem Halushko 7 years ago
parent
commit
5e65f2a48a
  1. 3
      ui-ngx/angular.json
  2. 65
      ui-ngx/src/app/core/schema-utils.ts
  3. 89
      ui-ngx/src/app/core/utils.ts
  4. 5
      ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts
  5. 2
      ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts
  6. 3
      ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.interface.ts
  7. 95
      ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget2.ts
  8. 16
      ui-ngx/src/app/modules/home/components/widget/lib/maps/maps-utils.ts
  9. 34
      ui-ngx/src/app/modules/home/components/widget/lib/maps/markers.scss
  10. 23
      ui-ngx/src/app/modules/home/components/widget/lib/maps/markers.ts
  11. 371
      ui-ngx/src/app/modules/home/components/widget/lib/maps/schemes.ts
  12. 3
      ui-ngx/src/app/modules/home/components/widget/trip-animation/trip-animation.component.html
  13. 46
      ui-ngx/src/app/modules/home/components/widget/trip-animation/trip-animation.component.ts
  14. 38
      ui-ngx/src/app/shared/components/time/history-selector/history-selector.component.ts
  15. 3
      ui-ngx/src/polyfills.ts

3
ui-ngx/angular.json

@ -38,7 +38,8 @@
"src/app/shared/components/json-form/react/json-form.scss",
"node_modules/rc-select/assets/index.less",
"node_modules/jstree-bootstrap-theme/dist/themes/proton/style.min.css",
"node_modules/leaflet/dist/leaflet.css"
"node_modules/leaflet/dist/leaflet.css",
"src/app/modules/home/components/widget/lib/maps/markers.scss"
],
"stylePreprocessorOptions": {
"includePaths": [

65
ui-ngx/src/app/core/schema-utils.ts

@ -0,0 +1,65 @@
export function initSchema() {
return {
schema: {
type: "object",
properties: {},
required: []
},
form: [],
groupInfoes: []
};
}
export function addGroupInfo(schema, title: string) {
schema.groupInfoes.push({
"formIndex": schema.groupInfoes?.length || 0,
"GroupTitle": title
});
}
export function addToSchema(schema, newSchema) {
Object.assign(schema.schema.properties, newSchema.schema.properties);
schema.schema.required = schema.schema.required.concat(newSchema.schema.required);
schema.form.push(newSchema.form);
}
export function mergeSchemes(schemes: any[]) {
return schemes.reduce((finalSchema, schema) => {
return {
schema: {
properties: {
...finalSchema.schema.properties,
...schema.schema.properties
},
required: [
...finalSchema.schema.required,
...schema.schema.required
]
},
form: [
...finalSchema.form,
...schema.form
]
}
}, initSchema());
}
export function addCondition(schema, condition: String) {
schema.form = schema.form.map(element => {
if (typeof element === 'string') {
return {
key: element,
condition: condition
}
}
if (typeof element == 'object') {
if (element.condition) {
element.condition += ' && ' + condition
}
else element.condition = condition;
}
return element;
});
return schema;
}

89
ui-ngx/src/app/core/utils.ts

@ -452,54 +452,55 @@ export function aspectCache(imageUrl: string): Observable<number> {
export function parseArray(input: any[]): any[] {
let alliases: any = _(input).groupBy(el => el?.datasource?.aliasName).values().value();
return alliases.map((alliasArray, dsIndex) =>
alliasArray[0].data.map((el, i) => {
const obj = {
aliasName: alliasArray[0]?.datasource?.aliasName,
$datasource: alliasArray[0]?.datasource,
dsIndex: dsIndex,
time: el[0]
};
alliasArray.forEach(el => {
obj[el?.dataKey?.label] = el?.data[i][1];
obj[el?.dataKey?.label + '|ts'] = el?.data[0][0];
if (el?.dataKey?.label == 'type') {
obj['deviceType'] = el?.data[0][1];
}
});
return obj;
})
);
}
export function parseData(input: any[]): any[] {
return _(input).groupBy(el => el?.datasource?.aliasName).values().value().map((alliasArray, i) => {
alliasArray[0].data.map((el, i) => {
const obj = {
aliasName: alliasArray[0]?.datasource?.aliasName,
entityName: alliasArray[0]?.datasource?.entityName,
$datasource: alliasArray[0]?.datasource,
dsIndex: i
aliasName: alliasArray[0]?.datasource?.aliasName,
entityName: alliasArray[0]?.datasource?.entityName,
$datasource: alliasArray[0]?.datasource,
dsIndex: dsIndex,
time: el[0]
};
alliasArray.forEach(el => {
obj[el?.dataKey?.label] = el?.data[0][1];
obj[el?.dataKey?.label + '|ts'] = el?.data[0][0];
if (el?.dataKey?.label == 'type') {
obj['deviceType'] = el?.data[0][1];
}
obj[el?.dataKey?.label] = el?.data[i][1];
obj[el?.dataKey?.label + '|ts'] = el?.data[0][0];
if (el?.dataKey?.label == 'type') {
obj['deviceType'] = el?.data[0][1];
}
});
return obj;
})
);
}
export function parseData(input: any[]): any[] {
return _(input).groupBy(el => el?.datasource?.aliasName).values().value().map((alliasArray, i) => {
const obj = {
aliasName: alliasArray[0]?.datasource?.aliasName,
entityName: alliasArray[0]?.datasource?.entityName,
$datasource: alliasArray[0]?.datasource,
dsIndex: i
};
alliasArray.forEach(el => {
obj[el?.dataKey?.label] = el?.data[0][1];
obj[el?.dataKey?.label + '|ts'] = el?.data[0][0];
if (el?.dataKey?.label == 'type') {
obj['deviceType'] = el?.data[0][1];
}
});
return obj;
});
}
export function safeExecute(func: Function, params = []) {
let res = null;
if (func && typeof (func) == "function") {
try {
res = func(...params);
}
catch (err) {
console.error(err);
res = null;
}
try {
res = func(...params);
}
catch (err) {
console.error(err);
res = null;
}
}
return res;
}
@ -507,13 +508,13 @@ export function safeExecute(func: Function, params = []) {
export function parseFunction(source: string, params: string[] = []): Function {
let res = null;
if (source?.length) {
try {
res = new Function(...params, source);
}
catch (err) {
console.error(err);
res = null;
}
try {
res = new Function(...params, source);
}
catch (err) {
console.error(err);
res = null;
}
}
return res;
}

5
ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts

@ -122,6 +122,11 @@ export default abstract class LeafletMap {
////Markers
updateMarkers(markersData) {
markersData.forEach(data => {
if(data.rotationAngle){
this.options.icon= L.divIcon({
html: `<div class="arrow" style="transform: rotate(${data.rotationAngle}deg)"><div>`
})
}
if (this.markers.get(data.aliasName)) {
this.updateMarker(data.aliasName, data, markersData, this.options as MarkerSettings)
}

2
ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts

@ -18,6 +18,7 @@ export interface MapOptions {
useDefaultCenterPosition?: boolean,
gmDefaultMapType?: string,
useLabelFunction: string;
icon?: any;
}
export enum MapProviders {
@ -29,6 +30,7 @@ export enum MapProviders {
}
export interface MarkerSettings extends MapOptions {
icon?: any;
showLabel?: boolean,
draggable?: boolean,
displayTooltip?: boolean,

3
ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.interface.ts

@ -8,7 +8,8 @@ export interface MapWidgetInterface {
}
export interface MapWidgetStaticInterface {
settingsSchema(mapProvider, drawRoutes): Object;
settingsSchema(mapProvider?, drawRoutes?): Object;
getProvidersSchema():Object
dataKeySettingsSchema(): Object;
actionSources(): Object;
}

95
ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget2.ts

@ -15,6 +15,7 @@ import {
import { MapWidgetStaticInterface, MapWidgetInterface } from './map-widget.interface';
import { OpenStreetMap, TencentMap, GoogleMap, HEREMap, ImageMap } from './providers';
import { parseFunction, parseArray, parseData } from '@app/core/utils';
import { initSchema, addToSchema, mergeSchemes, addCondition, addGroupInfo } from '@app/core/schema-utils';
export class MapWidgetController implements MapWidgetInterface {
@ -73,7 +74,7 @@ export class MapWidgetController implements MapWidgetInterface {
this.map.updateMarkers(parseData(this.data));
}
public updateHistoryData(dataSources){
public updateHistoryData(dataSources) {
dataSources.map()
}
@ -93,90 +94,28 @@ export class MapWidgetController implements MapWidgetInterface {
return {};
}
public static getProvidersSchema(){
return mergeSchemes([mapProviderSchema,
...Object.values(providerSets)?.map(
setting => addCondition(setting?.schema, `model.provider === '${setting.name}'`))])
}
public static settingsSchema(mapProvider, drawRoutes): Object {
//const providerInfo = providerSets[mapProvider];
let schema = initSchema();
addToSchema(schema,this.getProvidersSchema());
function initSchema() {
return {
schema: {
type: "object",
properties: {},
required: []
},
form: [],
groupInfoes: []
};
}
function addGroupInfo(title: string) {
schema.groupInfoes.push({
"formIndex": schema.groupInfoes?.length || 0,
"GroupTitle": title
});
}
function addToSchema(newSchema) {
Object.assign(schema.schema.properties, newSchema.schema.properties);
schema.schema.required = schema.schema.required.concat(newSchema.schema.required);
schema.form.push(newSchema.form);//schema.form.concat(commonMapSettingsSchema.form);
}
function mergeSchemes(schemes: any[]) {
return schemes.reduce((finalSchema, schema) => {
return {
schema: {
properties: {
...finalSchema.schema.properties,
...schema.schema.properties
},
required: [
...finalSchema.schema.required,
...schema.schema.required
]
},
form: [
...finalSchema.form,
...schema.form
]
}
}, initSchema());
}
function addCondition(schema, condition: String) {
schema.form = schema.form.map(element => {
if (typeof element === 'string') {
return {
key: element,
condition: condition
}
}
if (typeof element == 'object') {
if (element.condition) {
element.condition += ' && ' + condition
}
else element.condition = condition;
}
return element;
});
return schema;
}
addToSchema(mergeSchemes([mapProviderSchema,
...Object.values(providerSets)?.map(
setting => addCondition(setting?.schema, `model.provider === '${setting.name}'`))]));
addGroupInfo("Map Provider Settings");
addToSchema(commonMapSettingsSchema);
addGroupInfo("Common Map Settings");
addGroupInfo(schema, "Map Provider Settings");
addToSchema(schema, commonMapSettingsSchema);
addGroupInfo(schema, "Common Map Settings");
if (drawRoutes) {
addToSchema(routeMapSettingsSchema);
addGroupInfo("Route Map Settings");
addToSchema(schema, routeMapSettingsSchema);
addGroupInfo(schema, "Route Map Settings");
} else if (mapProvider !== 'image-map') {
let clusteringSchema = mergeSchemes([markerClusteringSettingsSchemaLeaflet, markerClusteringSettingsSchema])
addToSchema(clusteringSchema);
addGroupInfo("Markers Clustering Settings");
addToSchema(schema, clusteringSchema);
addGroupInfo(schema, "Markers Clustering Settings");
}
console.log(11, schema);
@ -243,7 +182,7 @@ const defaultSettings = {
latKeyName: 'latitude',
lngKeyName: 'longitude',
polygonKeyName: 'coordinates',
showLabel: true,
showLabel: false,
label: "${entityName}",
showTooltip: false,
useDefaultCenterPosition: false,

16
ui-ngx/src/app/modules/home/components/widget/lib/maps/maps-utils.ts

@ -30,6 +30,12 @@ export function interpolateArray(originData, interpolatedIntervals) {
return (intermediateMoment - firsMoment) / (secondMoment - firsMoment);
};
function findAngle(startPoint, endPoint) {
let angle = -Math.atan2(endPoint.latitude - startPoint.longitude, endPoint.longitude - startPoint.latitude);
angle = angle * 180 / Math.PI;
return parseInt(angle.toFixed(2));
}
const result = {};
for (let i = 1, j = 0; i < originData.length, j < interpolatedIntervals.length;) {
@ -37,10 +43,16 @@ export function interpolateArray(originData, interpolatedIntervals) {
while (originData[i].time < currentTime) i++;
const before = originData[i - 1];
const after = originData[i];
result[currentTime] = (interpolateOnPointSegment(
const interpolation = interpolateOnPointSegment(
new L.Point(before.latitude, before.longitude),
new L.Point(after.latitude, after.longitude),
getRatio(before.time, after.time, currentTime)));
getRatio(before.time, after.time, currentTime));
result[currentTime] = ({
...originData[i],
rotationAngle: findAngle(before, after),
latitude: interpolation.x,
longitude: interpolation.y
});
j++;
}

34
ui-ngx/src/app/modules/home/components/widget/lib/maps/markers.scss

@ -0,0 +1,34 @@
.arrow{
background:#222;
text-align:center;
font-size:180%;
margin:2em;
font-family: Calibri, arial, sans-serif;
color:white;
padding-top:1.8em;
display:inline-block;/* or block */
position:relative;
border-color:white;
text-decoration:none;
transition:all .3s ease-out;
}
.arrow:before{
content:'▲';
font-size:.9em;
position:absolute;
top:0;
left:50%;
margin-left:-.7em;
border:solid .13em white;
border-radius:10em;
width:1.4em;
height:1.4em;
line-height:1.3em;
border-color:inherit;
transition:transform .5s ease-in;
}
.arrow:hover{
color:pink;
border-color:pink;
}

23
ui-ngx/src/app/modules/home/components/widget/lib/maps/markers.ts

@ -25,7 +25,7 @@ export class Marker {
this.leafletMarker.setIcon(iconInfo.icon);
if (settings.showLabel) {
this.tooltipOffset = [0, -iconInfo.size[1] + 10];
this.updateMarkerLabel(settings)
// this.updateMarkerLabel(settings)
}
this.leafletMarker.addTo(map)
@ -55,8 +55,6 @@ export class Marker {
this.leafletMarker.setLatLng(position);
}
updateMarkerLabel(settings) {
function getText(template, data) {
@ -74,7 +72,7 @@ export class Marker {
return res;
}
this.leafletMarker.unbindTooltip();
if (settings.showLabel) {
if (settings.useLabelFunction) {
@ -104,9 +102,20 @@ export class Marker {
}
createMarkerIcon(onMarkerIconReady) {
const currentImage = this.settings.useMarkerImageFunction ?
safeExecute(this.settings.markerImageFunction, [this.data, this.settings.markerImages, this.dataSources, this.data.dsIndex]) : this.settings.currentImage;
// var opMap = this;
if (this.settings.icon) {
onMarkerIconReady({
size: [30,30],
icon: this.settings.icon,
});
return;
}
let currentImage = this.settings.useMarkerImageFunction ?
safeExecute(this.settings.markerImageFunction,
[this.data, this.settings.markerImages, this.dataSources, this.data.dsIndex]) : this.settings.currentImage;
if (currentImage && currentImage.url) {
aspectCache(currentImage.url).subscribe(
(aspect) => {

371
ui-ngx/src/app/modules/home/components/widget/lib/maps/schemes.ts

@ -856,4 +856,373 @@ export const mapProviderSchema =
]
}
]
};
};
export const tripAnimationSchema = {
"schema": {
"title": "Openstreet Map Configuration",
"type": "object",
"properties": {
"normalizationStep": {
"title": "Normalization data step (ms)",
"type": "number",
"default": 1000
},
"latKeyName": {
"title": "Latitude key name",
"type": "string",
"default": "latitude"
},
"lngKeyName": {
"title": "Longitude key name",
"type": "string",
"default": "longitude"
},
"polKeyName": {
"title": "Polygon key name",
"type": "string",
"default": "coordinates"
},
"showLabel": {
"title": "Show label",
"type": "boolean",
"default": true
},
"label": {
"title": "Label (pattern examples: '${entityName}', '${entityName}: (Text ${keyName} units.)' )",
"type": "string",
"default": "${entityName}"
},
"useLabelFunction": {
"title": "Use label function",
"type": "boolean",
"default": false
},
"labelFunction": {
"title": "Label function: f(data, dsData, dsIndex)",
"type": "string"
},
"showTooltip": {
"title": "Show tooltip",
"type": "boolean",
"default": true
},
"tooltipColor": {
"title": "Tooltip background color",
"type": "string",
"default": "#fff"
},
"tooltipFontColor": {
"title": "Tooltip font color",
"type": "string",
"default": "#000"
},
"tooltipOpacity": {
"title": "Tooltip opacity (0-1)",
"type": "number",
"default": 1
},
"tooltipPattern": {
"title": "Tooltip (for ex. 'Text ${keyName} units.' or <link-act name='my-action'>Link text</link-act>')",
"type": "string",
"default": "<b>${entityName}</b><br/><br/><b>Latitude:</b> ${latitude:7}<br/><b>Longitude:</b> ${longitude:7}"
},
"useTooltipFunction": {
"title": "Use tooltip function",
"type": "boolean",
"default": false
},
"tooltipFunction": {
"title": "Tooltip function: f(data, dsData, dsIndex)",
"type": "string"
},
"color": {
"title": "Path color",
"type": "string"
},
"strokeWeight": {
"title": "Stroke weight",
"type": "number",
"default": 2
},
"strokeOpacity": {
"title": "Stroke opacity",
"type": "number",
"default": 1
},
"useColorFunction": {
"title": "Use path color function",
"type": "boolean",
"default": false
},
"colorFunction": {
"title": "Path color function: f(data, dsData, dsIndex)",
"type": "string"
},
"usePolylineDecorator": {
"title": "Use path decorator",
"type": "boolean",
"default": false
},
"decoratorSymbol": {
"title": "Decorator symbol",
"type": "string",
"default": "arrowHead"
},
"decoratorSymbolSize": {
"title": "Decorator symbol size (px)",
"type": "number",
"default": 10
},
"useDecoratorCustomColor": {
"title": "Use path decorator custom color",
"type": "boolean",
"default": false
},
"decoratorCustomColor": {
"title": "Decorator custom color",
"type": "string",
"default": "#000"
},
"decoratorOffset": {
"title": "Decorator offset",
"type": "string",
"default": "20px"
},
"endDecoratorOffset": {
"title": "End decorator offset",
"type": "string",
"default": "20px"
},
"decoratorRepeat": {
"title": "Decorator repeat",
"type": "string",
"default": "20px"
},
"showPolygon": {
"title": "Show polygon",
"type": "boolean",
"default": false
},
"polygonTooltipPattern": {
"title": "Tooltip (for ex. 'Text ${keyName} units.' or <link-act name='my-action'>Link text</link-act>')",
"type": "string",
"default": "<b>${entityName}</b><br/><br/><b>TimeStamp:</b> ${ts:7}"
},
"usePolygonTooltipFunction": {
"title": "Use polygon tooltip function",
"type": "boolean",
"default": false
},
"polygonTooltipFunction": {
"title": "Polygon tooltip function: f(data, dsData, dsIndex)",
"type": "string"
},
"polygonColor": {
"title": "Polygon color",
"type": "string"
},
"polygonOpacity": {
"title": "Polygon opacity",
"type": "number",
"default": 0.5
},
"polygonStrokeColor": {
"title": "Polygon border color",
"type": "string"
},
"polygonStrokeOpacity": {
"title": "Polygon border opacity",
"type": "number",
"default": 1
},
"polygonStrokeWeight": {
"title": "Polygon border weight",
"type": "number",
"default": 1
},
"usePolygonColorFunction": {
"title": "Use polygon color function",
"type": "boolean",
"default": false
},
"polygonColorFunction": {
"title": "Polygon Color function: f(data, dsData, dsIndex)",
"type": "string"
},
"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
},
"autocloseTooltip": {
"title": "Auto-close point popup",
"type": "boolean",
"default": true
},
"markerImage": {
"title": "Custom marker image",
"type": "string"
},
"markerImageSize": {
"title": "Custom marker image size (px)",
"type": "number",
"default": 34
},
"rotationAngle": {
"title": "Set additional rotation angle for marker (deg)",
"type": "number",
"default": 180
},
"useMarkerImageFunction": {
"title": "Use marker image function",
"type": "boolean",
"default": false
},
"markerImageFunction": {
"title": "Marker image function: f(data, images, dsData, dsIndex)",
"type": "string"
},
"markerImages": {
"title": "Marker images",
"type": "array",
"items": {
"title": "Marker image",
"type": "string"
}
}
},
"required": []
},
"form": [{
"key": "mapProvider",
"type": "rc-select",
"multiple": false,
"items": [{
"value": "OpenStreetMap.Mapnik",
"label": "OpenStreetMap.Mapnik (Default)"
}, {
"value": "OpenStreetMap.BlackAndWhite",
"label": "OpenStreetMap.BlackAndWhite"
}, {
"value": "OpenStreetMap.HOT",
"label": "OpenStreetMap.HOT"
}, {
"value": "Esri.WorldStreetMap",
"label": "Esri.WorldStreetMap"
}, {
"value": "Esri.WorldTopoMap",
"label": "Esri.WorldTopoMap"
}, {
"value": "CartoDB.Positron",
"label": "CartoDB.Positron"
}, {
"value": "CartoDB.DarkMatter",
"label": "CartoDB.DarkMatter"
}]
}, "normalizationStep", "latKeyName", "lngKeyName", "polKeyName", "showLabel", "label", "useLabelFunction", {
"key": "labelFunction",
"type": "javascript"
}, "showTooltip", {
"key": "tooltipColor",
"type": "color"
}, {
"key": "tooltipFontColor",
"type": "color"
}, "tooltipOpacity", {
"key": "tooltipPattern",
"type": "textarea"
}, "useTooltipFunction", {
"key": "tooltipFunction",
"type": "javascript"
}, {
"key": "color",
"type": "color"
}, "useColorFunction", {
"key": "colorFunction",
"type": "javascript"
}, "usePolylineDecorator", {
"key": "decoratorSymbol",
"type": "rc-select",
"multiple": false,
"items": [{
"value": "arrowHead",
"label": "Arrow"
}, {
"value": "dash",
"label": "Dash"
}]
}, "decoratorSymbolSize", "useDecoratorCustomColor", {
"key": "decoratorCustomColor",
"type": "color"
}, {
"key": "decoratorOffset",
"type": "textarea"
}, {
"key": "endDecoratorOffset",
"type": "textarea"
}, {
"key": "decoratorRepeat",
"type": "textarea"
}, "strokeWeight", "strokeOpacity", "showPolygon", {
"key": "polygonTooltipPattern",
"type": "textarea"
}, "usePolygonTooltipFunction", {
"key": "polygonTooltipFunction",
"type": "javascript"
}, {
"key": "polygonColor",
"type": "color"
}, "polygonOpacity", {
"key": "polygonStrokeColor",
"type": "color"
}, "polygonStrokeOpacity", "polygonStrokeWeight", "usePolygonColorFunction", {
"key": "polygonColorFunction",
"type": "javascript"
}, "showPoints", {
"key": "pointColor",
"type": "color"
}, "pointSize", "usePointAsAnchor", {
"key": "pointAsAnchorFunction",
"type": "javascript"
}, "pointTooltipOnRightPanel", "autocloseTooltip", {
"key": "markerImage",
"type": "image"
}, "markerImageSize", "rotationAngle", "useMarkerImageFunction",
{
"key": "markerImageFunction",
"type": "javascript"
}, {
"key": "markerImages",
"items": [
{
"key": "markerImages[]",
"type": "image"
}
]
}]
}

3
ui-ngx/src/app/modules/home/components/widget/trip-animation/trip-animation.component.html

@ -1,4 +1,3 @@
<div class="map" #map ></div>
<div>{{historicalData?.lenth}}</div>
<tb-history-selector *ngIf="historicalData" [settings]="ctx.settings" [intervals]="intervals"
<tb-history-selector *ngIf="historicalData" [settings]="settings" [intervals]="intervals"
(onTimeUpdated)="timeUpdated($event)"></tb-history-selector>

46
ui-ngx/src/app/modules/home/components/widget/trip-animation/trip-animation.component.ts

@ -1,8 +1,12 @@
import { Component, OnInit, Input, ViewChild, AfterViewInit, ChangeDetectorRef } from '@angular/core';
import { MapWidgetController } from '../lib/maps/map-widget2';
import { MapWidgetController, TbMapWidgetV2 } from '../lib/maps/map-widget2';
import { MapProviders } from '../lib/maps/map-models';
import { parseArray } from '@app/core/utils';
import { interpolateArray } from '../lib/maps/maps-utils';
import tinycolor from "tinycolor2";
import { initSchema, addToSchema, addGroupInfo } from '@app/core/schema-utils';
import { tripAnimationSchema } from '../lib/maps/schemes';
import L from 'leaflet';
@Component({
selector: 'trip-animation',
@ -18,35 +22,45 @@ export class TripAnimationComponent implements OnInit, AfterViewInit {
mapWidget: MapWidgetController;
historicalData;
intervals;
normalizationStep = 500;
normalizationStep = 1000;
interpolatedData = [];
widgetConfig;
settings;
constructor(private cd: ChangeDetectorRef) { }
ngOnInit(): void {
this.widgetConfig = this.ctx.widgetConfig;
const settings = {
normalizationStep: 1000,
buttonColor: tinycolor(this.widgetConfig.color).setAlpha(0.54).toRgbString(),
disabledButtonColor: tinycolor(this.widgetConfig.color).setAlpha(0.3).toRgbString(),
rotationAngle: 0
}
this.settings = { ...settings, ...this.ctx.settings };
//this.ctx.settings = settings;
console.log("TripAnimationComponent -> ngOnInit -> this.ctx.settings", this.ctx.settings)
let subscription = this.ctx.subscriptions[Object.keys(this.ctx.subscriptions)[0]];
if (subscription) subscription.callbacks.onDataUpdated = (updated) => {
this.historicalData = parseArray(this.ctx.data);
this.historicalData.forEach(el => {
console.log("TripAnimationComponent -> if -> el", el)
this.historicalData.forEach(ds => ds.forEach(el => {
el.longitude += (Math.random() - 0.5)
el.latitude += (Math.random() - 0.5)
});
}));
this.calculateIntervals();
this.timeUpdated(this.intervals[0]);
this.cd.detectChanges();
this.mapWidget.map.map.invalidateSize();
}
}
ngAfterViewInit() {
this.mapWidget = new MapWidgetController(MapProviders.openstreet, false, this.ctx, this.mapContainer.nativeElement);
this.mapWidget.data
}
timeUpdated(time) {
//this.mapWidget.ma
const currentPosition = this.interpolatedData.map(dataSource=>dataSource[time]);
console.log("TripAnimationComponent -> timeUpdated -> currentPosition", currentPosition)
const currentPosition = this.interpolatedData.map(dataSource => dataSource[time]);
this.mapWidget.map.updateMarkers(currentPosition);
}
calculateIntervals() {
@ -57,9 +71,17 @@ export class TripAnimationComponent implements OnInit, AfterViewInit {
}
this.intervals.push(dataSource[dataSource.length - 1]?.time);
this.interpolatedData[index] = interpolateArray(dataSource, this.intervals);
console.log("TripAnimationComponent -> calculateIntervals -> this.intervals", this.intervals)
});
}
static getSettingsSchema() {
let schema = initSchema();
addToSchema(schema, TbMapWidgetV2.getProvidersSchema());
addGroupInfo(schema, "Map Provider Settings");
addToSchema(schema, tripAnimationSchema);
addGroupInfo(schema, "Trip Animation Settings");
return schema;
}
}
export let TbTripAnimationWidget = TripAnimationComponent;

38
ui-ngx/src/app/shared/components/time/history-selector/history-selector.component.ts

@ -1,5 +1,5 @@
import { Component, OnInit, OnChanges, Input, Output, EventEmitter, ChangeDetectorRef } from '@angular/core';
import { interval } from 'rxjs';
import { interval, Subscription } from 'rxjs';
import { filter, tap } from 'rxjs/operators';
@Component({
@ -34,23 +34,25 @@ export class HistorySelectorComponent implements OnInit, OnChanges {
play() {
this.playing = true;
this.interval = interval(1000 / this.speed)
.pipe(
filter(() => this.playing),
tap(() => this.index++)).subscribe(() => {
if (this.index < this.maxTimeIndex) {
this.cd.detectChanges();
this.onTimeUpdated.emit(this.intervals[this.index]);
}
else {
this.interval.complete();
}
}, err => {
console.log(err);
}, () => {
this.index = this.minTimeIndex;
this.playing = false;
})
if (!this.interval)
this.interval = interval(1000 / this.speed)
.pipe(
filter(() => this.playing),
tap(() => this.index++)).subscribe(() => {
if (this.index < this.maxTimeIndex) {
this.cd.detectChanges();
this.onTimeUpdated.emit(this.intervals[this.index]);
}
else {
this.interval.complete();
}
}, err => {
console.log(err);
}, () => {
this.index = this.minTimeIndex;
this.playing = false;
this.interval = null;
});
}
pause() {

3
ui-ngx/src/polyfills.ts

@ -93,6 +93,7 @@ import { TbAnalogueRadialGauge } from '@home/components/widget/lib/analogue-radi
import { TbAnalogueLinearGauge } from '@home/components/widget/lib/analogue-linear-gauge';
import { TbCanvasDigitalGauge } from '@home/components/widget/lib/digital-gauge';
import { TbMapWidgetV2 } from '@home/components/widget/lib/maps/map-widget2';
import { TbTripAnimationWidget } from '@app/modules/home/components/widget/trip-animation/trip-animation.component';
import * as tinycolor_ from 'tinycolor2';
@ -106,3 +107,5 @@ const tinycolor = tinycolor_;
(window as any).TbAnalogueLinearGauge = TbAnalogueLinearGauge;
(window as any).TbCanvasDigitalGauge = TbCanvasDigitalGauge;
(window as any).TbMapWidgetV2 = TbMapWidgetV2;
(window as any).TbTripAnimationWidget = TbTripAnimationWidget;
console.log("TbTripAnimationWidget", TbTripAnimationWidget)

Loading…
Cancel
Save