Commit e8e2f2119352193d06614c7ea554fecca6ae063e

Authored by Igor Kulikov
1 parent 6b53e84c

Map widgets fixes

... ... @@ -38,13 +38,17 @@ import {
38 38 UnitedMapSettings
39 39 } from './map-models';
40 40 import { Marker } from './markers';
41   -import { BehaviorSubject, Observable, of } from 'rxjs';
42   -import { filter } from 'rxjs/operators';
  41 +import { Observable, of } from 'rxjs';
43 42 import { Polyline } from './polyline';
44 43 import { Polygon } from './polygon';
45   -import { createLoadingDiv, createTooltip, parseArray, safeExecute } from '@home/components/widget/lib/maps/maps-utils';
  44 +import {
  45 + createLoadingDiv,
  46 + createTooltip,
  47 + parseArray,
  48 + parseData,
  49 + safeExecute
  50 +} from '@home/components/widget/lib/maps/maps-utils';
46 51 import { WidgetContext } from '@home/models/widget-component.models';
47   -import { DatasourceData } from '@shared/models/widget.models';
48 52 import { deepClone, isDefinedAndNotEmptyStr } from '@core/utils';
49 53
50 54 export default abstract class LeafletMap {
... ... @@ -53,8 +57,6 @@ export default abstract class LeafletMap {
53 57 polylines: Map<string, Polyline> = new Map();
54 58 polygons: Map<string, Polygon> = new Map();
55 59 map: L.Map;
56   - map$: BehaviorSubject<L.Map> = new BehaviorSubject(null);
57   - ready$: Observable<L.Map> = this.map$.pipe(filter(map => !!map));
58 60 options: UnitedMapSettings;
59 61 bounds: L.LatLngBounds;
60 62 datasources: FormattedData[];
... ... @@ -69,6 +71,9 @@ export default abstract class LeafletMap {
69 71 markerLabelText: string;
70 72 replaceInfoTooltipMarker: Array<ReplaceInfo> = [];
71 73 markerTooltipText: string;
  74 + drawRoutes: boolean;
  75 + showPolygon: boolean;
  76 + updatePending = false;
72 77
73 78 protected constructor(public ctx: WidgetContext,
74 79 public $container: HTMLElement,
... ... @@ -78,8 +83,7 @@ export default abstract class LeafletMap {
78 83
79 84 public initSettings(options: MapSettings) {
80 85 this.options.tinyColor = tinycolor(this.options.color || defaultSettings.color);
81   - const { initCallback,
82   - disableScrollZooming,
  86 + const { disableScrollZooming,
83 87 useClusterMarkers,
84 88 zoomOnClick,
85 89 showCoverageOnHover,
... ... @@ -91,9 +95,6 @@ export default abstract class LeafletMap {
91 95 if (disableScrollZooming) {
92 96 this.map.scrollWheelZoom.disable();
93 97 }
94   - if (initCallback) {
95   - setTimeout(options.initCallback, 0);
96   - }
97 98 if (useClusterMarkers) {
98 99 const clusteringSettings: MarkerClusterGroupOptions = {
99 100 zoomToBoundsOnClick: zoomOnClick,
... ... @@ -109,7 +110,6 @@ export default abstract class LeafletMap {
109 110 clusteringSettings.disableClusteringAtZoom = Math.floor(maxZoom);
110 111 }
111 112 this.markersCluster = markerClusterGroup(clusteringSettings);
112   - this.ready$.subscribe(map => map.addLayer(this.markersCluster));
113 113 }
114 114 }
115 115
... ... @@ -182,18 +182,16 @@ export default abstract class LeafletMap {
182 182 public setLoading(loading: boolean) {
183 183 if (this.loading !== loading) {
184 184 this.loading = loading;
185   - this.ready$.subscribe(() => {
186   - if (this.loading) {
187   - if (!this.loadingDiv) {
188   - this.loadingDiv = createLoadingDiv(this.ctx.translate.instant('common.loading'));
189   - }
190   - this.$container.append(this.loadingDiv[0]);
191   - } else {
192   - if (this.loadingDiv) {
193   - this.loadingDiv.remove();
194   - }
  185 + if (this.loading) {
  186 + if (!this.loadingDiv) {
  187 + this.loadingDiv = createLoadingDiv(this.ctx.translate.instant('common.loading'));
195 188 }
196   - });
  189 + this.$container.append(this.loadingDiv[0]);
  190 + } else {
  191 + if (this.loadingDiv) {
  192 + this.loadingDiv.remove();
  193 + }
  194 + }
197 195 }
198 196 }
199 197
... ... @@ -207,11 +205,13 @@ export default abstract class LeafletMap {
207 205 if (this.options.draggableMarker) {
208 206 this.addMarkerControl();
209 207 }
210   - this.map$.next(this.map);
211   - }
212   -
213   - public setDataSources(dataSources: FormattedData[]) {
214   - this.datasources = dataSources;
  208 + if (this.options.useClusterMarkers) {
  209 + this.map.addLayer(this.markersCluster);
  210 + }
  211 + if (this.updatePending) {
  212 + this.updatePending = false;
  213 + this.updateData(this.drawRoutes, this.showPolygon);
  214 + }
215 215 }
216 216
217 217 public saveMarkerLocation(_e: FormattedData, lat?: number, lng?: number): Observable<any> {
... ... @@ -259,7 +259,7 @@ export default abstract class LeafletMap {
259 259 this.map.once('zoomend', () => {
260 260 let minZoom = this.options.minZoomLevel;
261 261 if (this.options.defaultZoomLevel) {
262   - minZoom = Math.min(minZoom, this.options.defaultZoomLevel);
  262 + minZoom = Math.max(minZoom, this.options.defaultZoomLevel);
263 263 }
264 264 if (this.map.getZoom() > minZoom) {
265 265 this.map.setZoom(minZoom, { animate: false });
... ... @@ -297,8 +297,12 @@ export default abstract class LeafletMap {
297 297 }
298 298 }
299 299
300   - updateData(data: DatasourceData[], formattedData: FormattedData[], drawRoutes: boolean, showPolygon: boolean) {
301   - this.ready$.subscribe(() => {
  300 + updateData(drawRoutes: boolean, showPolygon: boolean) {
  301 + this.drawRoutes = drawRoutes;
  302 + this.showPolygon = showPolygon;
  303 + if (this.map) {
  304 + const data = this.ctx.data;
  305 + const formattedData = parseData(this.ctx.data);
302 306 if (drawRoutes) {
303 307 this.updatePolylines(parseArray(data), false);
304 308 }
... ... @@ -306,23 +310,28 @@ export default abstract class LeafletMap {
306 310 this.updatePolygons(formattedData, false);
307 311 }
308 312 this.updateMarkers(formattedData, false);
309   - this.updateBoundsInternal(drawRoutes, showPolygon);
310   - });
  313 + this.updateBoundsInternal();
  314 + if (this.options.draggableMarker) {
  315 + this.datasources = formattedData;
  316 + }
  317 + } else {
  318 + this.updatePending = true;
  319 + }
311 320 }
312 321
313   - private updateBoundsInternal(drawRoutes: boolean, showPolygon: boolean) {
  322 + private updateBoundsInternal() {
314 323 const bounds = new L.LatLngBounds(null, null);
315   - if (drawRoutes) {
  324 + if (this.drawRoutes) {
316 325 this.polylines.forEach((polyline) => {
317 326 bounds.extend(polyline.leafletPoly.getBounds());
318 327 });
319 328 }
320   - if (showPolygon) {
  329 + if (this.showPolygon) {
321 330 this.polygons.forEach((polygon) => {
322 331 bounds.extend(polygon.leafletPoly.getBounds());
323 332 });
324 333 }
325   - if ((this.options as MarkerSettings).useClusterMarkers) {
  334 + if ((this.options as MarkerSettings).useClusterMarkers && this.markersCluster.getBounds().isValid()) {
326 335 bounds.extend(this.markersCluster.getBounds());
327 336 } else {
328 337 this.markers.forEach((marker) => {
... ... @@ -331,7 +340,7 @@ export default abstract class LeafletMap {
331 340 }
332 341
333 342 const mapBounds = this.map.getBounds();
334   - if (bounds.isValid() && (!this.bounds || !mapBounds.contains(bounds))) {
  343 + if (bounds.isValid() && (!this.bounds || !this.bounds.isValid() || !this.bounds.equals(bounds) && !mapBounds.contains(bounds))) {
335 344 this.bounds = bounds;
336 345 this.fitBounds(bounds);
337 346 }
... ... @@ -340,59 +349,57 @@ export default abstract class LeafletMap {
340 349 // Markers
341 350 updateMarkers(markersData: FormattedData[], updateBounds = true, callback?) {
342 351 const rawMarkers = markersData.filter(mdata => !!this.convertPosition(mdata));
343   - this.ready$.subscribe(() => {
344   - const toDelete = new Set(Array.from(this.markers.keys()));
345   - const createdMarkers: Marker[] = [];
346   - const updatedMarkers: Marker[] = [];
347   - const deletedMarkers: Marker[] = [];
348   - let m: Marker;
349   - rawMarkers.forEach(data => {
350   - if (data.rotationAngle || data.rotationAngle === 0) {
351   - const currentImage = this.options.useMarkerImageFunction ?
352   - safeExecute(this.options.markerImageFunction,
353   - [data, this.options.markerImages, markersData, data.dsIndex]) : this.options.currentImage;
354   - const style = currentImage ? 'background-image: url(' + currentImage.url + ');' : '';
355   - this.options.icon = L.divIcon({
356   - html: `<div class="arrow"
357   - style="transform: translate(-10px, -10px)
358   - rotate(${data.rotationAngle}deg);
359   - ${style}"><div>`
360   - });
361   - } else {
362   - this.options.icon = null;
363   - }
364   - if (this.markers.get(data.entityName)) {
365   - m = this.updateMarker(data.entityName, data, markersData, this.options);
366   - if (m) {
367   - updatedMarkers.push(m);
368   - }
369   - } else {
370   - m = this.createMarker(data.entityName, data, markersData, this.options as MarkerSettings, updateBounds, callback);
371   - if (m) {
372   - createdMarkers.push(m);
373   - }
374   - }
375   - toDelete.delete(data.entityName);
  352 + const toDelete = new Set(Array.from(this.markers.keys()));
  353 + const createdMarkers: Marker[] = [];
  354 + const updatedMarkers: Marker[] = [];
  355 + const deletedMarkers: Marker[] = [];
  356 + let m: Marker;
  357 + rawMarkers.forEach(data => {
  358 + if (data.rotationAngle || data.rotationAngle === 0) {
  359 + const currentImage = this.options.useMarkerImageFunction ?
  360 + safeExecute(this.options.markerImageFunction,
  361 + [data, this.options.markerImages, markersData, data.dsIndex]) : this.options.currentImage;
  362 + const style = currentImage ? 'background-image: url(' + currentImage.url + ');' : '';
  363 + this.options.icon = L.divIcon({
  364 + html: `<div class="arrow"
  365 + style="transform: translate(-10px, -10px)
  366 + rotate(${data.rotationAngle}deg);
  367 + ${style}"><div>`
376 368 });
377   - toDelete.forEach((key) => {
378   - m = this.deleteMarker(key);
379   - if (m) {
380   - deletedMarkers.push(m);
381   - }
382   - });
383   - this.markersData = markersData;
384   - if ((this.options as MarkerSettings).useClusterMarkers) {
385   - if (createdMarkers.length) {
386   - this.markersCluster.addLayers(createdMarkers.map(marker => marker.leafletMarker));
387   - }
388   - if (updatedMarkers.length) {
389   - this.markersCluster.refreshClusters(updatedMarkers.map(marker => marker.leafletMarker))
390   - }
391   - if (deletedMarkers.length) {
392   - this.markersCluster.removeLayers(deletedMarkers.map(marker => marker.leafletMarker));
393   - }
  369 + } else {
  370 + this.options.icon = null;
  371 + }
  372 + if (this.markers.get(data.entityName)) {
  373 + m = this.updateMarker(data.entityName, data, markersData, this.options);
  374 + if (m) {
  375 + updatedMarkers.push(m);
394 376 }
395   - });
  377 + } else {
  378 + m = this.createMarker(data.entityName, data, markersData, this.options as MarkerSettings, updateBounds, callback);
  379 + if (m) {
  380 + createdMarkers.push(m);
  381 + }
  382 + }
  383 + toDelete.delete(data.entityName);
  384 + });
  385 + toDelete.forEach((key) => {
  386 + m = this.deleteMarker(key);
  387 + if (m) {
  388 + deletedMarkers.push(m);
  389 + }
  390 + });
  391 + this.markersData = markersData;
  392 + if ((this.options as MarkerSettings).useClusterMarkers) {
  393 + if (createdMarkers.length) {
  394 + this.markersCluster.addLayers(createdMarkers.map(marker => marker.leafletMarker));
  395 + }
  396 + if (updatedMarkers.length) {
  397 + this.markersCluster.refreshClusters(updatedMarkers.map(marker => marker.leafletMarker))
  398 + }
  399 + if (deletedMarkers.length) {
  400 + this.markersCluster.removeLayers(deletedMarkers.map(marker => marker.leafletMarker));
  401 + }
  402 + }
396 403 }
397 404
398 405 dragMarker = (e, data = {} as FormattedData) => {
... ... @@ -420,10 +427,8 @@ export default abstract class LeafletMap {
420 427
421 428 private updateMarker(key: string, data: FormattedData, dataSources: FormattedData[], settings: MarkerSettings): Marker {
422 429 const marker: Marker = this.markers.get(key);
423   - const location = this.convertPosition(data)
424   - if (!location.equals(marker.location)) {
425   - marker.updateMarkerPosition(location);
426   - }
  430 + const location = this.convertPosition(data);
  431 + marker.updateMarkerPosition(location);
427 432 if (settings.showTooltip) {
428 433 marker.updateMarkerTooltip(data);
429 434 }
... ... @@ -445,26 +450,24 @@ export default abstract class LeafletMap {
445 450 }
446 451
447 452 updatePoints(pointsData: FormattedData[], getTooltip: (point: FormattedData, setTooltip?: boolean) => string) {
448   - this.map$.subscribe(map => {
449   - if (this.points) {
450   - map.removeLayer(this.points);
451   - }
452   - this.points = new FeatureGroup();
453   - pointsData.filter(pdata => !!this.convertPosition(pdata)).forEach(data => {
454   - const point = L.circleMarker(this.convertPosition(data), {
455   - color: this.options.pointColor,
456   - radius: this.options.pointSize
457   - });
458   - if (!this.options.pointTooltipOnRightPanel) {
459   - point.on('click', () => getTooltip(data));
460   - }
461   - else {
462   - createTooltip(point, this.options, data.$datasource, getTooltip(data, false));
463   - }
464   - this.points.addLayer(point);
465   - });
466   - map.addLayer(this.points);
467   - });
  453 + if (this.points) {
  454 + this.map.removeLayer(this.points);
  455 + }
  456 + this.points = new FeatureGroup();
  457 + pointsData.filter(pdata => !!this.convertPosition(pdata)).forEach(data => {
  458 + const point = L.circleMarker(this.convertPosition(data), {
  459 + color: this.options.pointColor,
  460 + radius: this.options.pointSize
  461 + });
  462 + if (!this.options.pointTooltipOnRightPanel) {
  463 + point.on('click', () => getTooltip(data));
  464 + }
  465 + else {
  466 + createTooltip(point, this.options, data.$datasource, getTooltip(data, false));
  467 + }
  468 + this.points.addLayer(point);
  469 + });
  470 + this.map.addLayer(this.points);
468 471 }
469 472
470 473 // Polyline
... ... @@ -494,27 +497,23 @@ export default abstract class LeafletMap {
494 497 }
495 498
496 499 createPolyline(data: FormattedData, dataSources: FormattedData[], settings: PolylineSettings, updateBounds = true) {
497   - this.ready$.subscribe(() => {
498   - const poly = new Polyline(this.map,
499   - dataSources.map(el => this.convertPosition(el)).filter(el => !!el), data, dataSources, settings);
500   - if (updateBounds) {
501   - const bounds = poly.leafletPoly.getBounds();
502   - this.fitBounds(bounds);
503   - }
504   - this.polylines.set(data.entityName, poly);
505   - });
  500 + const poly = new Polyline(this.map,
  501 + dataSources.map(el => this.convertPosition(el)).filter(el => !!el), data, dataSources, settings);
  502 + if (updateBounds) {
  503 + const bounds = poly.leafletPoly.getBounds();
  504 + this.fitBounds(bounds);
  505 + }
  506 + this.polylines.set(data.entityName, poly);
506 507 }
507 508
508 509 updatePolyline(data: FormattedData, dataSources: FormattedData[], settings: PolylineSettings, updateBounds = true) {
509   - this.ready$.subscribe(() => {
510   - const poly = this.polylines.get(data.entityName);
511   - const oldBounds = poly.leafletPoly.getBounds();
512   - poly.updatePolyline(dataSources.map(el => this.convertPosition(el)).filter(el => !!el), data, dataSources, settings);
513   - const newBounds = poly.leafletPoly.getBounds();
514   - if (updateBounds && oldBounds.toBBoxString() !== newBounds.toBBoxString()) {
515   - this.fitBounds(newBounds);
516   - }
517   - });
  510 + const poly = this.polylines.get(data.entityName);
  511 + const oldBounds = poly.leafletPoly.getBounds();
  512 + poly.updatePolyline(dataSources.map(el => this.convertPosition(el)).filter(el => !!el), data, dataSources, settings);
  513 + const newBounds = poly.leafletPoly.getBounds();
  514 + if (updateBounds && oldBounds.toBBoxString() !== newBounds.toBBoxString()) {
  515 + this.fitBounds(newBounds);
  516 + }
518 517 }
519 518
520 519 removePolyline(name: string) {
... ... @@ -560,26 +559,22 @@ export default abstract class LeafletMap {
560 559 }
561 560
562 561 createPolygon(polyData: FormattedData, dataSources: FormattedData[], settings: PolygonSettings, updateBounds = true) {
563   - this.ready$.subscribe(() => {
564   - const polygon = new Polygon(this.map, polyData, dataSources, settings);
565   - if (updateBounds) {
566   - const bounds = polygon.leafletPoly.getBounds();
567   - this.fitBounds(bounds);
568   - }
569   - this.polygons.set(polyData.entityName, polygon);
570   - });
  562 + const polygon = new Polygon(this.map, polyData, dataSources, settings);
  563 + if (updateBounds) {
  564 + const bounds = polygon.leafletPoly.getBounds();
  565 + this.fitBounds(bounds);
  566 + }
  567 + this.polygons.set(polyData.entityName, polygon);
571 568 }
572 569
573 570 updatePolygon(polyData: FormattedData, dataSources: FormattedData[], settings: PolygonSettings, updateBounds = true) {
574   - this.ready$.subscribe(() => {
575   - const poly = this.polygons.get(polyData.entityName);
576   - const oldBounds = poly.leafletPoly.getBounds();
577   - poly.updatePolygon(polyData, dataSources, settings);
578   - const newBounds = poly.leafletPoly.getBounds();
579   - if (updateBounds && oldBounds.toBBoxString() !== newBounds.toBBoxString()) {
580   - this.fitBounds(newBounds);
581   - }
582   - });
  571 + const poly = this.polygons.get(polyData.entityName);
  572 + const oldBounds = poly.leafletPoly.getBounds();
  573 + poly.updatePolygon(polyData, dataSources, settings);
  574 + const newBounds = poly.leafletPoly.getBounds();
  575 + if (updateBounds && oldBounds.toBBoxString() !== newBounds.toBBoxString()) {
  576 + this.fitBounds(newBounds);
  577 + }
583 578 }
584 579
585 580 removePolygon(name: string) {
... ...
... ... @@ -15,14 +15,7 @@
15 15 ///
16 16
17 17 import { LatLngTuple } from 'leaflet';
18   -import { Datasource, JsonSettingsSchema } from '@app/shared/models/widget.models';
19   -import { Type } from '@angular/core';
20   -import LeafletMap from './leaflet-map';
21   -import { OpenStreetMap, TencentMap, GoogleMap, HEREMap, ImageMap } from './providers';
22   -import {
23   - openstreetMapSettingsSchema, tencentMapSettingsSchema,
24   - googleMapSettingsSchema, hereMapSettingsSchema, imageMapSettingsSchema
25   -} from './schemes';
  18 +import { Datasource } from '@app/shared/models/widget.models';
26 19 import { EntityType } from '@shared/models/entity-type.models';
27 20 import tinycolor from 'tinycolor2';
28 21
... ... @@ -30,12 +23,10 @@ export const DEFAULT_MAP_PAGE_SIZE = 16384;
30 23
31 24 export type GenericFunction = (data: FormattedData, dsData: FormattedData[], dsIndex: number) => string;
32 25 export type MarkerImageFunction = (data: FormattedData, dsData: FormattedData[], dsIndex: number) => string;
33   -export type GetTooltip = (point: FormattedData, setTooltip?: boolean) => string;
34 26 export type PosFuncton = (origXPos, origYPos) => { x, y };
35 27
36 28 export type MapSettings = {
37 29 draggableMarker: boolean;
38   - initCallback?: () => any;
39 30 posFunction: PosFuncton;
40 31 defaultZoomLevel?: number;
41 32 disableScrollZooming?: boolean;
... ... @@ -209,40 +200,6 @@ export type actionsHandler = ($event: Event, datasource: Datasource) => void;
209 200
210 201 export type UnitedMapSettings = MapSettings & PolygonSettings & MarkerSettings & PolylineSettings & TripAnimationSettings;
211 202
212   -interface IProvider {
213   - MapClass: Type<LeafletMap>,
214   - schema: JsonSettingsSchema,
215   - name: string
216   -}
217   -
218   -export const providerSets: { [key: string]: IProvider } = {
219   - 'openstreet-map': {
220   - MapClass: OpenStreetMap,
221   - schema: openstreetMapSettingsSchema,
222   - name: 'openstreet-map',
223   - },
224   - 'tencent-map': {
225   - MapClass: TencentMap,
226   - schema: tencentMapSettingsSchema,
227   - name: 'tencent-map'
228   - },
229   - 'google-map': {
230   - MapClass: GoogleMap,
231   - schema: googleMapSettingsSchema,
232   - name: 'google-map'
233   - },
234   - here: {
235   - MapClass: HEREMap,
236   - schema: hereMapSettingsSchema,
237   - name: 'here'
238   - },
239   - 'image-map': {
240   - MapClass: ImageMap,
241   - schema: imageMapSettingsSchema,
242   - name: 'image-map'
243   - }
244   -};
245   -
246 203 export const defaultSettings: any = {
247 204 xPosKeyName: 'xPos',
248 205 yPosKeyName: 'yPos',
... ...
... ... @@ -15,12 +15,10 @@
15 15 ///
16 16
17 17 import {
18   - DEFAULT_MAP_PAGE_SIZE,
19 18 defaultSettings,
20 19 FormattedData,
21 20 hereProviders,
22 21 MapProviders,
23   - providerSets,
24 22 UnitedMapSettings
25 23 } from './map-models';
26 24 import LeafletMap from './leaflet-map';
... ... @@ -46,6 +44,7 @@ import _ from 'lodash';
46 44 import { EntityDataPageLink } from '@shared/models/query/query.models';
47 45 import { isDefined } from '@core/utils';
48 46 import { forkJoin, Observable, of } from 'rxjs';
  47 +import { providerSets } from '@home/components/widget/lib/maps/providers';
49 48
50 49 // @dynamic
51 50 export class MapWidgetController implements MapWidgetInterface {
... ... @@ -275,11 +274,7 @@ export class MapWidgetController implements MapWidgetInterface {
275 274 }
276 275
277 276 update() {
278   - const formattedData = parseData(this.data);
279   - this.map.updateData(this.data, formattedData, this.drawRoutes, this.settings.showPolygon);
280   - if (this.settings.draggableMarker) {
281   - this.map.setDataSources(formattedData);
282   - }
  277 + this.map.updateData(this.drawRoutes, this.settings.showPolygon);
283 278 this.map.setLoading(false);
284 279 }
285 280
... ...
... ... @@ -34,11 +34,10 @@ export class Marker {
34 34 tooltipOffset: L.LatLngTuple;
35 35 markerOffset: L.LatLngTuple;
36 36 tooltip: L.Popup;
37   - location: L.LatLngExpression;
38 37 data: FormattedData;
39 38 dataSources: FormattedData[];
40 39
41   - constructor(private map: LeafletMap, location: L.LatLngExpression, public settings: MarkerSettings,
  40 + constructor(private map: LeafletMap, private location: L.LatLng, public settings: MarkerSettings,
42 41 data?: FormattedData, dataSources?, onDragendListener?) {
43 42 this.setDataSources(data, dataSources);
44 43 this.leafletMarker = L.marker(location, {
... ... @@ -94,8 +93,11 @@ export class Marker {
94 93 }
95 94 }
96 95
97   - updateMarkerPosition(position: L.LatLngExpression) {
  96 + updateMarkerPosition(position: L.LatLng) {
  97 + if (!this.location.equals(position)) {
  98 + this.location = position;
98 99 this.leafletMarker.setLatLng(position);
  100 + }
99 101 }
100 102
101 103 updateMarkerLabel(settings: MarkerSettings) {
... ...
... ... @@ -35,6 +35,7 @@ export class GoogleMap extends LeafletMap {
35 35 constructor(ctx: WidgetContext, $container, options: UnitedMapSettings) {
36 36 super(ctx, $container, options);
37 37 this.resource = ctx.$injector.get(ResourcesService);
  38 + super.initSettings(options);
38 39 this.loadGoogle(() => {
39 40 const map = L.map($container, {attributionControl: false}).setView(options?.defaultCenterPosition, options?.defaultZoomLevel);
40 41 (L.gridLayer as any).googleMutant({
... ... @@ -42,7 +43,6 @@ export class GoogleMap extends LeafletMap {
42 43 }).addTo(map);
43 44 super.setMap(map);
44 45 }, options.gmApiKey);
45   - super.initSettings(options);
46 46 }
47 47
48 48 private loadGoogle(callback, apiKey = 'AIzaSyDoEx2kaGz3PxwbI9T7ccTSg5xjdw8Nw8Q') {
... ...
... ... @@ -25,7 +25,7 @@ export class HEREMap extends LeafletMap {
25 25 const map = L.map($container).setView(options?.defaultCenterPosition, options?.defaultZoomLevel);
26 26 const tileLayer = (L.tileLayer as any).provider(options.mapProviderHere || 'HERE.normalDay', options.credentials);
27 27 tileLayer.addTo(map);
28   - super.setMap(map);
29 28 super.initSettings(options);
  29 + super.setMap(map);
30 30 }
31 31 }
... ...
... ... @@ -47,8 +47,8 @@ export class ImageMap extends LeafletMap {
47 47 this.onResize(true);
48 48 } else {
49 49 this.onResize();
50   - super.setMap(this.map);
51 50 super.initSettings(options);
  51 + super.setMap(this.map);
52 52 }
53 53 });
54 54 }
... ...
... ... @@ -14,8 +14,50 @@
14 14 /// limitations under the License.
15 15 ///
16 16
17   -export * from './tencent-map';
18   -export * from './google-map';
19   -export * from './here-map';
20   -export * from './image-map';
21   -export * from './openstreet-map';
  17 +import {
  18 + googleMapSettingsSchema, hereMapSettingsSchema, imageMapSettingsSchema,
  19 + openstreetMapSettingsSchema,
  20 + tencentMapSettingsSchema
  21 +} from '@home/components/widget/lib/maps/schemes';
  22 +import { OpenStreetMap } from './openstreet-map';
  23 +import { TencentMap } from './tencent-map';
  24 +import { GoogleMap } from './google-map';
  25 +import { HEREMap } from './here-map';
  26 +import { ImageMap } from './image-map';
  27 +import { Type } from '@angular/core';
  28 +import LeafletMap from '@home/components/widget/lib/maps/leaflet-map';
  29 +import { JsonSettingsSchema } from '@shared/models/widget.models';
  30 +
  31 +interface IProvider {
  32 + MapClass: Type<LeafletMap>,
  33 + schema: JsonSettingsSchema,
  34 + name: string
  35 +}
  36 +
  37 +export const providerSets: { [key: string]: IProvider } = {
  38 + 'openstreet-map': {
  39 + MapClass: OpenStreetMap,
  40 + schema: openstreetMapSettingsSchema,
  41 + name: 'openstreet-map',
  42 + },
  43 + 'tencent-map': {
  44 + MapClass: TencentMap,
  45 + schema: tencentMapSettingsSchema,
  46 + name: 'tencent-map'
  47 + },
  48 + 'google-map': {
  49 + MapClass: GoogleMap,
  50 + schema: googleMapSettingsSchema,
  51 + name: 'google-map'
  52 + },
  53 + here: {
  54 + MapClass: HEREMap,
  55 + schema: hereMapSettingsSchema,
  56 + name: 'here'
  57 + },
  58 + 'image-map': {
  59 + MapClass: ImageMap,
  60 + schema: imageMapSettingsSchema,
  61 + name: 'image-map'
  62 + }
  63 +};
... ...
... ... @@ -29,7 +29,7 @@ export class OpenStreetMap extends LeafletMap {
29 29 else
30 30 tileLayer = (L.tileLayer as any).provider(options.mapProvider || 'OpenStreetMap.Mapnik');
31 31 tileLayer.addTo(map);
32   - super.setMap(map);
33 32 super.initSettings(options);
  33 + super.setMap(map);
34 34 }
35 35 }
... ...
... ... @@ -31,7 +31,7 @@ export class TencentMap extends LeafletMap {
31 31 attribution: '&copy;2020 Tencent - GS(2018)2236号- Data&copy; NavInfo'
32 32 }).addTo(map);
33 33 txLayer.addTo(map);
34   - super.setMap(map);
35 34 super.initSettings(options);
  35 + super.setMap(map);
36 36 }
37 37 }
... ...
... ... @@ -159,7 +159,7 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy
159 159 }
160 160 this.calcLabel();
161 161 this.calcTooltip(currentPosition.find(position => position.entityName === this.activeTrip.entityName));
162   - if (this.mapWidget) {
  162 + if (this.mapWidget && this.mapWidget.map && this.mapWidget.map.map) {
163 163 this.mapWidget.map.updatePolylines(this.interpolatedTimeData.map(ds => _.values(ds)), true, this.activeTrip);
164 164 if (this.settings.showPolygon) {
165 165 this.mapWidget.map.updatePolygons(this.interpolatedTimeData);
... ...