Commit cff36668ed73b3f0b5b9eab23576c373373c49ee

Authored by Igor Kulikov
Committed by GitHub
2 parents 5caba218 7f8c3ad0

Merge pull request #3940 from kalutkaz/fixMapPolygon

[3.2.1] Fix map polygon
@@ -30,6 +30,7 @@ import { Datasource, DatasourceData } from '@shared/models/widget.models'; @@ -30,6 +30,7 @@ import { Datasource, DatasourceData } from '@shared/models/widget.models';
30 import _ from 'lodash'; 30 import _ from 'lodash';
31 import { mapProviderSchema, providerSets } from '@home/components/widget/lib/maps/schemes'; 31 import { mapProviderSchema, providerSets } from '@home/components/widget/lib/maps/schemes';
32 import { addCondition, mergeSchemes } from '@core/schema-utils'; 32 import { addCondition, mergeSchemes } from '@core/schema-utils';
  33 +import L, {Projection} from "leaflet";
33 34
34 export function getProviderSchema(mapProvider: MapProviders, ignoreImageMap = false) { 35 export function getProviderSchema(mapProvider: MapProviders, ignoreImageMap = false) {
35 const providerSchema = _.cloneDeep(mapProviderSchema); 36 const providerSchema = _.cloneDeep(mapProviderSchema);
@@ -443,3 +444,21 @@ export function createLoadingDiv(loadingText: string): JQuery<HTMLElement> { @@ -443,3 +444,21 @@ export function createLoadingDiv(loadingText: string): JQuery<HTMLElement> {
443 </div> 444 </div>
444 `); 445 `);
445 } 446 }
  447 +
  448 +export function checkLngLat(point: L.LatLng, southWest: L.LatLng, northEast: L.LatLng, offset = 0): L.LatLng {
  449 + const maxLngMap = northEast.lng - offset;
  450 + const minLngMap = southWest.lng + offset;
  451 + const maxLatMap = northEast.lat - offset;
  452 + const minLatMap = southWest.lat + offset;
  453 + if (point.lng > maxLngMap) {
  454 + point.lng = maxLngMap;
  455 + } else if (point.lng < minLngMap) {
  456 + point.lng = minLngMap;
  457 + }
  458 + if (point.lat > maxLatMap) {
  459 + point.lat = maxLatMap;
  460 + } else if (point.lat < minLatMap) {
  461 + point.lat = minLatMap;
  462 + }
  463 + return point;
  464 +}
@@ -16,12 +16,12 @@ @@ -16,12 +16,12 @@
16 16
17 import L, { 17 import L, {
18 FeatureGroup, 18 FeatureGroup,
19 - Icon, 19 + Icon, LatLng,
20 LatLngBounds, 20 LatLngBounds,
21 LatLngTuple, 21 LatLngTuple,
22 markerClusterGroup, 22 markerClusterGroup,
23 MarkerClusterGroup, 23 MarkerClusterGroup,
24 - MarkerClusterGroupOptions 24 + MarkerClusterGroupOptions, Projection
25 } from 'leaflet'; 25 } from 'leaflet';
26 import tinycolor from 'tinycolor2'; 26 import tinycolor from 'tinycolor2';
27 import 'leaflet-providers'; 27 import 'leaflet-providers';
@@ -46,6 +46,7 @@ import { @@ -46,6 +46,7 @@ import {
46 createTooltip, 46 createTooltip,
47 } from '@home/components/widget/lib/maps/maps-utils'; 47 } from '@home/components/widget/lib/maps/maps-utils';
48 import { 48 import {
  49 + checkLngLat,
49 createLoadingDiv, 50 createLoadingDiv,
50 parseArray, 51 parseArray,
51 parseData, 52 parseData,
@@ -79,6 +80,8 @@ export default abstract class LeafletMap { @@ -79,6 +80,8 @@ export default abstract class LeafletMap {
79 updatePending = false; 80 updatePending = false;
80 addMarkers: L.Marker[] = []; 81 addMarkers: L.Marker[] = [];
81 addPolygons: L.Polygon[] = []; 82 addPolygons: L.Polygon[] = [];
  83 + southWest = new L.LatLng(-Projection.SphericalMercator['MAX_LATITUDE'], -180);
  84 + northEast = new L.LatLng(Projection.SphericalMercator['MAX_LATITUDE'], 180);
82 85
83 protected constructor(public ctx: WidgetContext, 86 protected constructor(public ctx: WidgetContext,
84 public $container: HTMLElement, 87 public $container: HTMLElement,
@@ -206,21 +209,30 @@ export default abstract class LeafletMap { @@ -206,21 +209,30 @@ export default abstract class LeafletMap {
206 209
207 addPolygonControl() { 210 addPolygonControl() {
208 if (this.options.showPolygon && this.options.editablePolygon) { 211 if (this.options.showPolygon && this.options.editablePolygon) {
209 - let mousePositionOnMap: L.LatLng[]; 212 + let polygonPoints: L.LatLng[];
210 let addPolygon: L.Control; 213 let addPolygon: L.Control;
  214 + let mousePositionOnMap: LatLng;
211 this.map.on('mousemove', (e: L.LeafletMouseEvent) => { 215 this.map.on('mousemove', (e: L.LeafletMouseEvent) => {
212 - const polygonOffset = this.options.provider === MapProviders.image ? 10 : 0.01;  
213 - const latlng1 = e.latlng;  
214 - const latlng2 = L.latLng(e.latlng.lat, e.latlng.lng + polygonOffset);  
215 - const latlng3 = L.latLng(e.latlng.lat - polygonOffset, e.latlng.lng);  
216 - mousePositionOnMap = [latlng1, latlng2, latlng3]; 216 + mousePositionOnMap = e.latlng;
217 }); 217 });
  218 +
218 const dragListener = (e: L.DragEndEvent) => { 219 const dragListener = (e: L.DragEndEvent) => {
219 - if (e.type === 'dragend' && mousePositionOnMap) {  
220 - const newPolygon = L.polygon(mousePositionOnMap).addTo(this.map); 220 + if (e.type === 'dragend') {
  221 + const polygonOffset = this.options.provider === MapProviders.image ? 10 : 0.01;
  222 +
  223 + let convert = this.convertToCustomFormat(mousePositionOnMap,polygonOffset);
  224 + mousePositionOnMap.lat = convert[this.options.latKeyName];
  225 + mousePositionOnMap.lng = convert[this.options.lngKeyName];
  226 +
  227 + const latlng1 = mousePositionOnMap;
  228 + const latlng2 = L.latLng(mousePositionOnMap.lat, mousePositionOnMap.lng + polygonOffset);
  229 + const latlng3 = L.latLng(mousePositionOnMap.lat - polygonOffset, mousePositionOnMap.lng);
  230 + polygonPoints = [latlng1, latlng2, latlng3];
  231 +
  232 + const newPolygon = L.polygon(polygonPoints).addTo(this.map);
221 this.addPolygons.push(newPolygon); 233 this.addPolygons.push(newPolygon);
222 const datasourcesList = document.createElement('div'); 234 const datasourcesList = document.createElement('div');
223 - const customLatLng = {[this.options.polygonKeyName]: this.convertToPolygonFormat(mousePositionOnMap)}; 235 + const customLatLng = {[this.options.polygonKeyName]: this.convertToPolygonFormat(polygonPoints)};
224 const header = document.createElement('p'); 236 const header = document.createElement('p');
225 header.appendChild(document.createTextNode('Select entity:')); 237 header.appendChild(document.createTextNode('Select entity:'));
226 header.setAttribute('style', 'font-size: 14px; margin: 8px 0'); 238 header.setAttribute('style', 'font-size: 14px; margin: 8px 0');
@@ -414,12 +426,9 @@ export default abstract class LeafletMap { @@ -414,12 +426,9 @@ export default abstract class LeafletMap {
414 }).filter(el => !!el); 426 }).filter(el => !!el);
415 } 427 }
416 428
417 - convertToCustomFormat(position: L.LatLng): object {  
418 - if (position.lng > 180) {  
419 - position.lng = 180;  
420 - } else if (position.lng < -180) {  
421 - position.lng = -180;  
422 - } 429 + convertToCustomFormat(position: L.LatLng, offset = 0): object {
  430 + position = checkLngLat(position, this.southWest, this.northEast, offset);
  431 +
423 return { 432 return {
424 [this.options.latKeyName]: position.lat, 433 [this.options.latKeyName]: position.lat,
425 [this.options.lngKeyName]: position.lng 434 [this.options.lngKeyName]: position.lng
@@ -728,6 +737,11 @@ export default abstract class LeafletMap { @@ -728,6 +737,11 @@ export default abstract class LeafletMap {
728 if (e === undefined || (e.type !== 'editable:vertex:dragend' && e.type !== 'editable:vertex:deleted')) { 737 if (e === undefined || (e.type !== 'editable:vertex:dragend' && e.type !== 'editable:vertex:deleted')) {
729 return; 738 return;
730 } 739 }
  740 + if(this.options.provider !== MapProviders.image) {
  741 + for (let key in e.layer._latlngs[0]) {
  742 + e.layer._latlngs[0][key] = checkLngLat(e.layer._latlngs[0][key], this.southWest, this.northEast);
  743 + }
  744 + }
731 this.savePolygonLocation({ ...data, ...this.convertPolygonToCustomFormat(e.layer._latlngs) }).subscribe(); 745 this.savePolygonLocation({ ...data, ...this.convertPolygonToCustomFormat(e.layer._latlngs) }).subscribe();
732 } 746 }
733 747
@@ -19,7 +19,12 @@ import LeafletMap from '../leaflet-map'; @@ -19,7 +19,12 @@ import LeafletMap from '../leaflet-map';
19 import { MapImage, PosFuncton, UnitedMapSettings } from '../map-models'; 19 import { MapImage, PosFuncton, UnitedMapSettings } from '../map-models';
20 import { Observable, ReplaySubject } from 'rxjs'; 20 import { Observable, ReplaySubject } from 'rxjs';
21 import { filter, map, mergeMap } from 'rxjs/operators'; 21 import { filter, map, mergeMap } from 'rxjs/operators';
22 -import { aspectCache, calculateNewPointCoordinate, parseFunction } from '@home/components/widget/lib/maps/common-maps-utils'; 22 +import {
  23 + aspectCache,
  24 + calculateNewPointCoordinate,
  25 + checkLngLat,
  26 + parseFunction
  27 +} from '@home/components/widget/lib/maps/common-maps-utils';
23 import { WidgetContext } from '@home/models/widget-component.models'; 28 import { WidgetContext } from '@home/models/widget-component.models';
24 import { DataSet, DatasourceType, widgetType } from '@shared/models/widget.models'; 29 import { DataSet, DatasourceType, widgetType } from '@shared/models/widget.models';
25 import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; 30 import { DataKeyType } from '@shared/models/telemetry/telemetry.models';
@@ -132,9 +137,9 @@ export class ImageMap extends LeafletMap { @@ -132,9 +137,9 @@ export class ImageMap extends LeafletMap {
132 updateBounds(updateImage?: boolean, lastCenterPos?) { 137 updateBounds(updateImage?: boolean, lastCenterPos?) {
133 const w = this.width; 138 const w = this.width;
134 const h = this.height; 139 const h = this.height;
135 - let southWest = this.pointToLatLng(0, h);  
136 - let northEast = this.pointToLatLng(w, 0);  
137 - const bounds = new L.LatLngBounds(southWest, northEast); 140 + this.southWest = this.pointToLatLng(0, h);
  141 + this.northEast = this.pointToLatLng(w, 0);
  142 + const bounds = new L.LatLngBounds(this.southWest, this.northEast);
138 143
139 if (updateImage && this.imageOverlay) { 144 if (updateImage && this.imageOverlay) {
140 this.imageOverlay.remove(); 145 this.imageOverlay.remove();
@@ -147,8 +152,8 @@ export class ImageMap extends LeafletMap { @@ -147,8 +152,8 @@ export class ImageMap extends LeafletMap {
147 this.imageOverlay = L.imageOverlay(this.imageUrl, bounds).addTo(this.map); 152 this.imageOverlay = L.imageOverlay(this.imageUrl, bounds).addTo(this.map);
148 } 153 }
149 const padding = 200 * maxZoom; 154 const padding = 200 * maxZoom;
150 - southWest = this.pointToLatLng(-padding, h + padding);  
151 - northEast = this.pointToLatLng(w + padding, -padding); 155 + const southWest = this.pointToLatLng(-padding, h + padding);
  156 + const northEast = this.pointToLatLng(w + padding, -padding);
152 const maxBounds = new L.LatLngBounds(southWest, northEast); 157 const maxBounds = new L.LatLngBounds(southWest, northEast);
153 this.map.setMaxBounds(maxBounds); 158 this.map.setMaxBounds(maxBounds);
154 if (lastCenterPos) { 159 if (lastCenterPos) {
@@ -187,7 +192,7 @@ export class ImageMap extends LeafletMap { @@ -187,7 +192,7 @@ export class ImageMap extends LeafletMap {
187 this.updateMarkers(this.markersData); 192 this.updateMarkers(this.markersData);
188 if (this.options.draggableMarker && this.addMarkers.length) { 193 if (this.options.draggableMarker && this.addMarkers.length) {
189 this.addMarkers.forEach((marker) => { 194 this.addMarkers.forEach((marker) => {
190 - const prevPoint = this.convertToCustomFormat(marker.getLatLng(), prevWidth, prevHeight); 195 + const prevPoint = this.convertToCustomFormat(marker.getLatLng(), null, prevWidth, prevHeight);
191 marker.setLatLng(this.convertPosition(prevPoint)); 196 marker.setLatLng(this.convertPosition(prevPoint));
192 }); 197 });
193 } 198 }
@@ -257,11 +262,10 @@ export class ImageMap extends LeafletMap { @@ -257,11 +262,10 @@ export class ImageMap extends LeafletMap {
257 return L.CRS.Simple.latLngToPoint(latLng, maxZoom - 1); 262 return L.CRS.Simple.latLngToPoint(latLng, maxZoom - 1);
258 } 263 }
259 264
260 - convertToCustomFormat(position: L.LatLng, width = this.width, height = this.height): object { 265 + convertToCustomFormat(position: L.LatLng, offset = 0, width = this.width, height = this.height): object {
261 const point = this.latLngToPoint(position); 266 const point = this.latLngToPoint(position);
262 const customX = calculateNewPointCoordinate(point.x, width); 267 const customX = calculateNewPointCoordinate(point.x, width);
263 const customY = calculateNewPointCoordinate(point.y, height); 268 const customY = calculateNewPointCoordinate(point.y, height);
264 -  
265 if (customX === 0) { 269 if (customX === 0) {
266 point.x = 0; 270 point.x = 0;
267 } else if (customX === 1) { 271 } else if (customX === 1) {
@@ -273,7 +277,8 @@ export class ImageMap extends LeafletMap { @@ -273,7 +277,8 @@ export class ImageMap extends LeafletMap {
273 } else if (customY === 1) { 277 } else if (customY === 1) {
274 point.y = height; 278 point.y = height;
275 } 279 }
276 - const customLatLng = this.pointToLatLng(point.x, point.y); 280 +
  281 + const customLatLng = checkLngLat(this.pointToLatLng(point.x, point.y), this.southWest, this.northEast, offset);
277 282
278 return { 283 return {
279 [this.options.xPosKeyName]: customX, 284 [this.options.xPosKeyName]: customX,