Commit 047230a2284ba88e88eccc5050ab701fa36b9ad3
Committed by
GitHub
1 parent
a4f5d355
Map/3.0 (#2544)
* add base map infrastructure * add leaflet css * add tencent map * add google maps support * added image map support * refactor schemes * here maps support && WIP on markers * add simple marker suppor * data update & polyline support * map bouds support * add some settings support * add map provider select to settings * labels support * WIP on trip animation widget * WIP on history control and route interpolation * trip-animation map provider & custom markers * comleted track marker & history controls * add license headers * label fix & tooltips support * WIP on polygons * marker dropping support * add polygon support * add label to trip animation * WIP on tooltips * lint anf typed leaflet AddMarker * some typing and poly improvements * add typing * add marker creation * update proxy * save position fix * add bounds padding * update map widget bendle && bugfixes * update marker placement widget * add licenses * reomove log * fix sizes * entity and map fixes * Fix tile server support form OSM and zoom level fix Co-authored-by: Artem Halushko <ahalushko@thingboards.io> Co-authored-by: Adsumus <artemtv42@gmail.com>
Showing
3 changed files
with
34 additions
and
16 deletions
@@ -23,7 +23,7 @@ import 'leaflet.markercluster/dist/leaflet.markercluster' | @@ -23,7 +23,7 @@ import 'leaflet.markercluster/dist/leaflet.markercluster' | ||
23 | 23 | ||
24 | import { MapSettings, MarkerSettings, FormattedData, UnitedMapSettings, PolygonSettings, PolylineSettings } from './map-models'; | 24 | import { MapSettings, MarkerSettings, FormattedData, UnitedMapSettings, PolygonSettings, PolylineSettings } from './map-models'; |
25 | import { Marker } from './markers'; | 25 | import { Marker } from './markers'; |
26 | -import { Observable, of, BehaviorSubject, Subject } from 'rxjs'; | 26 | +import { Observable, BehaviorSubject } from 'rxjs'; |
27 | import { filter } from 'rxjs/operators'; | 27 | import { filter } from 'rxjs/operators'; |
28 | import { Polyline } from './polyline'; | 28 | import { Polyline } from './polyline'; |
29 | import { Polygon } from './polygon'; | 29 | import { Polygon } from './polygon'; |
@@ -64,7 +64,7 @@ export default abstract class LeafletMap { | @@ -64,7 +64,7 @@ export default abstract class LeafletMap { | ||
64 | let mousePositionOnMap: L.LatLng; | 64 | let mousePositionOnMap: L.LatLng; |
65 | let addMarker: L.Control; | 65 | let addMarker: L.Control; |
66 | this.map.on('mouseup', (e: L.LeafletMouseEvent) => { | 66 | this.map.on('mouseup', (e: L.LeafletMouseEvent) => { |
67 | - mousePositionOnMap = e.latlng | 67 | + mousePositionOnMap = e.latlng; |
68 | }) | 68 | }) |
69 | const dragListener = (e: L.DragEndEvent) => { | 69 | const dragListener = (e: L.DragEndEvent) => { |
70 | if (e.type === 'dragend' && mousePositionOnMap) { | 70 | if (e.type === 'dragend' && mousePositionOnMap) { |
@@ -164,6 +164,23 @@ export default abstract class LeafletMap { | @@ -164,6 +164,23 @@ export default abstract class LeafletMap { | ||
164 | return this.map.getCenter(); | 164 | return this.map.getCenter(); |
165 | } | 165 | } |
166 | 166 | ||
167 | + fitBounds(bounds, useDefaultZoom = false) { | ||
168 | + if (bounds.isValid()) { | ||
169 | + if ((this.options.dontFitMapBounds || useDefaultZoom) && this.options.defaultZoomLevel) { | ||
170 | + this.map.setZoom(this.options.defaultZoomLevel, { animate: false }); | ||
171 | + this.map.panTo(bounds.getCenter(), { animate: false }); | ||
172 | + } else { | ||
173 | + this.map.once('zoomend', function () { | ||
174 | + if (!this.options.defaultZoomLevel && this.options.map.getZoom() > this.options.minZoomLevel) { | ||
175 | + this.map.setZoom(this.options.minZoomLevel, { animate: false }); | ||
176 | + } | ||
177 | + }); | ||
178 | + this.map.fitBounds(bounds, { padding: [50, 50], animate: false }); | ||
179 | + } | ||
180 | + this.bounds = this.bounds.extend(bounds); | ||
181 | + } | ||
182 | + } | ||
183 | + | ||
167 | convertPosition(expression: object): L.LatLng { | 184 | convertPosition(expression: object): L.LatLng { |
168 | if (!expression) return null; | 185 | if (!expression) return null; |
169 | const lat = expression[this.options.latKeyName]; | 186 | const lat = expression[this.options.latKeyName]; |
@@ -185,7 +202,7 @@ export default abstract class LeafletMap { | @@ -185,7 +202,7 @@ export default abstract class LeafletMap { | ||
185 | updateMarkers(markersData) { | 202 | updateMarkers(markersData) { |
186 | markersData.forEach(data => { | 203 | markersData.forEach(data => { |
187 | if (this.convertPosition(data)) { | 204 | if (this.convertPosition(data)) { |
188 | - if (data.rotationAngle) { | 205 | + if (data.rotationAngle || data.rotationAngle === 0) { |
189 | this.options.icon = L.divIcon({ | 206 | this.options.icon = L.divIcon({ |
190 | html: `<div class="arrow" style="transform: translate(-10px, -10px) rotate(${data.rotationAngle}deg);"><div>` | 207 | html: `<div class="arrow" style="transform: translate(-10px, -10px) rotate(${data.rotationAngle}deg);"><div>` |
191 | }) | 208 | }) |
@@ -211,8 +228,7 @@ export default abstract class LeafletMap { | @@ -211,8 +228,7 @@ export default abstract class LeafletMap { | ||
211 | private createMarker(key: string, data: FormattedData, dataSources: FormattedData[], settings: MarkerSettings, setFocus = true) { | 228 | private createMarker(key: string, data: FormattedData, dataSources: FormattedData[], settings: MarkerSettings, setFocus = true) { |
212 | this.ready$.subscribe(() => { | 229 | this.ready$.subscribe(() => { |
213 | const newMarker = new Marker(this.map, this.convertPosition(data), settings, data, dataSources, () => { }, this.dragMarker); | 230 | const newMarker = new Marker(this.map, this.convertPosition(data), settings, data, dataSources, () => { }, this.dragMarker); |
214 | - if (setFocus /*&& settings.fitMapBounds*/) | ||
215 | - this.map.fitBounds(this.bounds.extend(newMarker.leafletMarker.getLatLng()).pad(0.2)); | 231 | + this.fitBounds(this.bounds.extend(newMarker.leafletMarker.getLatLng()), setFocus); |
216 | this.markers.set(key, newMarker); | 232 | this.markers.set(key, newMarker); |
217 | }); | 233 | }); |
218 | } | 234 | } |
@@ -260,11 +276,8 @@ export default abstract class LeafletMap { | @@ -260,11 +276,8 @@ export default abstract class LeafletMap { | ||
260 | this.ready$.subscribe(() => { | 276 | this.ready$.subscribe(() => { |
261 | const poly = new Polyline(this.map, | 277 | const poly = new Polyline(this.map, |
262 | data.map(el => this.convertPosition(el)).filter(el => !!el), data, dataSources, settings); | 278 | data.map(el => this.convertPosition(el)).filter(el => !!el), data, dataSources, settings); |
263 | - const bounds = this.bounds.extend(poly.leafletPoly.getBounds().pad(0.2)); | ||
264 | - if (bounds.isValid()) { | ||
265 | - this.map.fitBounds(bounds); | ||
266 | - this.bounds = bounds; | ||
267 | - } | 279 | + const bounds = this.bounds.extend(poly.leafletPoly.getBounds()); |
280 | + this.fitBounds(bounds) | ||
268 | this.polylines.set(data[0].entityName, poly) | 281 | this.polylines.set(data[0].entityName, poly) |
269 | }); | 282 | }); |
270 | } | 283 | } |
@@ -296,7 +309,7 @@ export default abstract class LeafletMap { | @@ -296,7 +309,7 @@ export default abstract class LeafletMap { | ||
296 | createPolygon(key: string, data: LatLngTuple[], dataSources: DatasourceData[], settings: PolygonSettings) { | 309 | createPolygon(key: string, data: LatLngTuple[], dataSources: DatasourceData[], settings: PolygonSettings) { |
297 | this.ready$.subscribe(() => { | 310 | this.ready$.subscribe(() => { |
298 | const polygon = new Polygon(this.map, data, dataSources, settings); | 311 | const polygon = new Polygon(this.map, data, dataSources, settings); |
299 | - const bounds = this.bounds.extend(polygon.leafletPoly.getBounds().pad(0.2)); | 312 | + const bounds = this.bounds.extend(polygon.leafletPoly.getBounds()); |
300 | if (bounds.isValid()) { | 313 | if (bounds.isValid()) { |
301 | this.map.fitBounds(bounds); | 314 | this.map.fitBounds(bounds); |
302 | this.bounds = bounds; | 315 | this.bounds = bounds; |
@@ -14,7 +14,7 @@ | @@ -14,7 +14,7 @@ | ||
14 | /// limitations under the License. | 14 | /// limitations under the License. |
15 | /// | 15 | /// |
16 | 16 | ||
17 | -import L from 'leaflet'; | 17 | +import L, { LatLngLiteral } from 'leaflet'; |
18 | import LeafletMap from '../leaflet-map'; | 18 | import LeafletMap from '../leaflet-map'; |
19 | import { MapSettings, UnitedMapSettings } from '../map-models'; | 19 | import { MapSettings, UnitedMapSettings } from '../map-models'; |
20 | import { aspectCache } from '@app/core/utils'; | 20 | import { aspectCache } from '@app/core/utils'; |
@@ -93,7 +93,6 @@ export class ImageMap extends LeafletMap { | @@ -93,7 +93,6 @@ export class ImageMap extends LeafletMap { | ||
93 | lastCenterPos.y /= prevHeight; | 93 | lastCenterPos.y /= prevHeight; |
94 | this.updateBounds(updateImage, lastCenterPos); | 94 | this.updateBounds(updateImage, lastCenterPos); |
95 | this.map.invalidateSize(true); | 95 | this.map.invalidateSize(true); |
96 | - // this.updateMarkers(); | ||
97 | } | 96 | } |
98 | 97 | ||
99 | } | 98 | } |
@@ -113,7 +112,6 @@ export class ImageMap extends LeafletMap { | @@ -113,7 +112,6 @@ export class ImageMap extends LeafletMap { | ||
113 | attributionControl: false | 112 | attributionControl: false |
114 | }); | 113 | }); |
115 | this.updateBounds(updateImage); | 114 | this.updateBounds(updateImage); |
116 | - // this.updateMarkers(); | ||
117 | } | 115 | } |
118 | } | 116 | } |
119 | 117 | ||
@@ -127,7 +125,14 @@ export class ImageMap extends LeafletMap { | @@ -127,7 +125,14 @@ export class ImageMap extends LeafletMap { | ||
127 | return L.CRS.Simple.pointToLatLng({ x, y } as L.PointExpression, maxZoom - 1); | 125 | return L.CRS.Simple.pointToLatLng({ x, y } as L.PointExpression, maxZoom - 1); |
128 | } | 126 | } |
129 | 127 | ||
130 | - latLngToPoint(latLng) { | 128 | + latLngToPoint(latLng: LatLngLiteral) { |
131 | return L.CRS.Simple.latLngToPoint(latLng, maxZoom - 1); | 129 | return L.CRS.Simple.latLngToPoint(latLng, maxZoom - 1); |
132 | } | 130 | } |
131 | + | ||
132 | + /* convertToCustomFormat(position: L.LatLng): object { | ||
133 | + return { | ||
134 | + [this.options.xPosKeyName]: (position.lng + 180) / 360, | ||
135 | + [this.options.yPosKeyName]: (position.lat + 180) / 360 | ||
136 | + } | ||
137 | + }*/ | ||
133 | } | 138 | } |
@@ -22,7 +22,7 @@ export class OpenStreetMap extends LeafletMap { | @@ -22,7 +22,7 @@ export class OpenStreetMap extends LeafletMap { | ||
22 | constructor($container, options: UnitedMapSettings) { | 22 | constructor($container, options: UnitedMapSettings) { |
23 | super($container, options); | 23 | super($container, options); |
24 | const map = L.map($container).setView(options?.defaultCenterPosition, options?.defaultZoomLevel); | 24 | const map = L.map($container).setView(options?.defaultCenterPosition, options?.defaultZoomLevel); |
25 | - const tileLayer = (L.tileLayer as any).provider('OpenStreetMap.Mapnik'); | 25 | + const tileLayer = (L.tileLayer as any).provider(options.mapProvider || 'OpenStreetMap.Mapnik'); |
26 | tileLayer.addTo(map); | 26 | tileLayer.addTo(map); |
27 | super.setMap(map); | 27 | super.setMap(map); |
28 | super.initSettings(options); | 28 | super.initSettings(options); |