Showing
6 changed files
with
85 additions
and
54 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 { MapSettings, MarkerSettings, FormattedData } from './map-models'; | |
24 | +import { MapSettings, MarkerSettings, FormattedData, UnitedMapSettings, PolygonSettings } 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'; |
... | ... | @@ -31,18 +31,18 @@ import { Polygon } from './polygon'; |
31 | 31 | export default abstract class LeafletMap { |
32 | 32 | |
33 | 33 | markers: Map<string, Marker> = new Map(); |
34 | - dragMode = false; | |
34 | + dragMode = true; | |
35 | 35 | tooltips = []; |
36 | 36 | poly: Polyline; |
37 | 37 | polygon: Polygon; |
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: MapSettings & MarkerSettings; | |
41 | + options: UnitedMapSettings; | |
42 | 42 | isMarketCluster: boolean; |
43 | 43 | bounds: L.LatLngBounds; |
44 | 44 | |
45 | - constructor($container: HTMLElement, options: MapSettings & MarkerSettings) { | |
45 | + constructor(public $container: HTMLElement, options: UnitedMapSettings) { | |
46 | 46 | this.options = options; |
47 | 47 | } |
48 | 48 | |
... | ... | @@ -55,7 +55,7 @@ export default abstract class LeafletMap { |
55 | 55 | mapProvider, |
56 | 56 | credentials, |
57 | 57 | defaultCenterPosition, |
58 | - draggebleMarker, | |
58 | + draggableMarker, | |
59 | 59 | markerClusteringSetting }: MapSettings = options; |
60 | 60 | if (disableScrollZooming) { |
61 | 61 | this.map.scrollWheelZoom.disable(); |
... | ... | @@ -66,7 +66,19 @@ export default abstract class LeafletMap { |
66 | 66 | } |
67 | 67 | |
68 | 68 | addMarkerControl() { |
69 | - if (this.options.draggebleMarker) | |
69 | + if (this.options.draggableMarker) { | |
70 | + let mousePositionOnMap: L.LatLng; | |
71 | + let addMarker: L.Control; | |
72 | + this.map.on('mouseup', (e: L.LeafletMouseEvent) => { | |
73 | + mousePositionOnMap = e.latlng | |
74 | + }) | |
75 | + const dragListener = (e: L.DragEndEvent) => { | |
76 | + if (e.type === 'dragend' && mousePositionOnMap) { | |
77 | + L.marker(mousePositionOnMap, { | |
78 | + }).addTo(this.map); | |
79 | + } | |
80 | + addMarker.setPosition('topright') | |
81 | + } | |
70 | 82 | L.Control.AddMarker = L.Control.extend({ |
71 | 83 | onAdd(map) { |
72 | 84 | const img = L.DomUtil.create('img') as any; |
... | ... | @@ -74,22 +86,27 @@ export default abstract class LeafletMap { |
74 | 86 | img.style.width = '32px'; |
75 | 87 | img.style.height = '32px'; |
76 | 88 | img.onclick = this.dragMarker; |
89 | + img.draggable = true; | |
90 | + const draggableImg = new L.Draggable(img); | |
91 | + draggableImg.enable(); | |
92 | + draggableImg.on('dragend', dragListener) | |
77 | 93 | return img; |
78 | 94 | }, |
79 | 95 | addHooks() { |
80 | - L.DomEvent.on(window as any, 'onclick', this.enableDragMode, this); | |
96 | + // L.DomEvent.on(window as any, 'onmousedown', this.dragMarker, this); | |
81 | 97 | }, |
82 | 98 | onRemove(map) { |
83 | 99 | }, |
84 | - dragMarker: ($event) => { | |
85 | - this.dragMode = !this.dragMode; | |
86 | - } | |
100 | + dragMarker: this.dragMarker | |
101 | + | |
87 | 102 | } as any); |
88 | 103 | |
89 | - L.control.addMarker = (opts) => { | |
90 | - return new L.Control.AddMarker(opts); | |
104 | + L.control.addMarker = (opts) => { | |
105 | + return new L.Control.AddMarker(opts); | |
106 | + } | |
107 | + | |
108 | + addMarker = L.control.addMarker({ position: 'topright' }).addTo(this.map); | |
91 | 109 | } |
92 | - L.control.addMarker({ position: 'topright' }).addTo(this.map); | |
93 | 110 | } |
94 | 111 | |
95 | 112 | public setMap(map: L.Map) { |
... | ... | @@ -99,12 +116,12 @@ export default abstract class LeafletMap { |
99 | 116 | this.bounds = map.getBounds(); |
100 | 117 | } |
101 | 118 | else this.bounds = new L.LatLngBounds(null, null); |
102 | - if (this.options.draggebleMarker) { | |
119 | + if (this.options.draggableMarker) { | |
103 | 120 | this.addMarkerControl(); |
104 | - this.map.on('click', (e: L.LeafletMouseEvent) => { | |
105 | - if (this.dragMode) | |
106 | - this.saveMarkerLocation(this.convertToCustomFormat(e.latlng)); | |
107 | - }) | |
121 | + /* this.map.on('click', (e: L.LeafletMouseEvent) => { | |
122 | + if (this.dragMode) | |
123 | + this.saveMarkerLocation(this.convertToCustomFormat(e.latlng)); | |
124 | + })*/ | |
108 | 125 | } |
109 | 126 | this.map$.next(this.map); |
110 | 127 | } |
... | ... | @@ -177,9 +194,14 @@ export default abstract class LeafletMap { |
177 | 194 | }); |
178 | 195 | } |
179 | 196 | |
180 | - private createMarker(key, data: FormattedData, dataSources, settings: MarkerSettings) { | |
197 | + dragMarker = (e, data?) => { | |
198 | + if (e.type !== 'dragend') return; | |
199 | + this.saveMarkerLocation({ ...data, ...this.convertToCustomFormat(e.target._latlng) }); | |
200 | + } | |
201 | + | |
202 | + private createMarker(key, data: FormattedData, dataSources: FormattedData[], settings: MarkerSettings) { | |
181 | 203 | this.ready$.subscribe(() => { |
182 | - const newMarker = new Marker(this.map, this.convertPosition(data), settings, data, dataSources); | |
204 | + const newMarker = new Marker(this.map, this.convertPosition(data), settings, data, dataSources, () => { }, this.dragMarker); | |
183 | 205 | this.map.fitBounds(this.bounds.extend(newMarker.leafletMarker.getLatLng())); |
184 | 206 | this.markers.set(key, newMarker); |
185 | 207 | }); |
... | ... | @@ -239,7 +261,7 @@ export default abstract class LeafletMap { |
239 | 261 | |
240 | 262 | // Polygon |
241 | 263 | |
242 | - updatePolygons(polyData: Array<Array<any>>) { | |
264 | + updatePolygons(polyData: any[]) { | |
243 | 265 | polyData.forEach((data: any) => { |
244 | 266 | if (data.data.length && data.dataKey.name === this.options.polygonKeyName) { |
245 | 267 | if (typeof (data?.data[0][1]) === 'string') { |
... | ... | @@ -255,7 +277,7 @@ export default abstract class LeafletMap { |
255 | 277 | }); |
256 | 278 | } |
257 | 279 | |
258 | - createPolygon(data, dataSources, settings) { | |
280 | + createPolygon(data: FormattedData, dataSources: FormattedData[], settings: PolygonSettings) { | |
259 | 281 | this.ready$.subscribe(() => { |
260 | 282 | this.polygon = new Polygon(this.map, data, dataSources, settings); |
261 | 283 | const bounds = this.bounds.extend(this.polygon.leafletPoly.getBounds()); | ... | ... |
... | ... | @@ -21,7 +21,7 @@ export type MarkerImageFunction = (data: FormattedData, dsData: FormattedData[], |
21 | 21 | |
22 | 22 | export type MapSettings = { |
23 | 23 | polygonKeyName: any; |
24 | - draggebleMarker: any; | |
24 | + draggableMarker: boolean; | |
25 | 25 | initCallback?: () => any; |
26 | 26 | defaultZoomLevel?: number; |
27 | 27 | dontFitMapBounds?: boolean; |
... | ... | @@ -58,7 +58,7 @@ export type MarkerSettings = { |
58 | 58 | labelColor: string; |
59 | 59 | labelText: string; |
60 | 60 | useLabelFunction: boolean; |
61 | - draggable?: boolean; | |
61 | + draggableMarker: boolean; | |
62 | 62 | showTooltip?: boolean; |
63 | 63 | color?: string; |
64 | 64 | autocloseTooltip: boolean; |
... | ... | @@ -110,9 +110,9 @@ export type PolylineSettings = { |
110 | 110 | decoratorCustomColor: any; |
111 | 111 | |
112 | 112 | |
113 | - colorFunction(colorFunction: any, arg1: any[]): string; | |
114 | - strokeOpacityFunction(strokeOpacityFunction: any, arg1: any[]): number; | |
115 | - strokeWeightFunction(strokeWeightFunction: any, arg1: any[]): number; | |
113 | + colorFunction: GenericFunction; | |
114 | + strokeOpacityFunction: GenericFunction; | |
115 | + strokeWeightFunction: GenericFunction; | |
116 | 116 | } |
117 | 117 | |
118 | 118 | export interface HistorySelectSettings { | ... | ... |
... | ... | @@ -32,10 +32,14 @@ import { MapWidgetStaticInterface, MapWidgetInterface } from './map-widget.inter |
32 | 32 | import { OpenStreetMap, TencentMap, GoogleMap, HEREMap, ImageMap } from './providers'; |
33 | 33 | import { parseFunction, parseArray, parseData } from '@app/core/utils'; |
34 | 34 | import { initSchema, addToSchema, mergeSchemes, addCondition, addGroupInfo } from '@app/core/schema-utils'; |
35 | -import { AttributeScope, EntityId } from '@app/shared/public-api'; | |
35 | +import { AttributeScope, EntityId, JsonSettingsSchema } from '@app/shared/public-api'; | |
36 | 36 | import { forkJoin } from 'rxjs'; |
37 | 37 | import { WidgetContext } from '@app/modules/home/models/widget-component.models'; |
38 | 38 | import { AttributeService } from '@app/core/public-api'; |
39 | +import { getDefCenterPosition } from './maps-utils'; | |
40 | + | |
41 | +let providerSets; | |
42 | +let defaultSettings; | |
39 | 43 | |
40 | 44 | export class MapWidgetController implements MapWidgetInterface { |
41 | 45 | |
... | ... | @@ -63,19 +67,19 @@ export class MapWidgetController implements MapWidgetInterface { |
63 | 67 | provider: MapProviders; |
64 | 68 | schema; |
65 | 69 | data; |
66 | - settings:UnitedMapSettings; | |
70 | + settings: UnitedMapSettings; | |
67 | 71 | |
68 | - public static dataKeySettingsSchema(): Object { | |
72 | + public static dataKeySettingsSchema(): object { | |
69 | 73 | return {}; |
70 | 74 | } |
71 | 75 | |
72 | 76 | public static getProvidersSchema() { |
73 | 77 | return mergeSchemes([mapProviderSchema, |
74 | 78 | ...Object.values(providerSets)?.map( |
75 | - setting => addCondition(setting?.schema, `model.provider === '${setting.name}'`))]); | |
79 | + (setting: IProvider) => addCondition(setting?.schema, `model.provider === '${setting.name}'`))]); | |
76 | 80 | } |
77 | 81 | |
78 | - public static settingsSchema(mapProvider, drawRoutes): Object { | |
82 | + public static settingsSchema(mapProvider, drawRoutes): object { | |
79 | 83 | const schema = initSchema(); |
80 | 84 | addToSchema(schema, this.getProvidersSchema()); |
81 | 85 | addGroupInfo(schema, 'Map Provider Settings'); |
... | ... | @@ -93,7 +97,7 @@ export class MapWidgetController implements MapWidgetInterface { |
93 | 97 | return schema; |
94 | 98 | } |
95 | 99 | |
96 | - public static actionSources(): Object { | |
100 | + public static actionSources(): object { | |
97 | 101 | return { |
98 | 102 | markerClick: { |
99 | 103 | name: 'widget-action.marker-click', |
... | ... | @@ -114,9 +118,7 @@ export class MapWidgetController implements MapWidgetInterface { |
114 | 118 | } |
115 | 119 | |
116 | 120 | setMarkerLocation = (e) => { |
117 | - const s = this.ctx.$injector.get(AttributeService); | |
118 | - console.log('MapWidgetController -> setMarkerLocation -> s', s, s.saveEntityAttributes) | |
119 | - const attributeService = this.ctx.$scope.$injector.get(this.ctx.servicesMap.get('attributeService')); | |
121 | + const attributeService = this.ctx.$injector.get(AttributeService); | |
120 | 122 | forkJoin( |
121 | 123 | this.data.filter(data => !!e[data.dataKey.name]) |
122 | 124 | .map(data => { |
... | ... | @@ -140,15 +142,7 @@ export class MapWidgetController implements MapWidgetInterface { |
140 | 142 | initSettings(settings: any) { |
141 | 143 | const functionParams = ['data', 'dsData', 'dsIndex']; |
142 | 144 | this.provider = settings.provider ? settings.provider : this.mapProvider; |
143 | - | |
144 | - function getDefCenterPosition(position) { | |
145 | - if (typeof (position) === 'string') | |
146 | - return position.split(','); | |
147 | - if (typeof (position) === 'object') | |
148 | - return position; | |
149 | - return [0, 0]; | |
150 | - } | |
151 | - | |
145 | + console.log(settings.draggableMarker); | |
152 | 146 | const customOptions = { |
153 | 147 | provider: this.provider, |
154 | 148 | mapUrl: settings?.mapImageUrl, |
... | ... | @@ -159,9 +153,9 @@ export class MapWidgetController implements MapWidgetInterface { |
159 | 153 | markerImageFunction: parseFunction(settings.markerImageFunction, ['data', 'images', 'dsData', 'dsIndex']), |
160 | 154 | labelColor: this.ctx.widgetConfig.color, |
161 | 155 | tooltipPattern: settings.tooltipPattern || |
162 | - '<b>${entityName}</b><br/><br/><b>Latitude:</b> ${' + settings.latKeyName + ':7}<br/><b>Longitude:</b> ${' + settings.lngKeyName + ':7}', | |
156 | + '<b>${entityName}</b><br/><br/><b>Latitude:</b> ${' + | |
157 | + settings.latKeyName + ':7}<br/><b>Longitude:</b> ${' + settings.lngKeyName + ':7}', | |
163 | 158 | defaultCenterPosition: getDefCenterPosition(settings?.defaultCenterPosition), |
164 | - useDraggableMarker: true, | |
165 | 159 | currentImage: (settings.useMarkerImage && settings.markerImage?.length) ? { |
166 | 160 | url: settings.markerImage, |
167 | 161 | size: settings.markerImageSize || 34 |
... | ... | @@ -197,8 +191,13 @@ export class MapWidgetController implements MapWidgetInterface { |
197 | 191 | |
198 | 192 | export let TbMapWidgetV2: MapWidgetStaticInterface = MapWidgetController; |
199 | 193 | |
194 | +interface IProvider { | |
195 | + MapClass: LeafletMap, | |
196 | + schema: JsonSettingsSchema, | |
197 | + name: string | |
198 | +} | |
200 | 199 | |
201 | -const providerSets = { | |
200 | +providerSets = { | |
202 | 201 | 'openstreet-map': { |
203 | 202 | MapClass: OpenStreetMap, |
204 | 203 | schema: openstreetMapSettingsSchema, |
... | ... | @@ -226,7 +225,7 @@ const providerSets = { |
226 | 225 | } |
227 | 226 | } |
228 | 227 | |
229 | -const defaultSettings = { | |
228 | +defaultSettings = { | |
230 | 229 | xPosKeyName: 'xPos', |
231 | 230 | yPosKeyName: 'yPos', |
232 | 231 | markerOffsetX: 0.5, |
... | ... | @@ -259,5 +258,5 @@ const defaultSettings = { |
259 | 258 | minZoomLevel: 16, |
260 | 259 | credentials: '', |
261 | 260 | markerClusteringSetting: null, |
262 | - draggebleMarker: false | |
261 | + draggableMarker: false | |
263 | 262 | } |
\ No newline at end of file | ... | ... |
... | ... | @@ -44,3 +44,12 @@ export function findAngle(startPoint, endPoint) { |
44 | 44 | return parseInt(angle.toFixed(2), 10); |
45 | 45 | } |
46 | 46 | |
47 | + | |
48 | +export function getDefCenterPosition(position) { | |
49 | + if (typeof (position) === 'string') | |
50 | + return position.split(','); | |
51 | + if (typeof (position) === 'object') | |
52 | + return position; | |
53 | + return [0, 0]; | |
54 | +} | |
55 | + | ... | ... |
... | ... | @@ -28,10 +28,11 @@ export class Marker { |
28 | 28 | data: FormattedData; |
29 | 29 | dataSources: FormattedData[]; |
30 | 30 | |
31 | - constructor(private map: L.Map, location: L.LatLngExpression, public settings: MarkerSettings, data?, dataSources?, onClickListener?, onDragendListener?) { | |
31 | + constructor(private map: L.Map, location: L.LatLngExpression, public settings: MarkerSettings, | |
32 | + data?, dataSources?, onClickListener?, onDragendListener?) { | |
32 | 33 | this.setDataSources(data, dataSources); |
33 | 34 | this.leafletMarker = L.marker(location, { |
34 | - draggable: settings.draggable | |
35 | + draggable: settings.draggableMarker | |
35 | 36 | }); |
36 | 37 | |
37 | 38 | this.createMarkerIcon((iconInfo) => { |
... | ... | @@ -51,7 +52,7 @@ export class Marker { |
51 | 52 | } |
52 | 53 | |
53 | 54 | if (onDragendListener) { |
54 | - this.leafletMarker.on('dragend', onDragendListener); | |
55 | + this.leafletMarker.on('dragend', (e) => onDragendListener(e, this.data)); | |
55 | 56 | } |
56 | 57 | } |
57 | 58 | ... | ... |
... | ... | @@ -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: UnitedMapSettings) { | |
31 | + constructor($container: HTMLElement, options: UnitedMapSettings) { | |
32 | 32 | super($container, options); |
33 | 33 | aspectCache(options.mapUrl).subscribe(aspect => { |
34 | 34 | this.aspect = aspect; | ... | ... |