Showing
14 changed files
with
209 additions
and
137 deletions
... | ... | @@ -21,7 +21,7 @@ import 'leaflet.markercluster/dist/MarkerCluster.css' |
21 | 21 | import 'leaflet.markercluster/dist/MarkerCluster.Default.css' |
22 | 22 | import 'leaflet.markercluster/dist/leaflet.markercluster' |
23 | 23 | |
24 | -import { MapOptions, MarkerSettings } from './map-models'; | |
24 | +import { MapSettings, MarkerSettings, FormattedData } from './map-models'; | |
25 | 25 | import { Marker } from './markers'; |
26 | 26 | import { Observable, of, BehaviorSubject, Subject } from 'rxjs'; |
27 | 27 | import { filter } from 'rxjs/operators'; |
... | ... | @@ -38,15 +38,15 @@ export default abstract class LeafletMap { |
38 | 38 | map: L.Map; |
39 | 39 | map$: BehaviorSubject<L.Map> = new BehaviorSubject(null); |
40 | 40 | ready$: Observable<L.Map> = this.map$.pipe(filter(map => !!map)); |
41 | - options: MapOptions; | |
41 | + options: MapSettings & MarkerSettings; | |
42 | 42 | isMarketCluster: boolean; |
43 | 43 | bounds: L.LatLngBounds; |
44 | 44 | |
45 | - constructor($container: HTMLElement, options: MapOptions) { | |
45 | + constructor($container: HTMLElement, options: MapSettings & MarkerSettings) { | |
46 | 46 | this.options = options; |
47 | 47 | } |
48 | 48 | |
49 | - public initSettings(options: MapOptions) { | |
49 | + public initSettings(options: MapSettings) { | |
50 | 50 | const { initCallback, |
51 | 51 | defaultZoomLevel, |
52 | 52 | dontFitMapBounds, |
... | ... | @@ -56,7 +56,7 @@ export default abstract class LeafletMap { |
56 | 56 | credentials, |
57 | 57 | defaultCenterPosition, |
58 | 58 | draggebleMarker, |
59 | - markerClusteringSetting }: MapOptions = options; | |
59 | + markerClusteringSetting }: MapSettings = options; | |
60 | 60 | if (disableScrollZooming) { |
61 | 61 | this.map.scrollWheelZoom.disable(); |
62 | 62 | } |
... | ... | @@ -86,16 +86,12 @@ export default abstract class LeafletMap { |
86 | 86 | } |
87 | 87 | } as any); |
88 | 88 | |
89 | - L.control.addMarker = function (opts) { | |
89 | + L.control.addMarker = (opts) => { | |
90 | 90 | return new L.Control.AddMarker(opts); |
91 | 91 | } |
92 | 92 | L.control.addMarker({ position: 'topright' }).addTo(this.map); |
93 | 93 | } |
94 | 94 | |
95 | - /*inited() {/// !!!! | |
96 | - return !!this.map; | |
97 | - }*/ | |
98 | - | |
99 | 95 | public setMap(map: L.Map) { |
100 | 96 | this.map = map; |
101 | 97 | if (this.options.useDefaultCenterPosition) { |
... | ... | @@ -117,10 +113,6 @@ export default abstract class LeafletMap { |
117 | 113 | |
118 | 114 | } |
119 | 115 | |
120 | - getContainer() { | |
121 | - return this.map; | |
122 | - } | |
123 | - | |
124 | 116 | createLatLng(lat: number, lng: number): L.LatLng { |
125 | 117 | return L.latLng(lat, lng); |
126 | 118 | } |
... | ... | @@ -147,8 +139,13 @@ export default abstract class LeafletMap { |
147 | 139 | return this.map.getCenter(); |
148 | 140 | } |
149 | 141 | |
150 | - convertPosition(expression: any): L.LatLng { | |
151 | - return L.latLng(expression[this.options.latKeyName], expression[this.options.lngKeyName]) as L.LatLng; | |
142 | + convertPosition(expression: object): L.LatLng { | |
143 | + const lat = expression[this.options.latKeyName]; | |
144 | + const lng = expression[this.options.lngKeyName]; | |
145 | + if (isNaN(lat) || isNaN(lng)) | |
146 | + return null; | |
147 | + else | |
148 | + return L.latLng(lat, lng) as L.LatLng; | |
152 | 149 | } |
153 | 150 | |
154 | 151 | convertToCustomFormat(position: L.LatLng): object { |
... | ... | @@ -161,24 +158,26 @@ export default abstract class LeafletMap { |
161 | 158 | // Markers |
162 | 159 | updateMarkers(markersData) { |
163 | 160 | markersData.forEach(data => { |
164 | - if (data.rotationAngle) { | |
165 | - this.options.icon = L.divIcon({ | |
166 | - html: `<div class="arrow" style="transform: rotate(${data.rotationAngle}deg)"><div>` | |
167 | - }) | |
168 | - } | |
169 | - else { | |
170 | - this.options.icon = null; | |
171 | - } | |
172 | - if (this.markers.get(data.aliasName)) { | |
173 | - this.updateMarker(data.aliasName, data, markersData, this.options as MarkerSettings) | |
174 | - } | |
175 | - else { | |
176 | - this.createMarker(data.aliasName, data, markersData, this.options as MarkerSettings); | |
161 | + if (this.convertPosition(data)) { | |
162 | + if (data.rotationAngle) { | |
163 | + this.options.icon = L.divIcon({ | |
164 | + html: `<div class="arrow" style="transform: rotate(${data.rotationAngle}deg)"><div>` | |
165 | + }) | |
166 | + } | |
167 | + else { | |
168 | + this.options.icon = null; | |
169 | + } | |
170 | + if (this.markers.get(data.aliasName)) { | |
171 | + this.updateMarker(data.aliasName, data, markersData, this.options) | |
172 | + } | |
173 | + else { | |
174 | + this.createMarker(data.aliasName, data, markersData, this.options as MarkerSettings); | |
175 | + } | |
177 | 176 | } |
178 | 177 | }); |
179 | 178 | } |
180 | 179 | |
181 | - private createMarker(key, data, dataSources, settings: MarkerSettings) { | |
180 | + private createMarker(key, data: FormattedData, dataSources, settings: MarkerSettings) { | |
182 | 181 | this.ready$.subscribe(() => { |
183 | 182 | const newMarker = new Marker(this.map, this.convertPosition(data), settings, data, dataSources); |
184 | 183 | this.map.fitBounds(this.bounds.extend(newMarker.leafletMarker.getLatLng())); |
... | ... | @@ -219,10 +218,11 @@ export default abstract class LeafletMap { |
219 | 218 | }) |
220 | 219 | } |
221 | 220 | |
222 | - createPolyline(data, dataSources, settings) { | |
221 | + createPolyline(data: any[], dataSources, settings) { | |
223 | 222 | if (data.length) |
224 | 223 | this.ready$.subscribe(() => { |
225 | - this.poly = new Polyline(this.map, data.map(data => this.convertPosition(data)), data, dataSources, settings); | |
224 | + this.poly = new Polyline(this.map, | |
225 | + data.map(el => this.convertPosition(el)).filter(el => !!el), data, dataSources, settings); | |
226 | 226 | const bounds = this.bounds.extend(this.poly.leafletPoly.getBounds()); |
227 | 227 | if (bounds.isValid()) { |
228 | 228 | this.map.fitBounds(bounds); |
... | ... | @@ -237,7 +237,7 @@ export default abstract class LeafletMap { |
237 | 237 | }); |
238 | 238 | } |
239 | 239 | |
240 | - // polygon | |
240 | + // Polygon | |
241 | 241 | |
242 | 242 | updatePolygons(polyData: Array<Array<any>>) { |
243 | 243 | polyData.forEach((data: any) => { |
... | ... | @@ -268,7 +268,7 @@ export default abstract class LeafletMap { |
268 | 268 | |
269 | 269 | updatePolygon(data, dataSources, settings) { |
270 | 270 | this.ready$.subscribe(() => { |
271 | - // this.polygon.updatePolygon(settings, data, dataSources); | |
271 | + // this.polygon.updatePolygon(settings, data, dataSources); | |
272 | 272 | }); |
273 | 273 | } |
274 | 274 | } |
\ No newline at end of file | ... | ... |
1 | 1 | /// |
2 | 2 | /// Copyright © 2016-2020 The Thingsboard Authors |
3 | 3 | /// |
4 | -/// Licensed under the Apache License, Version 2.0 (the "License"); | |
4 | +/// Licensed under the Apache License; Version 2.0 (the "License"); | |
5 | 5 | /// you may not use this file except in compliance with the License. |
6 | 6 | /// You may obtain a copy of the License at |
7 | 7 | /// |
8 | 8 | /// http://www.apache.org/licenses/LICENSE-2.0 |
9 | 9 | /// |
10 | -/// Unless required by applicable law or agreed to in writing, software | |
11 | -/// distributed under the License is distributed on an "AS IS" BASIS, | |
12 | -/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
10 | +/// Unless required by applicable law or agreed to in writing; software | |
11 | +/// distributed under the License is distributed on an "AS IS" BASIS; | |
12 | +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND; either express or implied. | |
13 | 13 | /// See the License for the specific language governing permissions and |
14 | 14 | /// limitations under the License. |
15 | 15 | /// |
16 | 16 | |
17 | -import { LatLngExpression, LatLngTuple } from 'leaflet'; | |
17 | +import { LatLngTuple } from 'leaflet'; | |
18 | 18 | |
19 | -export interface MapOptions { | |
19 | +export type GenericFunction = (data: FormattedData, dsData: FormattedData[], dsIndex: number) => string; | |
20 | +export type MarkerImageFunction = (data: FormattedData, dsData: FormattedData[], dsIndex: number) => string; | |
21 | + | |
22 | +export type MapSettings = { | |
20 | 23 | polygonKeyName: any; |
21 | 24 | draggebleMarker: any; |
22 | - initCallback?: Function, | |
23 | - defaultZoomLevel?: number, | |
24 | - dontFitMapBounds?: boolean, | |
25 | - disableScrollZooming?: boolean, | |
26 | - minZoomLevel?: number, | |
27 | - latKeyName?: string, | |
28 | - lngKeyName?: string, | |
29 | - xPosKeyName?: string, | |
30 | - yPosKeyName?: string, | |
31 | - mapProvider: MapProviders, | |
25 | + initCallback?: () => any; | |
26 | + defaultZoomLevel?: number; | |
27 | + dontFitMapBounds?: boolean; | |
28 | + disableScrollZooming?: boolean; | |
29 | + minZoomLevel?: number; | |
30 | + latKeyName?: string; | |
31 | + lngKeyName?: string; | |
32 | + xPosKeyName?: string; | |
33 | + yPosKeyName?: string; | |
34 | + mapProvider: MapProviders; | |
32 | 35 | mapUrl?: string; |
33 | - credentials?: any, // declare credentials format | |
34 | - defaultCenterPosition?: LatLngTuple, | |
35 | - markerClusteringSetting?, | |
36 | - useDefaultCenterPosition?: boolean, | |
37 | - gmDefaultMapType?: string, | |
36 | + credentials?: any; // declare credentials format | |
37 | + defaultCenterPosition?: LatLngTuple; | |
38 | + markerClusteringSetting?; | |
39 | + useDefaultCenterPosition?: boolean; | |
40 | + gmDefaultMapType?: string; | |
38 | 41 | useLabelFunction: string; |
39 | 42 | icon?: any; |
40 | 43 | } |
... | ... | @@ -47,15 +50,73 @@ export enum MapProviders { |
47 | 50 | tencent = 'tencent-map' |
48 | 51 | } |
49 | 52 | |
50 | -export interface MarkerSettings extends MapOptions { | |
53 | +export type MarkerSettings = { | |
51 | 54 | tooltipPattern?: any; |
52 | 55 | icon?: any; |
53 | - showLabel?: boolean, | |
54 | - draggable?: boolean, | |
55 | - showTooltip?: boolean, | |
56 | - color?: string, | |
56 | + showLabel?: boolean; | |
57 | + label: string; | |
58 | + labelColor: string; | |
59 | + labelText: string; | |
60 | + useLabelFunction: boolean; | |
61 | + draggable?: boolean; | |
62 | + showTooltip?: boolean; | |
63 | + color?: string; | |
64 | + autocloseTooltip: boolean; | |
65 | + displayTooltipAction: string; | |
57 | 66 | currentImage?: string; |
58 | - useMarkerImageFunction?: boolean, | |
59 | - markerImages?: string[], | |
60 | - markerImageFunction?: Function; | |
61 | -} | |
\ No newline at end of file | ||
67 | + useMarkerImageFunction?: boolean; | |
68 | + markerImages?: string[]; | |
69 | + | |
70 | + labelFunction: GenericFunction; | |
71 | + markerImageFunction?: MarkerImageFunction; | |
72 | +} | |
73 | + | |
74 | +export interface FormattedData { | |
75 | + aliasName: string; | |
76 | + entityName: string; | |
77 | + $datasource: string; | |
78 | + dsIndex: number; | |
79 | + deviceType: string | |
80 | +} | |
81 | + | |
82 | +export type PolygonSettings = { | |
83 | + showPolygon: boolean; | |
84 | + showTooltip: any; | |
85 | + polygonStrokeOpacity: number; | |
86 | + polygonOpacity: number; | |
87 | + polygonStrokeWeight: number; | |
88 | + polygonStrokeColor: string; | |
89 | + polygonColor: string; | |
90 | + autocloseTooltip: boolean; | |
91 | + displayTooltipAction: string; | |
92 | +} | |
93 | + | |
94 | +export type PolylineSettings = { | |
95 | + usePolylineDecorator: any; | |
96 | + autocloseTooltip: boolean; | |
97 | + displayTooltipAction: string; | |
98 | + useColorFunction: any; | |
99 | + color: string; | |
100 | + useStrokeOpacityFunction: any; | |
101 | + strokeOpacity: number; | |
102 | + useStrokeWeightFunction: any; | |
103 | + strokeWeight: number; | |
104 | + decoratorOffset: string | number; | |
105 | + endDecoratorOffset: string | number; | |
106 | + decoratorRepeat: string | number; | |
107 | + decoratorSymbol: any; | |
108 | + decoratorSymbolSize: any; | |
109 | + useDecoratorCustomColor: any; | |
110 | + decoratorCustomColor: any; | |
111 | + | |
112 | + | |
113 | + colorFunction(colorFunction: any, arg1: any[]): string; | |
114 | + strokeOpacityFunction(strokeOpacityFunction: any, arg1: any[]): number; | |
115 | + strokeWeightFunction(strokeWeightFunction: any, arg1: any[]): number; | |
116 | +} | |
117 | + | |
118 | +export interface HistorySelectSettings { | |
119 | + buttonColor: string; | |
120 | +} | |
121 | + | |
122 | +export type UnitedMapSettings = MapSettings & PolygonSettings & MarkerSettings & PolygonSettings; | |
\ No newline at end of file | ... | ... |
... | ... | @@ -14,7 +14,7 @@ |
14 | 14 | /// limitations under the License. |
15 | 15 | /// |
16 | 16 | |
17 | -import { MapProviders, MapOptions } from './map-models'; | |
17 | +import { MapProviders, MapSettings, MarkerSettings, PolygonSettings, UnitedMapSettings } from './map-models'; | |
18 | 18 | import LeafletMap from './leaflet-map'; |
19 | 19 | import { |
20 | 20 | openstreetMapSettingsSchema, |
... | ... | @@ -63,7 +63,7 @@ export class MapWidgetController implements MapWidgetInterface { |
63 | 63 | provider: MapProviders; |
64 | 64 | schema; |
65 | 65 | data; |
66 | - settings; | |
66 | + settings:UnitedMapSettings; | |
67 | 67 | |
68 | 68 | public static dataKeySettingsSchema(): Object { |
69 | 69 | return {}; | ... | ... |
... | ... | @@ -16,12 +16,13 @@ |
16 | 16 | |
17 | 17 | import L from 'leaflet'; |
18 | 18 | import _ from 'lodash'; |
19 | +import { MarkerSettings, PolylineSettings, PolygonSettings } from './map-models'; | |
19 | 20 | |
20 | -export function createTooltip(target: L.Layer, settings): L.Popup { | |
21 | +export function createTooltip(target: L.Layer, settings: MarkerSettings | PolylineSettings | PolygonSettings): L.Popup { | |
21 | 22 | const popup = L.popup(); |
22 | 23 | popup.setContent(''); |
23 | 24 | target.bindPopup(popup, { autoClose: settings.autocloseTooltip, closeOnClick: false }); |
24 | - if (settings.displayTooltipAction == 'hover') { | |
25 | + if (settings.displayTooltipAction === 'hover') { | |
25 | 26 | target.off('click'); |
26 | 27 | target.on('mouseover', function () { |
27 | 28 | this.openPopup(); |
... | ... | @@ -40,6 +41,6 @@ export function getRatio(firsMoment: number, secondMoment: number, intermediateM |
40 | 41 | export function findAngle(startPoint, endPoint) { |
41 | 42 | let angle = -Math.atan2(endPoint.latitude - startPoint.latitude, endPoint.longitude - startPoint.longitude); |
42 | 43 | angle = angle * 180 / Math.PI; |
43 | - return parseInt(angle.toFixed(2)); | |
44 | + return parseInt(angle.toFixed(2), 10); | |
44 | 45 | } |
45 | 46 | ... | ... |
... | ... | @@ -15,23 +15,20 @@ |
15 | 15 | /// |
16 | 16 | |
17 | 17 | import L from 'leaflet'; |
18 | -import { MarkerSettings } from './map-models'; | |
18 | +import { MarkerSettings, FormattedData } from './map-models'; | |
19 | 19 | import { aspectCache, safeExecute, parseTemplate } from '@app/core/utils'; |
20 | 20 | import { createTooltip } from './maps-utils'; |
21 | 21 | |
22 | 22 | export class Marker { |
23 | 23 | |
24 | 24 | leafletMarker: L.Marker; |
25 | - | |
26 | - tooltipOffset; | |
27 | - tooltip; | |
28 | - location; | |
29 | - data; | |
30 | - dataSources; | |
25 | + tooltipOffset: [number, number]; | |
26 | + tooltip: L.Popup; | |
27 | + location: L.LatLngExpression; | |
28 | + data: FormattedData; | |
29 | + dataSources: FormattedData[]; | |
31 | 30 | |
32 | 31 | constructor(private map: L.Map, location: L.LatLngExpression, public settings: MarkerSettings, data?, dataSources?, onClickListener?, onDragendListener?) { |
33 | - // this.map = map; | |
34 | - this.location = location; | |
35 | 32 | this.setDataSources(data, dataSources); |
36 | 33 | this.leafletMarker = L.marker(location, { |
37 | 34 | draggable: settings.draggable |
... | ... | @@ -58,12 +55,12 @@ export class Marker { |
58 | 55 | } |
59 | 56 | } |
60 | 57 | |
61 | - setDataSources(data, dataSources) { | |
58 | + setDataSources(data: FormattedData, dataSources: FormattedData[]) { | |
62 | 59 | this.data = data; |
63 | 60 | this.dataSources = dataSources; |
64 | 61 | } |
65 | 62 | |
66 | - updateMarkerTooltip(data) { | |
63 | + updateMarkerTooltip(data: FormattedData) { | |
67 | 64 | this.tooltip.setContent(parseTemplate(this.settings.tooltipPattern, data)); |
68 | 65 | } |
69 | 66 | |
... | ... | @@ -71,7 +68,7 @@ export class Marker { |
71 | 68 | this.leafletMarker.setLatLng(position); |
72 | 69 | } |
73 | 70 | |
74 | - updateMarkerLabel(settings) { | |
71 | + updateMarkerLabel(settings: MarkerSettings) { | |
75 | 72 | this.leafletMarker.unbindTooltip(); |
76 | 73 | |
77 | 74 | if (settings.showLabel) { |
... | ... | @@ -90,7 +87,7 @@ export class Marker { |
90 | 87 | }); |
91 | 88 | } |
92 | 89 | |
93 | - updateMarkerIcon(settings) { | |
90 | + updateMarkerIcon(settings: MarkerSettings) { | |
94 | 91 | this.createMarkerIcon((iconInfo) => { |
95 | 92 | this.leafletMarker.setIcon(iconInfo.icon); |
96 | 93 | this.tooltipOffset = [0, -iconInfo.size[1] + 10]; | ... | ... |
... | ... | @@ -14,15 +14,16 @@ |
14 | 14 | /// limitations under the License. |
15 | 15 | /// |
16 | 16 | |
17 | -import L from 'leaflet'; | |
17 | +import L, { LatLngExpression } from 'leaflet'; | |
18 | 18 | import { createTooltip } from './maps-utils'; |
19 | +import { PolygonSettings } from './map-models'; | |
19 | 20 | |
20 | 21 | export class Polygon { |
21 | 22 | |
22 | 23 | leafletPoly: L.Polygon; |
23 | 24 | tooltip; |
24 | 25 | |
25 | - constructor(public map, coordinates, dataSources, settings, onClickListener?) { | |
26 | + constructor(public map, coordinates, dataSources, settings: PolygonSettings, onClickListener?) { | |
26 | 27 | this.leafletPoly = L.polygon(coordinates, { |
27 | 28 | fill: true, |
28 | 29 | fillColor: settings.polygonColor, |
... | ... | @@ -33,7 +34,7 @@ export class Polygon { |
33 | 34 | }).addTo(this.map); |
34 | 35 | |
35 | 36 | if (settings.showTooltip) { |
36 | - this.tooltip = createTooltip(this.leafletPoly, settings); | |
37 | + this.tooltip = createTooltip(this.leafletPoly, settings); | |
37 | 38 | } |
38 | 39 | if (onClickListener) { |
39 | 40 | this.leafletPoly.on('click', onClickListener); |
... | ... | @@ -44,11 +45,13 @@ export class Polygon { |
44 | 45 | this.map.removeLayer(this.leafletPoly); |
45 | 46 | } |
46 | 47 | |
47 | - updatePolygonColor(settings, color) { | |
48 | - const style = { | |
48 | + updatePolygonColor(settings) { | |
49 | + console.log('Polygon -> updatePolygonColor -> settings', settings) | |
50 | + const style: L.PathOptions = { | |
51 | + | |
49 | 52 | fill: true, |
50 | - fillColor: color, | |
51 | - color, | |
53 | + fillColor: settings.color, | |
54 | + color: settings.color, | |
52 | 55 | weight: settings.polygonStrokeWeight, |
53 | 56 | fillOpacity: settings.polygonOpacity, |
54 | 57 | opacity: settings.polygonStrokeOpacity |
... | ... | @@ -60,7 +63,7 @@ export class Polygon { |
60 | 63 | return this.leafletPoly.getLatLngs(); |
61 | 64 | } |
62 | 65 | |
63 | - setPolygonLatLngs(latLngs) { | |
66 | + setPolygonLatLngs(latLngs: LatLngExpression[]) { | |
64 | 67 | this.leafletPoly.setLatLngs(latLngs); |
65 | 68 | this.leafletPoly.redraw(); |
66 | 69 | } | ... | ... |
... | ... | @@ -18,51 +18,62 @@ import L, { PolylineDecoratorOptions } from 'leaflet'; |
18 | 18 | import 'leaflet-polylinedecorator'; |
19 | 19 | |
20 | 20 | import { safeExecute } from '@app/core/utils'; |
21 | +import { PolylineSettings, PolygonSettings } from './map-models'; | |
21 | 22 | |
22 | 23 | export class Polyline { |
23 | 24 | |
24 | 25 | leafletPoly: L.Polyline; |
26 | + polylineDecorator: L.PolylineDecorator; | |
25 | 27 | dataSources; |
26 | 28 | data; |
27 | 29 | |
28 | - constructor(private map: L.Map, locations, data, dataSources, settings) { | |
30 | + constructor(private map: L.Map, locations, data, dataSources, settings: PolylineSettings) { | |
29 | 31 | this.dataSources = dataSources; |
30 | 32 | this.data = data; |
31 | 33 | |
32 | 34 | this.leafletPoly = L.polyline(locations, |
33 | - this.getPolyStyle(settings, data, dataSources) | |
35 | + this.getPolyStyle(settings) | |
34 | 36 | ).addTo(this.map); |
35 | 37 | if (settings.usePolylineDecorator) { |
36 | - L.polylineDecorator(this.leafletPoly, { | |
37 | - patterns: [ | |
38 | - { | |
39 | - offset: settings.decoratorOffset, | |
40 | - endOffset: settings.endDecoratorOffset, | |
41 | - repeat: settings.decoratorRepeat, | |
42 | - symbol: L.Symbol[settings.decoratorSymbol]({ | |
43 | - pixelSize: settings.decoratorSymbolSize, | |
44 | - polygon: false, | |
45 | - pathOptions: { | |
46 | - color: settings.useDecoratorCustomColor ? settings.decoratorCustomColor : this.getPolyStyle(settings, data, dataSources).color, | |
47 | - stroke: true | |
48 | - } | |
49 | - }) | |
50 | - } | |
51 | - ], | |
52 | - interactive: false, | |
53 | - } as PolylineDecoratorOptions).addTo(this.map); | |
38 | + this.polylineDecorator = L.polylineDecorator(this.leafletPoly, this.getDecoratorSettings(settings)).addTo(this.map); | |
54 | 39 | } |
55 | 40 | } |
56 | 41 | |
42 | + getDecoratorSettings(settings: PolylineSettings): PolylineDecoratorOptions { | |
43 | + return { | |
44 | + patterns: [ | |
45 | + { | |
46 | + offset: settings.decoratorOffset, | |
47 | + endOffset: settings.endDecoratorOffset, | |
48 | + repeat: settings.decoratorRepeat, | |
49 | + symbol: L.Symbol[settings.decoratorSymbol]({ | |
50 | + pixelSize: settings.decoratorSymbolSize, | |
51 | + polygon: false, | |
52 | + pathOptions: { | |
53 | + color: settings.useDecoratorCustomColor ? settings.decoratorCustomColor : this.getPolyStyle(settings).color, | |
54 | + stroke: true | |
55 | + } | |
56 | + }) | |
57 | + } | |
58 | + ], | |
59 | + interactive: false, | |
60 | + } as PolylineDecoratorOptions | |
61 | + } | |
62 | + | |
57 | 63 | updatePolyline(settings, data, dataSources) { |
58 | - this.leafletPoly.setStyle(this.getPolyStyle(settings, data, dataSources)); | |
64 | + this.leafletPoly.setStyle(this.getPolyStyle(settings)); | |
65 | + this.setPolylineLatLngs(data); | |
66 | + this.polylineDecorator.setPaths(this.leafletPoly); | |
59 | 67 | } |
60 | 68 | |
61 | - getPolyStyle(settings, data, dataSources): L.PolylineOptions { | |
69 | + getPolyStyle(settings: PolylineSettings): L.PolylineOptions { | |
62 | 70 | return { |
63 | - color: settings.useColorFunction ? safeExecute(settings.colorFunction, [data, dataSources, data[0]?.dsIndex]) : settings.color, | |
64 | - opacity: settings.useStrokeOpacityFunction ? safeExecute(settings.strokeOpacityFunction, [data, dataSources, data[0]?.dsIndex]) : settings.strokeOpacity, | |
65 | - weight: settings.useStrokeWeightFunction ? safeExecute(settings.strokeWeightFunction, [data, dataSources, data[0]?.dsIndex]) : settings.strokeWeight, | |
71 | + color: settings.useColorFunction ? | |
72 | + safeExecute(settings.colorFunction, [this.data, this.dataSources, this.data[0]?.dsIndex]) : settings.color, | |
73 | + opacity: settings.useStrokeOpacityFunction ? | |
74 | + safeExecute(settings.strokeOpacityFunction, [this.data, this.dataSources, this.data[0]?.dsIndex]) : settings.strokeOpacity, | |
75 | + weight: settings.useStrokeWeightFunction ? | |
76 | + safeExecute(settings.strokeWeightFunction, [this.data, this.dataSources, this.data[0]?.dsIndex]) : settings.strokeWeight, | |
66 | 77 | } |
67 | 78 | } |
68 | 79 | ... | ... |
... | ... | @@ -17,14 +17,14 @@ |
17 | 17 | |
18 | 18 | import L from 'leaflet'; |
19 | 19 | import LeafletMap from '../leaflet-map'; |
20 | -import { MapOptions } from '../map-models'; | |
20 | +import { MapSettings, UnitedMapSettings } from '../map-models'; | |
21 | 21 | import 'leaflet.gridlayer.googlemutant'; |
22 | 22 | |
23 | 23 | let googleLoaded = false; |
24 | 24 | |
25 | 25 | |
26 | 26 | export class GoogleMap extends LeafletMap { |
27 | - constructor($container, options: MapOptions) { | |
27 | + constructor($container, options: UnitedMapSettings) { | |
28 | 28 | |
29 | 29 | super($container, options); |
30 | 30 | this.loadGoogle(() => { | ... | ... |
... | ... | @@ -16,11 +16,10 @@ |
16 | 16 | |
17 | 17 | import L from 'leaflet'; |
18 | 18 | import LeafletMap from '../leaflet-map'; |
19 | -import { MapOptions } from '../map-models'; | |
19 | +import { MapSettings, UnitedMapSettings } from '../map-models'; | |
20 | 20 | |
21 | 21 | export class HEREMap extends LeafletMap { |
22 | - constructor($container, options: MapOptions) { | |
23 | - console.log('HEREMap -> constructor -> options', options) | |
22 | + constructor($container, options: UnitedMapSettings) { | |
24 | 23 | const defaultCredentials = |
25 | 24 | { |
26 | 25 | app_id: 'AhM6TzD9ThyK78CT3ptx', | ... | ... |
... | ... | @@ -16,7 +16,7 @@ |
16 | 16 | |
17 | 17 | import L from 'leaflet'; |
18 | 18 | import LeafletMap from '../leaflet-map'; |
19 | -import { MapOptions } from '../map-models'; | |
19 | +import { MapSettings, UnitedMapSettings } from '../map-models'; | |
20 | 20 | import { aspectCache } from '@app/core/utils'; |
21 | 21 | |
22 | 22 | const maxZoom = 4;// ? |
... | ... | @@ -28,7 +28,7 @@ export class ImageMap extends LeafletMap { |
28 | 28 | width = 0; |
29 | 29 | height = 0; |
30 | 30 | |
31 | - constructor(private $container: HTMLElement, options: MapOptions) { | |
31 | + constructor(private $container: HTMLElement, options: UnitedMapSettings) { | |
32 | 32 | super($container, options); |
33 | 33 | aspectCache(options.mapUrl).subscribe(aspect => { |
34 | 34 | this.aspect = aspect; | ... | ... |
... | ... | @@ -16,10 +16,10 @@ |
16 | 16 | |
17 | 17 | import L from 'leaflet'; |
18 | 18 | import LeafletMap from '../leaflet-map'; |
19 | -import { MapOptions } from '../map-models'; | |
19 | +import { MapSettings, UnitedMapSettings } from '../map-models'; | |
20 | 20 | |
21 | 21 | export class OpenStreetMap extends LeafletMap { |
22 | - constructor($container, options: MapOptions) { | |
22 | + constructor($container, options: UnitedMapSettings) { | |
23 | 23 | super($container, options); |
24 | 24 | const map = L.map($container).setView(options?.defaultCenterPosition, options?.defaultZoomLevel); |
25 | 25 | const tileLayer = (L.tileLayer as any).provider('OpenStreetMap.Mapnik'); | ... | ... |
... | ... | @@ -17,10 +17,10 @@ |
17 | 17 | |
18 | 18 | import L from 'leaflet'; |
19 | 19 | import LeafletMap from '../leaflet-map'; |
20 | -import { MapOptions } from '../map-models'; | |
20 | +import { MapSettings, UnitedMapSettings } from '../map-models'; | |
21 | 21 | |
22 | 22 | export class TencentMap extends LeafletMap { |
23 | - constructor($container, options: MapOptions) { | |
23 | + constructor($container, options: UnitedMapSettings) { | |
24 | 24 | super($container, options); |
25 | 25 | const txUrl = 'http://rt{s}.map.gtimg.com/realtimerender?z={z}&x={x}&y={y}&type=vector&style=0'; |
26 | 26 | const map = L.map($container).setView(options?.defaultCenterPosition, options?.defaultZoomLevel); | ... | ... |
... | ... | @@ -97,7 +97,6 @@ export class TripAnimationComponent implements OnInit, AfterViewInit { |
97 | 97 | timeUpdated(time: number) { |
98 | 98 | const currentPosition = this.interpolatedData.map(dataSource => dataSource[time]); |
99 | 99 | this.activeTrip = currentPosition[0]; |
100 | - console.log("TripAnimationComponent -> timeUpdated -> this.interpolatedData", this.interpolatedData) | |
101 | 100 | if (this.settings.showPolygon) { |
102 | 101 | this.mapWidget.map.updatePolygons(this.interpolatedData); |
103 | 102 | } |
... | ... | @@ -120,11 +119,11 @@ export class TripAnimationComponent implements OnInit, AfterViewInit { |
120 | 119 | } |
121 | 120 | |
122 | 121 | showHideTooltip() { |
123 | - const tooltipText: string = this.settings.useTooltipFunction ? safeExecute(this.settings.tooolTipFunction, [this.activeTrip, this.historicalData, 0]) | |
122 | + const tooltipText: string = this.settings.useTooltipFunction ? | |
123 | + safeExecute(this.settings.tooolTipFunction, [this.activeTrip, this.historicalData, 0]) | |
124 | 124 | : this.settings.tooltipPattern; |
125 | 125 | |
126 | 126 | this.mainTooltip = this.sanitizer.sanitize(SecurityContext.HTML, parseTemplate(tooltipText, this.activeTrip)) |
127 | - console.log("TripAnimationComponent -> showHideTooltip -> this.mainTooltip", this.mainTooltip) | |
128 | 127 | this.visibleTooltip = !this.visibleTooltip; |
129 | 128 | } |
130 | 129 | |
... | ... | @@ -132,7 +131,7 @@ export class TripAnimationComponent implements OnInit, AfterViewInit { |
132 | 131 | |
133 | 132 | const result = {}; |
134 | 133 | |
135 | - for (let i = 1, j = 0; i < originData.length, j < interpolatedIntervals.length;) { | |
134 | + for (let i = 1, j = 0; i < originData.length && j < interpolatedIntervals.length;) { | |
136 | 135 | const currentTime = interpolatedIntervals[j]; |
137 | 136 | while (originData[i].time < currentTime) i++; |
138 | 137 | const before = originData[i - 1]; | ... | ... |
... | ... | @@ -17,6 +17,7 @@ |
17 | 17 | import { Component, OnInit, OnChanges, Input, Output, EventEmitter, ChangeDetectorRef } from '@angular/core'; |
18 | 18 | import { interval, Subscription, Subscriber, SubscriptionLike, Observer } from 'rxjs'; |
19 | 19 | import { filter, tap } from 'rxjs/operators'; |
20 | +import { HistorySelectSettings } from '@app/modules/home/components/widget/lib/maps/map-models'; | |
20 | 21 | |
21 | 22 | @Component({ |
22 | 23 | selector: 'tb-history-selector', |
... | ... | @@ -25,10 +26,10 @@ import { filter, tap } from 'rxjs/operators'; |
25 | 26 | }) |
26 | 27 | export class HistorySelectorComponent implements OnInit, OnChanges { |
27 | 28 | |
28 | - @Input() settings | |
29 | + @Input() settings: HistorySelectSettings | |
29 | 30 | @Input() intervals = []; |
30 | 31 | |
31 | - @Output() onTimeUpdated: EventEmitter<number> = new EventEmitter(); | |
32 | + @Output() timeUpdated: EventEmitter<number> = new EventEmitter(); | |
32 | 33 | |
33 | 34 | animationTime; |
34 | 35 | minTimeIndex = 0; |
... | ... | @@ -58,7 +59,7 @@ export class HistorySelectorComponent implements OnInit, OnChanges { |
58 | 59 | tap(() => this.index++)).subscribe(() => { |
59 | 60 | if (this.index < this.maxTimeIndex) { |
60 | 61 | this.cd.detectChanges(); |
61 | - this.onTimeUpdated.emit(this.intervals[this.index]); | |
62 | + this.timeUpdated.emit(this.intervals[this.index]); | |
62 | 63 | } |
63 | 64 | else { |
64 | 65 | this.interval.complete(); |
... | ... | @@ -70,12 +71,12 @@ export class HistorySelectorComponent implements OnInit, OnChanges { |
70 | 71 | this.playing = false; |
71 | 72 | this.interval = null; |
72 | 73 | this.cd.detectChanges(); |
73 | - }); | |
74 | + }); | |
74 | 75 | } |
75 | 76 | |
76 | 77 | reeneble() { |
77 | 78 | if (this.playing) { |
78 | - let position = this.index; | |
79 | + const position = this.index; | |
79 | 80 | this.interval.complete(); |
80 | 81 | this.index = position; |
81 | 82 | this.play(); |
... | ... | @@ -85,7 +86,7 @@ export class HistorySelectorComponent implements OnInit, OnChanges { |
85 | 86 | pause() { |
86 | 87 | this.playing = false; |
87 | 88 | this.cd.detectChanges(); |
88 | - this.onTimeUpdated.emit(this.intervals[this.index]); | |
89 | + this.timeUpdated.emit(this.intervals[this.index]); | |
89 | 90 | } |
90 | 91 | |
91 | 92 | moveNext() { |
... | ... | @@ -113,6 +114,6 @@ export class HistorySelectorComponent implements OnInit, OnChanges { |
113 | 114 | } |
114 | 115 | |
115 | 116 | changeIndex() { |
116 | - this.onTimeUpdated.emit(this.intervals[this.index]); | |
117 | + this.timeUpdated.emit(this.intervals[this.index]); | |
117 | 118 | } |
118 | 119 | } | ... | ... |