Fixed update position new marker/polygon on resize in image-map

This commit is contained in:
Vladyslav_Prykhodko 2020-08-18 13:45:29 +03:00
parent d547ba407a
commit 1e1d3a8257
2 changed files with 93 additions and 58 deletions

View File

@ -30,6 +30,7 @@ import 'leaflet.markercluster/dist/leaflet.markercluster';
import { import {
defaultSettings, defaultSettings,
FormattedData, FormattedData,
MapProviders,
MapSettings, MapSettings,
MarkerSettings, MarkerSettings,
PolygonSettings, PolygonSettings,
@ -74,6 +75,8 @@ export default abstract class LeafletMap {
drawRoutes: boolean; drawRoutes: boolean;
showPolygon: boolean; showPolygon: boolean;
updatePending = false; updatePending = false;
addMarkers: L.Marker[] = [];
addPolygons: L.Polygon[] = [];
protected constructor(public ctx: WidgetContext, protected constructor(public ctx: WidgetContext,
public $container: HTMLElement, public $container: HTMLElement,
@ -133,6 +136,7 @@ export default abstract class LeafletMap {
shadowSize: [41, 41] shadowSize: [41, 41]
}); });
const newMarker = L.marker(mousePositionOnMap, { icon }).addTo(this.map); const newMarker = L.marker(mousePositionOnMap, { icon }).addTo(this.map);
this.addMarkers.push(newMarker);
const datasourcesList = document.createElement('div'); const datasourcesList = document.createElement('div');
const customLatLng = this.convertToCustomFormat(mousePositionOnMap); const customLatLng = this.convertToCustomFormat(mousePositionOnMap);
const header = document.createElement('p'); const header = document.createElement('p');
@ -147,6 +151,10 @@ export default abstract class LeafletMap {
const updatedEnttity = { ...ds, ...customLatLng }; const updatedEnttity = { ...ds, ...customLatLng };
this.saveMarkerLocation(updatedEnttity).subscribe(() => { this.saveMarkerLocation(updatedEnttity).subscribe(() => {
this.map.removeLayer(newMarker); this.map.removeLayer(newMarker);
const markerIndex = this.addMarkers.indexOf(newMarker);
if (markerIndex > -1) {
this.addMarkers.splice(markerIndex, 1);
}
this.deleteMarker(ds.entityName); this.deleteMarker(ds.entityName);
this.createMarker(ds.entityName, updatedEnttity, this.datasources, this.options); this.createMarker(ds.entityName, updatedEnttity, this.datasources, this.options);
}); });
@ -158,6 +166,10 @@ export default abstract class LeafletMap {
deleteBtn.appendChild(document.createTextNode('Discard changes')); deleteBtn.appendChild(document.createTextNode('Discard changes'));
deleteBtn.onclick = () => { deleteBtn.onclick = () => {
this.map.removeLayer(newMarker); this.map.removeLayer(newMarker);
const markerIndex = this.addMarkers.indexOf(newMarker);
if (markerIndex > -1) {
this.addMarkers.splice(markerIndex, 1);
}
}; };
datasourcesList.append(deleteBtn); datasourcesList.append(deleteBtn);
const popup = L.popup(); const popup = L.popup();
@ -196,14 +208,16 @@ export default abstract class LeafletMap {
let mousePositionOnMap: L.LatLng[]; let mousePositionOnMap: L.LatLng[];
let addPolygon: L.Control; let addPolygon: L.Control;
this.map.on('mousemove', (e: L.LeafletMouseEvent) => { this.map.on('mousemove', (e: L.LeafletMouseEvent) => {
const polygonOffset = this.options.provider === MapProviders.image ? 10 : 0.01;
const latlng1 = e.latlng; const latlng1 = e.latlng;
const latlng2 = L.latLng(e.latlng.lat, e.latlng.lng + 10); const latlng2 = L.latLng(e.latlng.lat, e.latlng.lng + polygonOffset);
const latlng3 = L.latLng(e.latlng.lat - 10, e.latlng.lng); const latlng3 = L.latLng(e.latlng.lat - polygonOffset, e.latlng.lng);
mousePositionOnMap = [latlng1, latlng2, latlng3]; mousePositionOnMap = [latlng1, latlng2, latlng3];
}); });
const dragListener = (e: L.DragEndEvent) => { const dragListener = (e: L.DragEndEvent) => {
if (e.type === 'dragend' && mousePositionOnMap) { if (e.type === 'dragend' && mousePositionOnMap) {
const newPolygon = L.polygon(mousePositionOnMap).addTo(this.map); const newPolygon = L.polygon(mousePositionOnMap).addTo(this.map);
this.addPolygons.push(newPolygon);
const datasourcesList = document.createElement('div'); const datasourcesList = document.createElement('div');
const customLatLng = {[this.options.polygonKeyName]: this.convertToPolygonFormat(mousePositionOnMap)}; const customLatLng = {[this.options.polygonKeyName]: this.convertToPolygonFormat(mousePositionOnMap)};
const header = document.createElement('p'); const header = document.createElement('p');
@ -218,6 +232,10 @@ export default abstract class LeafletMap {
const updatedEnttity = { ...ds, ...customLatLng }; const updatedEnttity = { ...ds, ...customLatLng };
this.savePolygonLocation(updatedEnttity).subscribe(() => { this.savePolygonLocation(updatedEnttity).subscribe(() => {
this.map.removeLayer(newPolygon); this.map.removeLayer(newPolygon);
const polygonIndex = this.addPolygons.indexOf(newPolygon);
if (polygonIndex > -1) {
this.addPolygons.splice(polygonIndex, 1);
}
this.deletePolygon(ds.entityName); this.deletePolygon(ds.entityName);
}); });
}; };
@ -228,6 +246,10 @@ export default abstract class LeafletMap {
deleteBtn.appendChild(document.createTextNode('Discard changes')); deleteBtn.appendChild(document.createTextNode('Discard changes'));
deleteBtn.onclick = () => { deleteBtn.onclick = () => {
this.map.removeLayer(newPolygon); this.map.removeLayer(newPolygon);
const polygonIndex = this.addPolygons.indexOf(newPolygon);
if (polygonIndex > -1) {
this.addPolygons.splice(polygonIndex, 1);
}
}; };
datasourcesList.append(deleteBtn); datasourcesList.append(deleteBtn);
const popup = L.popup(); const popup = L.popup();

View File

@ -26,7 +26,7 @@ import { DataKeyType } from '@shared/models/telemetry/telemetry.models';
import { WidgetSubscriptionOptions } from '@core/api/widget-api.models'; import { WidgetSubscriptionOptions } from '@core/api/widget-api.models';
import { isDefinedAndNotNull, isEmptyStr } from '@core/utils'; import { isDefinedAndNotNull, isEmptyStr } from '@core/utils';
const maxZoom = 4;// ? const maxZoom = 4; // ?
export class ImageMap extends LeafletMap { export class ImageMap extends LeafletMap {
@ -162,52 +162,64 @@ export class ImageMap extends LeafletMap {
} }
onResize(updateImage?: boolean) { onResize(updateImage?: boolean) {
let width = this.$container.clientWidth; let width = this.$container.clientWidth;
if (width > 0 && this.aspect) { if (width > 0 && this.aspect) {
let height = width / this.aspect; let height = width / this.aspect;
const imageMapHeight = this.$container.clientHeight; const imageMapHeight = this.$container.clientHeight;
if (imageMapHeight > 0 && height > imageMapHeight) { if (imageMapHeight > 0 && height > imageMapHeight) {
height = imageMapHeight; height = imageMapHeight;
width = height * this.aspect; width = height * this.aspect;
}
width *= maxZoom;
const prevWidth = this.width;
const prevHeight = this.height;
if (this.width !== width || updateImage) {
this.width = width;
this.height = width / this.aspect;
if (!this.map) {
this.initMap(updateImage);
} else {
const lastCenterPos = this.latLngToPoint(this.map.getCenter());
lastCenterPos.x /= prevWidth;
lastCenterPos.y /= prevHeight;
this.updateBounds(updateImage, lastCenterPos);
this.map.invalidateSize(true);
this.updateMarkers(this.markersData);
this.updatePolygons(this.polygonsData);
}
}
} }
width *= maxZoom;
const prevWidth = this.width;
const prevHeight = this.height;
if (this.width !== width || updateImage) {
this.width = width;
this.height = width / this.aspect;
if (!this.map) {
this.initMap(updateImage);
} else {
const lastCenterPos = this.latLngToPoint(this.map.getCenter());
lastCenterPos.x /= prevWidth;
lastCenterPos.y /= prevHeight;
this.updateBounds(updateImage, lastCenterPos);
this.map.invalidateSize(true);
this.updateMarkers(this.markersData);
if (this.options.draggableMarker && this.addMarkers.length) {
this.addMarkers.forEach((marker) => {
const prevPoint = this.convertToCustomFormat(marker.getLatLng(), prevWidth, prevHeight);
marker.setLatLng(this.convertPosition(prevPoint));
});
}
this.updatePolygons(this.polygonsData);
if (this.options.showPolygon && this.options.editablePolygon && this.addPolygons.length) {
this.addPolygons.forEach((polygon) => {
const prevPolygonPoint = this.convertToPolygonFormat(polygon.getLatLngs(), prevWidth, prevHeight);
polygon.setLatLngs(this.convertPositionPolygon(prevPolygonPoint));
});
}
}
}
}
} }
fitBounds(bounds: LatLngBounds, padding?: LatLngTuple) { } fitBounds(bounds: LatLngBounds, padding?: LatLngTuple) { }
initMap(updateImage?: boolean) { initMap(updateImage?: boolean) {
if (!this.map && this.aspect > 0) { if (!this.map && this.aspect > 0) {
const center = this.pointToLatLng(this.width / 2, this.height / 2); const center = this.pointToLatLng(this.width / 2, this.height / 2);
this.map = L.map(this.$container, { this.map = L.map(this.$container, {
minZoom: 1, minZoom: 1,
maxZoom, maxZoom,
scrollWheelZoom: !this.options.disableScrollZooming, scrollWheelZoom: !this.options.disableScrollZooming,
center, center,
zoom: 1, zoom: 1,
crs: L.CRS.Simple, crs: L.CRS.Simple,
attributionControl: false, attributionControl: false,
editable: !!this.options.editablePolygon editable: !!this.options.editablePolygon
}); });
this.updateBounds(updateImage); this.updateBounds(updateImage);
} }
} }
convertPosition(expression): L.LatLng { convertPosition(expression): L.LatLng {
@ -227,13 +239,14 @@ export class ImageMap extends LeafletMap {
if (!Array.isArray(el[0]) && !Array.isArray(el[1]) && el.length === 2) { if (!Array.isArray(el[0]) && !Array.isArray(el[1]) && el.length === 2) {
return this.pointToLatLng( return this.pointToLatLng(
el[0] * this.width, el[0] * this.width,
el[1] * this.height) el[1] * this.height
);
} else if (Array.isArray(el) && el.length) { } else if (Array.isArray(el) && el.length) {
return this.convertPositionPolygon(el as LatLngTuple[] | LatLngTuple[][]); return this.convertPositionPolygon(el as LatLngTuple[] | LatLngTuple[][]);
} else { } else {
return null; return null;
} }
}).filter(el => !!el) }).filter(el => !!el);
} }
pointToLatLng(x, y): L.LatLng { pointToLatLng(x, y): L.LatLng {
@ -244,32 +257,32 @@ export class ImageMap extends LeafletMap {
return L.CRS.Simple.latLngToPoint(latLng, maxZoom - 1); return L.CRS.Simple.latLngToPoint(latLng, maxZoom - 1);
} }
convertToCustomFormat(position: L.LatLng): object { convertToCustomFormat(position: L.LatLng, width = this.width, height = this.height): object {
const point = this.latLngToPoint(position); const point = this.latLngToPoint(position);
return { return {
[this.options.xPosKeyName]: calculateNewPointCoordinate(point.x, this.width), [this.options.xPosKeyName]: calculateNewPointCoordinate(point.x, width),
[this.options.yPosKeyName]: calculateNewPointCoordinate(point.y, this.height) [this.options.yPosKeyName]: calculateNewPointCoordinate(point.y, height)
} };
} }
convertToPolygonFormat(points: Array<any>): Array<any> { convertToPolygonFormat(points: Array<any>, width = this.width, height = this.height): Array<any> {
if (points.length) { if (points.length) {
return points.map(point=> { return points.map(point => {
if (point.length) { if (point.length) {
return this.convertToPolygonFormat(point); return this.convertToPolygonFormat(point, width, height);
} else { } else {
const pos = this.latLngToPoint(point); const pos = this.latLngToPoint(point);
return [calculateNewPointCoordinate(pos.x, this.width), calculateNewPointCoordinate(pos.y, this.height)]; return [calculateNewPointCoordinate(pos.x, width), calculateNewPointCoordinate(pos.y, height)];
} }
}) });
} else { } else {
return [] return [];
} }
} }
convertPolygonToCustomFormat(expression: any[][]): object { convertPolygonToCustomFormat(expression: any[][]): object {
return { return {
[this.options.polygonKeyName] : this.convertToPolygonFormat(expression) [this.options.polygonKeyName] : this.convertToPolygonFormat(expression)
} };
} }
} }