add some settings support

This commit is contained in:
Artem Halushko 2020-03-05 11:56:07 +02:00
parent 240f58948d
commit 6818c9932e
7 changed files with 182 additions and 84 deletions

View File

@ -98,7 +98,7 @@ export default abstract class LeafletMap {
this.map.invalidateSize(true); this.map.invalidateSize(true);
} }
createTool0tip(marker, dsIndex, settings, markerArgs) { createTooltip(marker, dsIndex, settings, markerArgs) {
var popup = L.popup(); var popup = L.popup();
popup.setContent(''); popup.setContent('');
marker.bindPopup(popup, { autoClose: settings.autocloseTooltip, closeOnClick: false }); marker.bindPopup(popup, { autoClose: settings.autocloseTooltip, closeOnClick: false });
@ -139,32 +139,29 @@ export default abstract class LeafletMap {
updateMarkers(markersData) { updateMarkers(markersData) {
markersData.forEach(data => { markersData.forEach(data => {
if (this.markers.get(data.aliasName)) { if (this.markers.get(data.aliasName)) {
this.updateMarker(data.aliasName, this.convertPosition(data), this.options as MarkerSettings) this.updateMarker(data.aliasName, data, markersData, this.options as MarkerSettings)
} }
else { else {
this.createMarker(data.aliasName, this.convertPosition(data), this.options as MarkerSettings); this.createMarker(data.aliasName, data, markersData, this.options as MarkerSettings);
} }
}); });
} }
private createMarker(key, location, settings: MarkerSettings) { private createMarker(key, data, dataSources, settings: MarkerSettings) {
this.ready$.subscribe(() => { this.ready$.subscribe(() => {
let defaultSettings: MarkerSettings = { const newMarker = new Marker(this.map, this.convertPosition(data), settings, data, dataSources);
color: '#FD2785'
}
const newMarker = new Marker(this.map, location, { ...defaultSettings, ...settings });
this.map.fitBounds(this.bounds.extend(newMarker.leafletMarker.getLatLng())); this.map.fitBounds(this.bounds.extend(newMarker.leafletMarker.getLatLng()));
this.markers.set(key, newMarker); this.markers.set(key, newMarker);
}); });
} }
private updateMarker(key, location: L.LatLng, settings: MarkerSettings) { private updateMarker(key, data, dataSources, settings: MarkerSettings) {
const marker: Marker = this.markers.get(key); const marker: Marker = this.markers.get(key);
let location = this.convertPosition(data)
if (!location.equals(marker.location)) { if (!location.equals(marker.location)) {
marker.updateMarkerPosition(location); marker.updateMarkerPosition(location);
} }
//other implements later marker.updateMarkerIcon(settings, data, dataSources);
} }
private deleteMarker() { private deleteMarker() {
@ -173,28 +170,34 @@ export default abstract class LeafletMap {
//polyline //polyline
updatePolylines(polyData) { updatePolylines(polyData: Array<Array<any>>) {
polyData.forEach(data => {
if (data.length) {
let dataSource = polyData.map(arr=>arr[0]);
if (this.poly) { if (this.poly) {
this.updatePolyline(data, dataSource, this.options);
}
else {
this.createPolyline(polyData.map(data => this.convertPosition(data)), this.options);
}
/* markersData.forEach(data => {
if (this.markers.get(data.aliasName)) {
this.updateMarker(data.aliasName, this.convertPosition(data), this.options as MarkerSettings)
} }
else { else {
this.createMarker(data.aliasName, this.convertPosition(data), this.options as MarkerSettings); this.createPolyline(data, dataSource, this.options);
} }
});*/ }
})
} }
createPolyline(locations, settings) { createPolyline(data, dataSources, settings) {
this.ready$.subscribe(() => { this.ready$.subscribe(() => {
this.poly = new Polyline(this.map, locations, settings); this.poly = new Polyline(this.map, data.map(data => this.convertPosition(data)), data, dataSources, settings);
const bounds = this.bounds.extend(this.poly.leafletPoly.getBounds());
if (bounds.isValid()) {
this.map.fitBounds(bounds);
this.bounds = bounds;
}
});
}
updatePolyline(data, dataSources, settings) {
this.ready$.subscribe(() => {
this.poly.updatePolyline(settings, data, dataSources);
const bounds = this.bounds.extend(this.poly.leafletPoly.getBounds()); const bounds = this.bounds.extend(this.poly.leafletPoly.getBounds());
if (bounds.isValid()) { if (bounds.isValid()) {
this.map.fitBounds(bounds); this.map.fitBounds(bounds);

View File

@ -26,9 +26,13 @@ export enum MapProviders {
tencent = 'tencent-map' tencent = 'tencent-map'
} }
export interface MarkerSettings { export interface MarkerSettings extends MapOptions {
showLabel?: boolean, showLabel?: boolean,
draggable?: boolean, draggable?: boolean,
displayTooltip?: boolean, displayTooltip?: boolean,
color?: string color?: string,
currentImage?: string;
useMarkerImageFunction?: boolean,
markerImages?: string[],
markerImageFunction?: Function;
} }

View File

@ -13,8 +13,7 @@ import {
} from './schemes'; } from './schemes';
import { MapWidgetStaticInterface, MapWidgetInterface } from './map-widget.interface'; import { MapWidgetStaticInterface, MapWidgetInterface } from './map-widget.interface';
import { OpenStreetMap, TencentMap, GoogleMap, HEREMap, ImageMap } from './providers'; import { OpenStreetMap, TencentMap, GoogleMap, HEREMap, ImageMap } from './providers';
import { WidgetSubscription } from '@app/core/public-api'; import { parseData, parseArray, parseFunction } from './maps-utils';
import { parseData, parseArray } from './maps-utils';
export let TbMapWidgetV2: MapWidgetStaticInterface; export let TbMapWidgetV2: MapWidgetStaticInterface;
TbMapWidgetV2 = class TbMapWidgetV2 implements MapWidgetInterface { TbMapWidgetV2 = class TbMapWidgetV2 implements MapWidgetInterface {
@ -24,37 +23,44 @@ TbMapWidgetV2 = class TbMapWidgetV2 implements MapWidgetInterface {
data; data;
constructor(mapProvider: MapProviders, private drawRoutes, ctx, $element) { constructor(mapProvider: MapProviders, private drawRoutes, ctx, $element) {
console.log("TbMapWidgetV2 -> constructor -> ctx", ctx)
// console.log(ctx.subscriptions, ctx.data, ctx.datasources);
this.data = ctx.data; this.data = ctx.data;
//this.subsciptions.
if (!$element) { if (!$element) {
$element = ctx.$container[0]; $element = ctx.$container[0];
} }
this.provider = mapProvider; this.provider = mapProvider;
const baseOptions: MapOptions = {
initCallback: () => { },
defaultZoomLevel: 8,
dontFitMapBounds: false,
disableScrollZooming: false,
minZoomLevel: drawRoutes ? 18 : 15,
mapProvider: mapProvider,
mapUrl: ctx?.settings?.mapImageUrl,
credentials: '',
defaultCenterPosition: [0, 0],
markerClusteringSetting: null
}
let MapClass = providerSets[mapProvider]?.MapClass; let MapClass = providerSets[mapProvider]?.MapClass;
let settings = this.initSettings(ctx?.settings);
if (!MapClass) { if (!MapClass) {
return; return;
} }
this.map = new MapClass($element, { ...baseOptions, ...ctx.settings }); this.map = new MapClass($element, settings);
this.schema = providerSets[mapProvider]?.schema; this.schema = providerSets[mapProvider]?.schema;
} }
onInit() { onInit() {
} }
initSettings(settings: any) {
const functionParams = ['data', 'dsData', 'dsIndex'];
const customOptions = {
mapProvider: this.provider,
mapUrl: settings?.mapImageUrl,
labelFunction: parseFunction(settings.labelFunction, functionParams),
tooltipFunction: parseFunction(settings.tooltipFunction, functionParams),
colorFunction: parseFunction(settings.colorFunction, functionParams),
polygonColorFunction: parseFunction(settings.polygonColorFunction, functionParams),
markerImageFunction: parseFunction(settings.markerImageFunction, ['data', 'images', 'dsData', 'dsIndex']),
tooltipPattern: settings.tooltipPattern ||
"<b>${entityName}</b><br/><br/><b>Latitude:</b> ${" + settings.latKeyName + ":7}<br/><b>Longitude:</b> ${" + settings.lngKeyName + ":7}",
label: settings.label || "${entityName}",
currentImage: (settings.useMarkerImage && settings.markerImage?.length) ? {
url: settings.markerImage,
size: settings.markerImageSize || 34
} : null
}
return { ...defaultSettings, ...settings, ...customOptions, }
}
update() { update() {
if (this.drawRoutes) if (this.drawRoutes)
this.map.updatePolylines(parseArray(this.data)); this.map.updatePolylines(parseArray(this.data));
@ -180,3 +186,38 @@ const providerSets = {
schema: imageMapSettingsSchema schema: imageMapSettingsSchema
} }
} }
const defaultSettings = {
xPosKeyName: 'xPos',
yPosKeyName: 'yPos',
markerOffsetX: 0.5,
markerOffsetY: 1,
latKeyName: 'latitude',
lngKeyName: 'longitude',
polygonKeyName: 'coordinates',
showLabel: false,
showTooltip: false,
useDefaultCenterPosition: false,
showTooltipAction: "click",
autocloseTooltip: false,
showPolygon: true,
labelColor: '#000000',
color: "#FE7569",
polygonColor: "#0000ff",
polygonStrokeColor: "#fe0001",
polygonOpacity: 0.5,
polygonStrokeOpacity: 1,
polygonStrokeWeight: 1,
useLabelFunction: true,
markerImages: [],
strokeWeight: 2,
strokeOpacity: 1.0,
initCallback: () => { },
defaultZoomLevel: 8,
dontFitMapBounds: false,
disableScrollZooming: false,
minZoomLevel: 16,
credentials: '',
defaultCenterPosition: [0, 0],
markerClusteringSetting: null,
}

View File

@ -24,23 +24,61 @@ export function createTooltip(target, settings, targetArgs?) {
export function parseArray(input: any[]): any[] { export function parseArray(input: any[]): any[] {
let alliases: any = _(input).groupBy(el => el?.datasource?.aliasName).values().value(); let alliases: any = _(input).groupBy(el => el?.datasource?.aliasName).values().value();
return alliases.map(alliasArray => return alliases.map((alliasArray, dsIndex) =>
alliasArray[0].data.map((el, i) => { alliasArray[0].data.map((el, i) => {
const obj = { aliasName: alliasArray[0]?.datasource?.aliasName }; const obj = {
aliasName: alliasArray[0]?.datasource?.aliasName,
$datasource: alliasArray[0]?.datasource,
dsIndex: dsIndex
};
alliasArray.forEach(el => { alliasArray.forEach(el => {
obj[el?.dataKey?.label] = el?.data[i][1] obj[el?.dataKey?.label] = el?.data[i][1];
obj[el?.dataKey?.label + '|ts'] = el?.data[0][0];
}); });
return obj; return obj;
}) })
).flat(); );
} }
export function parseData(input: any[]): any[] { export function parseData(input: any[]): any[] {
return _(input).groupBy(el => el?.datasource?.aliasName).values().value().map(alliasArray => { return _(input).groupBy(el => el?.datasource?.aliasName).values().value().map((alliasArray, i) => {
const obj = { aliasName: alliasArray[0]?.datasource?.aliasName }; const obj = {
aliasName: alliasArray[0]?.datasource?.aliasName,
$datasource: alliasArray[0]?.datasource,
dsIndex: i
};
alliasArray.forEach(el => { alliasArray.forEach(el => {
obj[el?.dataKey?.label] = el?.data[0][1] obj[el?.dataKey?.label] = el?.data[0][1];
obj[el?.dataKey?.label + '|ts'] = el?.data[0][0];
}); });
return obj; 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;
}
}
return res;
}
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;
}
}
return res;
}

View File

@ -1,7 +1,6 @@
import L from 'leaflet'; import L from 'leaflet';
import { createTooltip } from './maps-utils'; import { createTooltip, safeExecute } from './maps-utils';
import { MarkerSettings } from './map-models'; import { MarkerSettings } from './map-models';
import { Observable } from 'rxjs';
import { aspectCache } from '@app/core/utils'; import { aspectCache } from '@app/core/utils';
export class Marker { export class Marker {
@ -11,15 +10,19 @@ export class Marker {
tooltipOffset; tooltipOffset;
tooltip; tooltip;
location; location;
data;
dataSources;
constructor(private map: L.Map, location: L.LatLngExpression, settings: MarkerSettings, onClickListener?, markerArgs?, onDragendListener?) { constructor(private map: L.Map, location: L.LatLngExpression, public settings: MarkerSettings, data, dataSources, onClickListener?, markerArgs?, onDragendListener?) {
//this.map = map; //this.map = map;
this.location = location; this.location = location;
this.data = data;
this.dataSources = dataSources;
this.leafletMarker = L.marker(location, { this.leafletMarker = L.marker(location, {
draggable: settings.draggable draggable: settings.draggable
}); });
this.createMarkerIcon(settings, (iconInfo) => { this.createMarkerIcon(dataSources, (iconInfo) => {
this.leafletMarker.setIcon(iconInfo.icon); this.leafletMarker.setIcon(iconInfo.icon);
if (settings.showLabel) { if (settings.showLabel) {
this.tooltipOffset = [0, -iconInfo.size[1] + 10]; this.tooltipOffset = [0, -iconInfo.size[1] + 10];
@ -44,7 +47,7 @@ export class Marker {
} }
updateMarkerPosition(position: L.LatLngExpression){ updateMarkerPosition(position: L.LatLngExpression) {
this.leafletMarker.setLatLng(position); this.leafletMarker.setLatLng(position);
} }
@ -61,8 +64,9 @@ export class Marker {
}); });
} }
updateMarkerIcon(settings) { updateMarkerIcon(settings, data, dataSources) {
this.createMarkerIcon(settings, (iconInfo) => { this.data = data;
this.createMarkerIcon(dataSources, (iconInfo) => {
this.leafletMarker.setIcon(iconInfo.icon); this.leafletMarker.setIcon(iconInfo.icon);
if (settings.showLabel) { if (settings.showLabel) {
this.tooltipOffset = [0, -iconInfo.size[1] + 10]; this.tooltipOffset = [0, -iconInfo.size[1] + 10];
@ -71,10 +75,9 @@ export class Marker {
}); });
} }
createMarkerIcon(dataSources, onMarkerIconReady) {
const currentImage = this.settings.useMarkerImageFunction ?
createMarkerIcon(settings, onMarkerIconReady) { safeExecute(this.settings.markerImageFunction, [this.data, this.settings.markerImages, dataSources, this.data.dsIndex]) : this.settings.currentImage;
var currentImage = settings.currentImage;
// var opMap = this; // var opMap = this;
if (currentImage && currentImage.url) { if (currentImage && currentImage.url) {
aspectCache(currentImage.url).subscribe( aspectCache(currentImage.url).subscribe(
@ -101,12 +104,12 @@ export class Marker {
}; };
onMarkerIconReady(iconInfo); onMarkerIconReady(iconInfo);
} else { } else {
this.createDefaultMarkerIcon(settings.color, onMarkerIconReady); this.createDefaultMarkerIcon(this.settings.color, onMarkerIconReady);
} }
} }
); );
} else { } else {
this.createDefaultMarkerIcon(settings.color, onMarkerIconReady); this.createDefaultMarkerIcon(this.settings.color, onMarkerIconReady);
} }
} }

View File

@ -1,26 +1,31 @@
import L from 'leaflet'; import L from 'leaflet';
import { safeExecute } from './maps-utils';
export class Polyline { export class Polyline {
leafletPoly: L.Polyline; leafletPoly: L.Polyline;
dataSources;
data;
constructor(private map: L.Map, locations, settings) { constructor(private map: L.Map, locations, data, dataSources, settings) {
this.dataSources = dataSources;
this.data = data;
this.leafletPoly = L.polyline(locations, this.leafletPoly = L.polyline(locations,
{ this.getPolyStyle(settings, data, dataSources)
color: settings.color,
opacity: settings.strokeOpacity,
weight: settings.strokeWeight
}
).addTo(this.map); ).addTo(this.map);
} }
updatePolylineColor(settings, color) { updatePolyline(settings, data, dataSources) {
var style = { this.leafletPoly.setStyle(this.getPolyStyle(settings, data, dataSources));
color: color,
}
getPolyStyle(settings, data, dataSources): L.PolylineOptions {
return {
color: settings.useColorFunction ? safeExecute(settings.colorFunction, [data, dataSources, data[0]?.dsIndex]) : settings.color,
opacity: settings.strokeOpacity, opacity: settings.strokeOpacity,
weight: settings.strokeWeight weight: settings.strokeWeight
}; }
this.leafletPoly.setStyle(style);
} }
removePolyline() { removePolyline() {

View File

@ -451,6 +451,8 @@ export default class TbMapWidgetV2 {
var color; var color;
try { try {
color = location.settings.polygonColorFunction(dataMap.dataMap, dataMap.dsDataMap, location.dsIndex); color = location.settings.polygonColorFunction(dataMap.dataMap, dataMap.dsDataMap, location.dsIndex);
// eslint-disable-next-line no-debugger
debugger
} catch (e) {/**/ } catch (e) {/**/
} }
if (!color) { if (!color) {
@ -485,6 +487,8 @@ export default class TbMapWidgetV2 {
if (location.settings.useMarkerImageFunction && location.settings.markerImageFunction) { if (location.settings.useMarkerImageFunction && location.settings.markerImageFunction) {
var image = null; var image = null;
try { try {
// eslint-disable-next-line no-debugger
debugger;
image = location.settings.markerImageFunction(dataMap.dataMap, location.settings.markerImages, dataMap.dsDataMap, location.dsIndex); image = location.settings.markerImageFunction(dataMap.dataMap, location.settings.markerImages, dataMap.dsDataMap, location.dsIndex);
} catch (e) { } catch (e) {
image = null; image = null;