Commit 1e1d3a8257a5aa824e3a8cbe15f44b22201ea6b8
1 parent
d547ba40
Fixed update position new marker/polygon on resize in image-map
Showing
2 changed files
with
91 additions
and
56 deletions
@@ -30,6 +30,7 @@ import 'leaflet.markercluster/dist/leaflet.markercluster'; | @@ -30,6 +30,7 @@ import 'leaflet.markercluster/dist/leaflet.markercluster'; | ||
30 | import { | 30 | import { |
31 | defaultSettings, | 31 | defaultSettings, |
32 | FormattedData, | 32 | FormattedData, |
33 | + MapProviders, | ||
33 | MapSettings, | 34 | MapSettings, |
34 | MarkerSettings, | 35 | MarkerSettings, |
35 | PolygonSettings, | 36 | PolygonSettings, |
@@ -74,6 +75,8 @@ export default abstract class LeafletMap { | @@ -74,6 +75,8 @@ export default abstract class LeafletMap { | ||
74 | drawRoutes: boolean; | 75 | drawRoutes: boolean; |
75 | showPolygon: boolean; | 76 | showPolygon: boolean; |
76 | updatePending = false; | 77 | updatePending = false; |
78 | + addMarkers: L.Marker[] = []; | ||
79 | + addPolygons: L.Polygon[] = []; | ||
77 | 80 | ||
78 | protected constructor(public ctx: WidgetContext, | 81 | protected constructor(public ctx: WidgetContext, |
79 | public $container: HTMLElement, | 82 | public $container: HTMLElement, |
@@ -133,6 +136,7 @@ export default abstract class LeafletMap { | @@ -133,6 +136,7 @@ export default abstract class LeafletMap { | ||
133 | shadowSize: [41, 41] | 136 | shadowSize: [41, 41] |
134 | }); | 137 | }); |
135 | const newMarker = L.marker(mousePositionOnMap, { icon }).addTo(this.map); | 138 | const newMarker = L.marker(mousePositionOnMap, { icon }).addTo(this.map); |
139 | + this.addMarkers.push(newMarker); | ||
136 | const datasourcesList = document.createElement('div'); | 140 | const datasourcesList = document.createElement('div'); |
137 | const customLatLng = this.convertToCustomFormat(mousePositionOnMap); | 141 | const customLatLng = this.convertToCustomFormat(mousePositionOnMap); |
138 | const header = document.createElement('p'); | 142 | const header = document.createElement('p'); |
@@ -147,6 +151,10 @@ export default abstract class LeafletMap { | @@ -147,6 +151,10 @@ export default abstract class LeafletMap { | ||
147 | const updatedEnttity = { ...ds, ...customLatLng }; | 151 | const updatedEnttity = { ...ds, ...customLatLng }; |
148 | this.saveMarkerLocation(updatedEnttity).subscribe(() => { | 152 | this.saveMarkerLocation(updatedEnttity).subscribe(() => { |
149 | this.map.removeLayer(newMarker); | 153 | this.map.removeLayer(newMarker); |
154 | + const markerIndex = this.addMarkers.indexOf(newMarker); | ||
155 | + if (markerIndex > -1) { | ||
156 | + this.addMarkers.splice(markerIndex, 1); | ||
157 | + } | ||
150 | this.deleteMarker(ds.entityName); | 158 | this.deleteMarker(ds.entityName); |
151 | this.createMarker(ds.entityName, updatedEnttity, this.datasources, this.options); | 159 | this.createMarker(ds.entityName, updatedEnttity, this.datasources, this.options); |
152 | }); | 160 | }); |
@@ -158,6 +166,10 @@ export default abstract class LeafletMap { | @@ -158,6 +166,10 @@ export default abstract class LeafletMap { | ||
158 | deleteBtn.appendChild(document.createTextNode('Discard changes')); | 166 | deleteBtn.appendChild(document.createTextNode('Discard changes')); |
159 | deleteBtn.onclick = () => { | 167 | deleteBtn.onclick = () => { |
160 | this.map.removeLayer(newMarker); | 168 | this.map.removeLayer(newMarker); |
169 | + const markerIndex = this.addMarkers.indexOf(newMarker); | ||
170 | + if (markerIndex > -1) { | ||
171 | + this.addMarkers.splice(markerIndex, 1); | ||
172 | + } | ||
161 | }; | 173 | }; |
162 | datasourcesList.append(deleteBtn); | 174 | datasourcesList.append(deleteBtn); |
163 | const popup = L.popup(); | 175 | const popup = L.popup(); |
@@ -196,14 +208,16 @@ export default abstract class LeafletMap { | @@ -196,14 +208,16 @@ export default abstract class LeafletMap { | ||
196 | let mousePositionOnMap: L.LatLng[]; | 208 | let mousePositionOnMap: L.LatLng[]; |
197 | let addPolygon: L.Control; | 209 | let addPolygon: L.Control; |
198 | this.map.on('mousemove', (e: L.LeafletMouseEvent) => { | 210 | this.map.on('mousemove', (e: L.LeafletMouseEvent) => { |
211 | + const polygonOffset = this.options.provider === MapProviders.image ? 10 : 0.01; | ||
199 | const latlng1 = e.latlng; | 212 | const latlng1 = e.latlng; |
200 | - const latlng2 = L.latLng(e.latlng.lat, e.latlng.lng + 10); | ||
201 | - const latlng3 = L.latLng(e.latlng.lat - 10, e.latlng.lng); | 213 | + const latlng2 = L.latLng(e.latlng.lat, e.latlng.lng + polygonOffset); |
214 | + const latlng3 = L.latLng(e.latlng.lat - polygonOffset, e.latlng.lng); | ||
202 | mousePositionOnMap = [latlng1, latlng2, latlng3]; | 215 | mousePositionOnMap = [latlng1, latlng2, latlng3]; |
203 | }); | 216 | }); |
204 | const dragListener = (e: L.DragEndEvent) => { | 217 | const dragListener = (e: L.DragEndEvent) => { |
205 | if (e.type === 'dragend' && mousePositionOnMap) { | 218 | if (e.type === 'dragend' && mousePositionOnMap) { |
206 | const newPolygon = L.polygon(mousePositionOnMap).addTo(this.map); | 219 | const newPolygon = L.polygon(mousePositionOnMap).addTo(this.map); |
220 | + this.addPolygons.push(newPolygon); | ||
207 | const datasourcesList = document.createElement('div'); | 221 | const datasourcesList = document.createElement('div'); |
208 | const customLatLng = {[this.options.polygonKeyName]: this.convertToPolygonFormat(mousePositionOnMap)}; | 222 | const customLatLng = {[this.options.polygonKeyName]: this.convertToPolygonFormat(mousePositionOnMap)}; |
209 | const header = document.createElement('p'); | 223 | const header = document.createElement('p'); |
@@ -218,6 +232,10 @@ export default abstract class LeafletMap { | @@ -218,6 +232,10 @@ export default abstract class LeafletMap { | ||
218 | const updatedEnttity = { ...ds, ...customLatLng }; | 232 | const updatedEnttity = { ...ds, ...customLatLng }; |
219 | this.savePolygonLocation(updatedEnttity).subscribe(() => { | 233 | this.savePolygonLocation(updatedEnttity).subscribe(() => { |
220 | this.map.removeLayer(newPolygon); | 234 | this.map.removeLayer(newPolygon); |
235 | + const polygonIndex = this.addPolygons.indexOf(newPolygon); | ||
236 | + if (polygonIndex > -1) { | ||
237 | + this.addPolygons.splice(polygonIndex, 1); | ||
238 | + } | ||
221 | this.deletePolygon(ds.entityName); | 239 | this.deletePolygon(ds.entityName); |
222 | }); | 240 | }); |
223 | }; | 241 | }; |
@@ -228,6 +246,10 @@ export default abstract class LeafletMap { | @@ -228,6 +246,10 @@ export default abstract class LeafletMap { | ||
228 | deleteBtn.appendChild(document.createTextNode('Discard changes')); | 246 | deleteBtn.appendChild(document.createTextNode('Discard changes')); |
229 | deleteBtn.onclick = () => { | 247 | deleteBtn.onclick = () => { |
230 | this.map.removeLayer(newPolygon); | 248 | this.map.removeLayer(newPolygon); |
249 | + const polygonIndex = this.addPolygons.indexOf(newPolygon); | ||
250 | + if (polygonIndex > -1) { | ||
251 | + this.addPolygons.splice(polygonIndex, 1); | ||
252 | + } | ||
231 | }; | 253 | }; |
232 | datasourcesList.append(deleteBtn); | 254 | datasourcesList.append(deleteBtn); |
233 | const popup = L.popup(); | 255 | const popup = L.popup(); |
@@ -26,7 +26,7 @@ import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; | @@ -26,7 +26,7 @@ import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; | ||
26 | import { WidgetSubscriptionOptions } from '@core/api/widget-api.models'; | 26 | import { WidgetSubscriptionOptions } from '@core/api/widget-api.models'; |
27 | import { isDefinedAndNotNull, isEmptyStr } from '@core/utils'; | 27 | import { isDefinedAndNotNull, isEmptyStr } from '@core/utils'; |
28 | 28 | ||
29 | -const maxZoom = 4;// ? | 29 | +const maxZoom = 4; // ? |
30 | 30 | ||
31 | export class ImageMap extends LeafletMap { | 31 | export class ImageMap extends LeafletMap { |
32 | 32 | ||
@@ -162,52 +162,64 @@ export class ImageMap extends LeafletMap { | @@ -162,52 +162,64 @@ export class ImageMap extends LeafletMap { | ||
162 | } | 162 | } |
163 | 163 | ||
164 | onResize(updateImage?: boolean) { | 164 | onResize(updateImage?: boolean) { |
165 | - let width = this.$container.clientWidth; | ||
166 | - if (width > 0 && this.aspect) { | ||
167 | - let height = width / this.aspect; | ||
168 | - const imageMapHeight = this.$container.clientHeight; | ||
169 | - if (imageMapHeight > 0 && height > imageMapHeight) { | ||
170 | - height = imageMapHeight; | ||
171 | - width = height * this.aspect; | 165 | + let width = this.$container.clientWidth; |
166 | + if (width > 0 && this.aspect) { | ||
167 | + let height = width / this.aspect; | ||
168 | + const imageMapHeight = this.$container.clientHeight; | ||
169 | + if (imageMapHeight > 0 && height > imageMapHeight) { | ||
170 | + height = imageMapHeight; | ||
171 | + width = height * this.aspect; | ||
172 | + } | ||
173 | + width *= maxZoom; | ||
174 | + const prevWidth = this.width; | ||
175 | + const prevHeight = this.height; | ||
176 | + if (this.width !== width || updateImage) { | ||
177 | + this.width = width; | ||
178 | + this.height = width / this.aspect; | ||
179 | + if (!this.map) { | ||
180 | + this.initMap(updateImage); | ||
181 | + } else { | ||
182 | + const lastCenterPos = this.latLngToPoint(this.map.getCenter()); | ||
183 | + lastCenterPos.x /= prevWidth; | ||
184 | + lastCenterPos.y /= prevHeight; | ||
185 | + this.updateBounds(updateImage, lastCenterPos); | ||
186 | + this.map.invalidateSize(true); | ||
187 | + this.updateMarkers(this.markersData); | ||
188 | + if (this.options.draggableMarker && this.addMarkers.length) { | ||
189 | + this.addMarkers.forEach((marker) => { | ||
190 | + const prevPoint = this.convertToCustomFormat(marker.getLatLng(), prevWidth, prevHeight); | ||
191 | + marker.setLatLng(this.convertPosition(prevPoint)); | ||
192 | + }); | ||
172 | } | 193 | } |
173 | - width *= maxZoom; | ||
174 | - const prevWidth = this.width; | ||
175 | - const prevHeight = this.height; | ||
176 | - if (this.width !== width || updateImage) { | ||
177 | - this.width = width; | ||
178 | - this.height = width / this.aspect; | ||
179 | - if (!this.map) { | ||
180 | - this.initMap(updateImage); | ||
181 | - } else { | ||
182 | - const lastCenterPos = this.latLngToPoint(this.map.getCenter()); | ||
183 | - lastCenterPos.x /= prevWidth; | ||
184 | - lastCenterPos.y /= prevHeight; | ||
185 | - this.updateBounds(updateImage, lastCenterPos); | ||
186 | - this.map.invalidateSize(true); | ||
187 | - this.updateMarkers(this.markersData); | ||
188 | - this.updatePolygons(this.polygonsData); | ||
189 | - } | 194 | + this.updatePolygons(this.polygonsData); |
195 | + if (this.options.showPolygon && this.options.editablePolygon && this.addPolygons.length) { | ||
196 | + this.addPolygons.forEach((polygon) => { | ||
197 | + const prevPolygonPoint = this.convertToPolygonFormat(polygon.getLatLngs(), prevWidth, prevHeight); | ||
198 | + polygon.setLatLngs(this.convertPositionPolygon(prevPolygonPoint)); | ||
199 | + }); | ||
190 | } | 200 | } |
201 | + } | ||
191 | } | 202 | } |
203 | + } | ||
192 | } | 204 | } |
193 | 205 | ||
194 | fitBounds(bounds: LatLngBounds, padding?: LatLngTuple) { } | 206 | fitBounds(bounds: LatLngBounds, padding?: LatLngTuple) { } |
195 | 207 | ||
196 | initMap(updateImage?: boolean) { | 208 | initMap(updateImage?: boolean) { |
197 | - if (!this.map && this.aspect > 0) { | ||
198 | - const center = this.pointToLatLng(this.width / 2, this.height / 2); | ||
199 | - this.map = L.map(this.$container, { | ||
200 | - minZoom: 1, | ||
201 | - maxZoom, | ||
202 | - scrollWheelZoom: !this.options.disableScrollZooming, | ||
203 | - center, | ||
204 | - zoom: 1, | ||
205 | - crs: L.CRS.Simple, | ||
206 | - attributionControl: false, | ||
207 | - editable: !!this.options.editablePolygon | ||
208 | - }); | ||
209 | - this.updateBounds(updateImage); | ||
210 | - } | 209 | + if (!this.map && this.aspect > 0) { |
210 | + const center = this.pointToLatLng(this.width / 2, this.height / 2); | ||
211 | + this.map = L.map(this.$container, { | ||
212 | + minZoom: 1, | ||
213 | + maxZoom, | ||
214 | + scrollWheelZoom: !this.options.disableScrollZooming, | ||
215 | + center, | ||
216 | + zoom: 1, | ||
217 | + crs: L.CRS.Simple, | ||
218 | + attributionControl: false, | ||
219 | + editable: !!this.options.editablePolygon | ||
220 | + }); | ||
221 | + this.updateBounds(updateImage); | ||
222 | + } | ||
211 | } | 223 | } |
212 | 224 | ||
213 | convertPosition(expression): L.LatLng { | 225 | convertPosition(expression): L.LatLng { |
@@ -227,13 +239,14 @@ export class ImageMap extends LeafletMap { | @@ -227,13 +239,14 @@ export class ImageMap extends LeafletMap { | ||
227 | if (!Array.isArray(el[0]) && !Array.isArray(el[1]) && el.length === 2) { | 239 | if (!Array.isArray(el[0]) && !Array.isArray(el[1]) && el.length === 2) { |
228 | return this.pointToLatLng( | 240 | return this.pointToLatLng( |
229 | el[0] * this.width, | 241 | el[0] * this.width, |
230 | - el[1] * this.height) | 242 | + el[1] * this.height |
243 | + ); | ||
231 | } else if (Array.isArray(el) && el.length) { | 244 | } else if (Array.isArray(el) && el.length) { |
232 | return this.convertPositionPolygon(el as LatLngTuple[] | LatLngTuple[][]); | 245 | return this.convertPositionPolygon(el as LatLngTuple[] | LatLngTuple[][]); |
233 | } else { | 246 | } else { |
234 | return null; | 247 | return null; |
235 | } | 248 | } |
236 | - }).filter(el => !!el) | 249 | + }).filter(el => !!el); |
237 | } | 250 | } |
238 | 251 | ||
239 | pointToLatLng(x, y): L.LatLng { | 252 | pointToLatLng(x, y): L.LatLng { |
@@ -244,32 +257,32 @@ export class ImageMap extends LeafletMap { | @@ -244,32 +257,32 @@ export class ImageMap extends LeafletMap { | ||
244 | return L.CRS.Simple.latLngToPoint(latLng, maxZoom - 1); | 257 | return L.CRS.Simple.latLngToPoint(latLng, maxZoom - 1); |
245 | } | 258 | } |
246 | 259 | ||
247 | - convertToCustomFormat(position: L.LatLng): object { | ||
248 | - const point = this.latLngToPoint(position); | ||
249 | - return { | ||
250 | - [this.options.xPosKeyName]: calculateNewPointCoordinate(point.x, this.width), | ||
251 | - [this.options.yPosKeyName]: calculateNewPointCoordinate(point.y, this.height) | ||
252 | - } | 260 | + convertToCustomFormat(position: L.LatLng, width = this.width, height = this.height): object { |
261 | + const point = this.latLngToPoint(position); | ||
262 | + return { | ||
263 | + [this.options.xPosKeyName]: calculateNewPointCoordinate(point.x, width), | ||
264 | + [this.options.yPosKeyName]: calculateNewPointCoordinate(point.y, height) | ||
265 | + }; | ||
253 | } | 266 | } |
254 | 267 | ||
255 | - convertToPolygonFormat(points: Array<any>): Array<any> { | 268 | + convertToPolygonFormat(points: Array<any>, width = this.width, height = this.height): Array<any> { |
256 | if (points.length) { | 269 | if (points.length) { |
257 | - return points.map(point=> { | 270 | + return points.map(point => { |
258 | if (point.length) { | 271 | if (point.length) { |
259 | - return this.convertToPolygonFormat(point); | 272 | + return this.convertToPolygonFormat(point, width, height); |
260 | } else { | 273 | } else { |
261 | const pos = this.latLngToPoint(point); | 274 | const pos = this.latLngToPoint(point); |
262 | - return [calculateNewPointCoordinate(pos.x, this.width), calculateNewPointCoordinate(pos.y, this.height)]; | 275 | + return [calculateNewPointCoordinate(pos.x, width), calculateNewPointCoordinate(pos.y, height)]; |
263 | } | 276 | } |
264 | - }) | 277 | + }); |
265 | } else { | 278 | } else { |
266 | - return [] | 279 | + return []; |
267 | } | 280 | } |
268 | } | 281 | } |
269 | 282 | ||
270 | convertPolygonToCustomFormat(expression: any[][]): object { | 283 | convertPolygonToCustomFormat(expression: any[][]): object { |
271 | return { | 284 | return { |
272 | [this.options.polygonKeyName] : this.convertToPolygonFormat(expression) | 285 | [this.options.polygonKeyName] : this.convertToPolygonFormat(expression) |
273 | - } | 286 | + }; |
274 | } | 287 | } |
275 | } | 288 | } |