Commit 047230a2284ba88e88eccc5050ab701fa36b9ad3

Authored by ArtemHalushko
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>
... ... @@ -23,7 +23,7 @@ import 'leaflet.markercluster/dist/leaflet.markercluster'
23 23
24 24 import { MapSettings, MarkerSettings, FormattedData, UnitedMapSettings, PolygonSettings, PolylineSettings } from './map-models';
25 25 import { Marker } from './markers';
26   -import { Observable, of, BehaviorSubject, Subject } from 'rxjs';
  26 +import { Observable, BehaviorSubject } from 'rxjs';
27 27 import { filter } from 'rxjs/operators';
28 28 import { Polyline } from './polyline';
29 29 import { Polygon } from './polygon';
... ... @@ -64,7 +64,7 @@ export default abstract class LeafletMap {
64 64 let mousePositionOnMap: L.LatLng;
65 65 let addMarker: L.Control;
66 66 this.map.on('mouseup', (e: L.LeafletMouseEvent) => {
67   - mousePositionOnMap = e.latlng
  67 + mousePositionOnMap = e.latlng;
68 68 })
69 69 const dragListener = (e: L.DragEndEvent) => {
70 70 if (e.type === 'dragend' && mousePositionOnMap) {
... ... @@ -164,6 +164,23 @@ export default abstract class LeafletMap {
164 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 184 convertPosition(expression: object): L.LatLng {
168 185 if (!expression) return null;
169 186 const lat = expression[this.options.latKeyName];
... ... @@ -185,7 +202,7 @@ export default abstract class LeafletMap {
185 202 updateMarkers(markersData) {
186 203 markersData.forEach(data => {
187 204 if (this.convertPosition(data)) {
188   - if (data.rotationAngle) {
  205 + if (data.rotationAngle || data.rotationAngle === 0) {
189 206 this.options.icon = L.divIcon({
190 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 228 private createMarker(key: string, data: FormattedData, dataSources: FormattedData[], settings: MarkerSettings, setFocus = true) {
212 229 this.ready$.subscribe(() => {
213 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 232 this.markers.set(key, newMarker);
217 233 });
218 234 }
... ... @@ -260,11 +276,8 @@ export default abstract class LeafletMap {
260 276 this.ready$.subscribe(() => {
261 277 const poly = new Polyline(this.map,
262 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 281 this.polylines.set(data[0].entityName, poly)
269 282 });
270 283 }
... ... @@ -296,7 +309,7 @@ export default abstract class LeafletMap {
296 309 createPolygon(key: string, data: LatLngTuple[], dataSources: DatasourceData[], settings: PolygonSettings) {
297 310 this.ready$.subscribe(() => {
298 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 313 if (bounds.isValid()) {
301 314 this.map.fitBounds(bounds);
302 315 this.bounds = bounds;
... ...
... ... @@ -14,7 +14,7 @@
14 14 /// limitations under the License.
15 15 ///
16 16
17   -import L from 'leaflet';
  17 +import L, { LatLngLiteral } from 'leaflet';
18 18 import LeafletMap from '../leaflet-map';
19 19 import { MapSettings, UnitedMapSettings } from '../map-models';
20 20 import { aspectCache } from '@app/core/utils';
... ... @@ -93,7 +93,6 @@ export class ImageMap extends LeafletMap {
93 93 lastCenterPos.y /= prevHeight;
94 94 this.updateBounds(updateImage, lastCenterPos);
95 95 this.map.invalidateSize(true);
96   - // this.updateMarkers();
97 96 }
98 97
99 98 }
... ... @@ -113,7 +112,6 @@ export class ImageMap extends LeafletMap {
113 112 attributionControl: false
114 113 });
115 114 this.updateBounds(updateImage);
116   - // this.updateMarkers();
117 115 }
118 116 }
119 117
... ... @@ -127,7 +125,14 @@ export class ImageMap extends LeafletMap {
127 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 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 }
\ No newline at end of file
... ...
... ... @@ -22,7 +22,7 @@ export class OpenStreetMap extends LeafletMap {
22 22 constructor($container, options: UnitedMapSettings) {
23 23 super($container, options);
24 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 26 tileLayer.addTo(map);
27 27 super.setMap(map);
28 28 super.initSettings(options);
... ...