From c88e6fc89736da8faa46d525c8781c0f1dac5384 Mon Sep 17 00:00:00 2001
From: YANGDL <114714267@qq.com>
Date: 星期五, 19 三月 2021 01:50:18 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'
---
src/components/plugin/Editable.js | 3826 +++++++++++++++++++++++++++++-----------------------------
1 files changed, 1,910 insertions(+), 1,916 deletions(-)
diff --git a/src/components/plugin/Editable.js b/src/components/plugin/Editable.js
index 79fc3ad..3f24a8d 100644
--- a/src/components/plugin/Editable.js
+++ b/src/components/plugin/Editable.js
@@ -1,2016 +1,2010 @@
-'use strict'
-const init = (L) => {
- (function (factory, window) {
- // define an AMD module that relies on 'leaflet'
- if (typeof define === 'function' && window.define.amd) {
- window.define(['leaflet'], factory)
+'use strict';
+(function (factory, window) {
+ // define an AMD module that relies on 'leaflet'
+ if (typeof define === 'function' && define.amd) {
+ define(['leaflet'], factory)
- // define a Common JS module that relies on 'leaflet'
- } else if (typeof exports === 'object') {
- module.exports = factory(require('leaflet'))
- }
+ // define a Common JS module that relies on 'leaflet'
+ } else if (typeof exports === 'object') {
+ module.exports = factory(require('leaflet'))
+ }
- // attach your plugin to the global 'L' variable
- if (typeof window !== 'undefined' && L) {
- factory(L)
- }
- }(function (L) {
- // 馃崅miniclass CancelableEvent (Event objects)
- // 馃崅method cancel()
- // Cancel any subsequent action.
+ // attach your plugin to the global 'L' variable
+ if (typeof window !== 'undefined' && window.L) {
+ factory(window.L)
+ }
+}(function (L) {
+ // 馃崅miniclass CancelableEvent (Event objects)
+ // 馃崅method cancel()
+ // Cancel any subsequent action.
- // 馃崅miniclass VertexEvent (Event objects)
- // 馃崅property vertex: VertexMarker
- // The vertex that fires the event.
+ // 馃崅miniclass VertexEvent (Event objects)
+ // 馃崅property vertex: VertexMarker
+ // The vertex that fires the event.
- // 馃崅miniclass ShapeEvent (Event objects)
- // 馃崅property shape: Array
- // The shape (LatLngs array) subject of the action.
+ // 馃崅miniclass ShapeEvent (Event objects)
+ // 馃崅property shape: Array
+ // The shape (LatLngs array) subject of the action.
- // 馃崅miniclass CancelableVertexEvent (Event objects)
- // 馃崅inherits VertexEvent
- // 馃崅inherits CancelableEvent
+ // 馃崅miniclass CancelableVertexEvent (Event objects)
+ // 馃崅inherits VertexEvent
+ // 馃崅inherits CancelableEvent
- // 馃崅miniclass CancelableShapeEvent (Event objects)
- // 馃崅inherits ShapeEvent
- // 馃崅inherits CancelableEvent
+ // 馃崅miniclass CancelableShapeEvent (Event objects)
+ // 馃崅inherits ShapeEvent
+ // 馃崅inherits CancelableEvent
- // 馃崅miniclass LayerEvent (Event objects)
- // 馃崅property layer: object
- // The Layer (Marker, Polyline鈥�) subject of the action.
+ // 馃崅miniclass LayerEvent (Event objects)
+ // 馃崅property layer: object
+ // The Layer (Marker, Polyline鈥�) subject of the action.
- // 馃崅namespace Editable; 馃崅class Editable; 馃崅aka L.Editable
- // Main edition handler. By default, it is attached to the map
- // as `map.editTools` property.
- // Leaflet.Editable is made to be fully extendable. You have three ways to customize
- // the behaviour: using options, listening to events, or extending.
- L.Editable = L.Evented.extend({
+ // 馃崅namespace Editable; 馃崅class Editable; 馃崅aka L.Editable
+ // Main edition handler. By default, it is attached to the map
+ // as `map.editTools` property.
+ // Leaflet.Editable is made to be fully extendable. You have three ways to customize
+ // the behaviour: using options, listening to events, or extending.
+ L.Editable = L.Evented.extend({
- statics: {
- FORWARD: 1,
- BACKWARD: -1
- },
+ statics: {
+ FORWARD: 1,
+ BACKWARD: -1
+ },
- options: {
+ options: {
- // You can pass them when creating a map using the `editOptions` key.
- // 馃崅option zIndex: int = 1000
- // The default zIndex of the editing tools.
- zIndex: 1000,
+ // You can pass them when creating a map using the `editOptions` key.
+ // 馃崅option zIndex: int = 1000
+ // The default zIndex of the editing tools.
+ zIndex: 1000,
- // 馃崅option polygonClass: class = L.Polygon
- // Class to be used when creating a new Polygon.
- polygonClass: L.Polygon,
+ // 馃崅option polygonClass: class = L.Polygon
+ // Class to be used when creating a new Polygon.
+ polygonClass: L.Polygon,
- // 馃崅option polylineClass: class = L.Polyline
- // Class to be used when creating a new Polyline.
- polylineClass: L.Polyline,
+ // 馃崅option polylineClass: class = L.Polyline
+ // Class to be used when creating a new Polyline.
+ polylineClass: L.Polyline,
- // 馃崅option markerClass: class = L.Marker
- // Class to be used when creating a new Marker.
- markerClass: L.Marker,
+ // 馃崅option markerClass: class = L.Marker
+ // Class to be used when creating a new Marker.
+ markerClass: L.Marker,
- // 馃崅option rectangleClass: class = L.Rectangle
- // Class to be used when creating a new Rectangle.
- rectangleClass: L.Rectangle,
+ // 馃崅option rectangleClass: class = L.Rectangle
+ // Class to be used when creating a new Rectangle.
+ rectangleClass: L.Rectangle,
- // 馃崅option circleClass: class = L.Circle
- // Class to be used when creating a new Circle.
- circleClass: L.Circle,
+ // 馃崅option circleClass: class = L.Circle
+ // Class to be used when creating a new Circle.
+ circleClass: L.Circle,
- // 馃崅option drawingCSSClass: string = 'leaflet-editable-drawing'
- // CSS class to be added to the map container while drawing.
- drawingCSSClass: 'leaflet-editable-drawing',
+ // 馃崅option drawingCSSClass: string = 'leaflet-editable-drawing'
+ // CSS class to be added to the map container while drawing.
+ drawingCSSClass: 'leaflet-editable-drawing',
- // 馃崅option drawingCursor: const = 'crosshair'
- // Cursor mode set to the map while drawing.
- drawingCursor: 'crosshair',
+ // 馃崅option drawingCursor: const = 'crosshair'
+ // Cursor mode set to the map while drawing.
+ drawingCursor: 'crosshair',
- // 馃崅option editLayer: Layer = new L.LayerGroup()
- // Layer used to store edit tools (vertex, line guide鈥�).
- editLayer: undefined,
+ // 馃崅option editLayer: Layer = new L.LayerGroup()
+ // Layer used to store edit tools (vertex, line guide鈥�).
+ editLayer: undefined,
- // 馃崅option featuresLayer: Layer = new L.LayerGroup()
- // Default layer used to store drawn features (Marker, Polyline鈥�).
- featuresLayer: undefined,
+ // 馃崅option featuresLayer: Layer = new L.LayerGroup()
+ // Default layer used to store drawn features (Marker, Polyline鈥�).
+ featuresLayer: undefined,
- // 馃崅option polylineEditorClass: class = PolylineEditor
- // Class to be used as Polyline editor.
- polylineEditorClass: undefined,
+ // 馃崅option polylineEditorClass: class = PolylineEditor
+ // Class to be used as Polyline editor.
+ polylineEditorClass: undefined,
- // 馃崅option polygonEditorClass: class = PolygonEditor
- // Class to be used as Polygon editor.
- polygonEditorClass: undefined,
+ // 馃崅option polygonEditorClass: class = PolygonEditor
+ // Class to be used as Polygon editor.
+ polygonEditorClass: undefined,
- // 馃崅option markerEditorClass: class = MarkerEditor
- // Class to be used as Marker editor.
- markerEditorClass: undefined,
+ // 馃崅option markerEditorClass: class = MarkerEditor
+ // Class to be used as Marker editor.
+ markerEditorClass: undefined,
- // 馃崅option rectangleEditorClass: class = RectangleEditor
- // Class to be used as Rectangle editor.
- rectangleEditorClass: undefined,
+ // 馃崅option rectangleEditorClass: class = RectangleEditor
+ // Class to be used as Rectangle editor.
+ rectangleEditorClass: undefined,
- // 馃崅option circleEditorClass: class = CircleEditor
- // Class to be used as Circle editor.
- circleEditorClass: undefined,
+ // 馃崅option circleEditorClass: class = CircleEditor
+ // Class to be used as Circle editor.
+ circleEditorClass: undefined,
- // 馃崅option lineGuideOptions: hash = {}
- // Options to be passed to the line guides.
- lineGuideOptions: {},
+ // 馃崅option lineGuideOptions: hash = {}
+ // Options to be passed to the line guides.
+ lineGuideOptions: {},
- // 馃崅option skipMiddleMarkers: boolean = false
- // Set this to true if you don't want middle markers.
- skipMiddleMarkers: false
+ // 馃崅option skipMiddleMarkers: boolean = false
+ // Set this to true if you don't want middle markers.
+ skipMiddleMarkers: false
- },
+ },
- initialize: function (map, options) {
- L.setOptions(this, options)
- this._lastZIndex = this.options.zIndex
- this.map = map
- this.editLayer = this.createEditLayer()
- this.featuresLayer = this.createFeaturesLayer()
- this.forwardLineGuide = this.createLineGuide()
- this.backwardLineGuide = this.createLineGuide()
- },
+ initialize: function (map, options) {
+ L.setOptions(this, options)
+ this._lastZIndex = this.options.zIndex
+ this.map = map
+ this.editLayer = this.createEditLayer()
+ this.featuresLayer = this.createFeaturesLayer()
+ this.forwardLineGuide = this.createLineGuide()
+ this.backwardLineGuide = this.createLineGuide()
+ },
- fireAndForward: function (type, e) {
- e = e || {}
- e.editTools = this
- this.fire(type, e)
- this.map.fire(type, e)
- },
+ fireAndForward: function (type, e) {
+ e = e || {}
+ e.editTools = this
+ this.fire(type, e)
+ this.map.fire(type, e)
+ },
- createLineGuide: function () {
- const options = L.extend({
- dashArray: '5,10',
- weight: 1,
- interactive: false
- }, this.options.lineGuideOptions)
- return L.polyline([], options)
- },
+ createLineGuide: function () {
+ const options = L.extend({
+ dashArray: '5,10',
+ weight: 1,
+ interactive: false
+ }, this.options.lineGuideOptions)
+ return L.polyline([], options)
+ },
- createVertexIcon: function (options) {
- return L.Browser.mobile && L.Browser.touch ? new L.Editable.TouchVertexIcon(options) : new L.Editable.VertexIcon(options)
- },
+ createVertexIcon: function (options) {
+ return L.Browser.mobile && L.Browser.touch ? new L.Editable.TouchVertexIcon(options) : new L.Editable.VertexIcon(options)
+ },
- createEditLayer: function () {
- return this.options.editLayer || new L.LayerGroup().addTo(this.map)
- },
+ createEditLayer: function () {
+ return this.options.editLayer || new L.LayerGroup().addTo(this.map)
+ },
- createFeaturesLayer: function () {
- return this.options.featuresLayer || new L.LayerGroup().addTo(this.map)
- },
+ createFeaturesLayer: function () {
+ return this.options.featuresLayer || new L.LayerGroup().addTo(this.map)
+ },
- moveForwardLineGuide: function (latlng) {
- if (this.forwardLineGuide._latlngs.length) {
- this.forwardLineGuide._latlngs[1] = latlng
- this.forwardLineGuide._bounds.extend(latlng)
- this.forwardLineGuide.redraw()
- }
- },
-
- moveBackwardLineGuide: function (latlng) {
- if (this.backwardLineGuide._latlngs.length) {
- this.backwardLineGuide._latlngs[1] = latlng
- this.backwardLineGuide._bounds.extend(latlng)
- this.backwardLineGuide.redraw()
- }
- },
-
- anchorForwardLineGuide: function (latlng) {
- this.forwardLineGuide._latlngs[0] = latlng
+ moveForwardLineGuide: function (latlng) {
+ if (this.forwardLineGuide._latlngs.length) {
+ this.forwardLineGuide._latlngs[1] = latlng
this.forwardLineGuide._bounds.extend(latlng)
this.forwardLineGuide.redraw()
- },
+ }
+ },
- anchorBackwardLineGuide: function (latlng) {
- this.backwardLineGuide._latlngs[0] = latlng
+ moveBackwardLineGuide: function (latlng) {
+ if (this.backwardLineGuide._latlngs.length) {
+ this.backwardLineGuide._latlngs[1] = latlng
this.backwardLineGuide._bounds.extend(latlng)
this.backwardLineGuide.redraw()
- },
-
- attachForwardLineGuide: function () {
- this.editLayer.addLayer(this.forwardLineGuide)
- },
-
- attachBackwardLineGuide: function () {
- this.editLayer.addLayer(this.backwardLineGuide)
- },
-
- detachForwardLineGuide: function () {
- this.forwardLineGuide.setLatLngs([])
- this.editLayer.removeLayer(this.forwardLineGuide)
- },
-
- detachBackwardLineGuide: function () {
- this.backwardLineGuide.setLatLngs([])
- this.editLayer.removeLayer(this.backwardLineGuide)
- },
-
- blockEvents: function () {
- // Hack: force map not to listen to other layers events while drawing.
- if (!this._oldTargets) {
- this._oldTargets = this.map._targets
- this.map._targets = {}
- }
- },
-
- unblockEvents: function () {
- if (this._oldTargets) {
- // Reset, but keep targets created while drawing.
- this.map._targets = L.extend(this.map._targets, this._oldTargets)
- delete this._oldTargets
- }
- },
-
- registerForDrawing: function (editor) {
- if (this._drawingEditor) this.unregisterForDrawing(this._drawingEditor)
- this.blockEvents()
- editor.reset() // Make sure editor tools still receive events.
- this._drawingEditor = editor
- this.map.on('mousemove touchmove', editor.onDrawingMouseMove, editor)
- this.map.on('mousedown', this.onMousedown, this)
- this.map.on('mouseup', this.onMouseup, this)
- L.DomUtil.addClass(this.map._container, this.options.drawingCSSClass)
- this.defaultMapCursor = this.map._container.style.cursor
- this.map._container.style.cursor = this.options.drawingCursor
- },
-
- unregisterForDrawing: function (editor) {
- this.unblockEvents()
- L.DomUtil.removeClass(this.map._container, this.options.drawingCSSClass)
- this.map._container.style.cursor = this.defaultMapCursor
- editor = editor || this._drawingEditor
- if (!editor) return
- this.map.off('mousemove touchmove', editor.onDrawingMouseMove, editor)
- this.map.off('mousedown', this.onMousedown, this)
- this.map.off('mouseup', this.onMouseup, this)
- if (editor !== this._drawingEditor) return
- delete this._drawingEditor
- if (editor._drawing) editor.cancelDrawing()
- },
-
- onMousedown: function (e) {
- if (e.originalEvent.which !== 1) return
- this._mouseDown = e
- this._drawingEditor.onDrawingMouseDown(e)
- },
-
- onMouseup: function (e) {
- if (this._mouseDown) {
- const editor = this._drawingEditor
- const mouseDown = this._mouseDown
- this._mouseDown = null
- editor.onDrawingMouseUp(e)
- if (this._drawingEditor !== editor) return // onDrawingMouseUp may call unregisterFromDrawing.
- const origin = L.point(mouseDown.originalEvent.clientX, mouseDown.originalEvent.clientY)
- const distance = L.point(e.originalEvent.clientX, e.originalEvent.clientY).distanceTo(origin)
- if (Math.abs(distance) < 9 * (window.devicePixelRatio || 1)) this._drawingEditor.onDrawingClick(e)
- }
- },
-
- // 馃崅section Public methods
- // You will generally access them by the `map.editTools`
- // instance:
- //
- // `map.editTools.startPolyline();`
-
- // 馃崅method drawing(): boolean
- // Return true if any drawing action is ongoing.
- drawing: function () {
- return this._drawingEditor && this._drawingEditor.drawing()
- },
-
- // 馃崅method stopDrawing()
- // When you need to stop any ongoing drawing, without needing to know which editor is active.
- stopDrawing: function () {
- this.unregisterForDrawing()
- },
-
- // 馃崅method commitDrawing()
- // When you need to commit any ongoing drawing, without needing to know which editor is active.
- commitDrawing: function (e) {
- if (!this._drawingEditor) return
- this._drawingEditor.commitDrawing(e)
- },
-
- connectCreatedToMap: function (layer) {
- return this.featuresLayer.addLayer(layer)
- },
- // 馃崅method startPolyline(latlng: L.LatLng, options: hash): L.Polyline
- // Start drawing a Polyline. If `latlng` is given, a first point will be added. In any case, continuing on user click.
- // If `options` is given, it will be passed to the Polyline class constructor.
- // 鐢荤嚎
- startPolyline: function (latlng, options) {
- const line = this.createPolyline([], options)
- line.enableEdit(this.map).newShape(latlng)
- return line
- },
-
- // 馃崅method startPolygon(latlng: L.LatLng, options: hash): L.Polygon
- // Start drawing a Polygon. If `latlng` is given, a first point will be added. In any case, continuing on user click.
- // If `options` is given, it will be passed to the Polygon class constructor.
- startPolygon: function (latlng, options) {
- const polygon = this.createPolygon([], options)
- polygon.enableEdit(this.map).newShape(latlng)
- return polygon
- },
-
- // 馃崅method startMarker(latlng: L.LatLng, options: hash): L.Marker
- // Start adding a Marker. If `latlng` is given, the Marker will be shown first at this point.
- // In any case, it will follow the user mouse, and will have a final `latlng` on next click (or touch).
- // If `options` is given, it will be passed to the Marker class constructor.
- startMarker: function (latlng, options) {
- latlng = latlng || this.map.getCenter().clone()
- const marker = this.createMarker(latlng, options)
- marker.enableEdit(this.map).startDrawing()
- return marker
- },
-
- // 馃崅method startRectangle(latlng: L.LatLng, options: hash): L.Rectangle
- // Start drawing a Rectangle. If `latlng` is given, the Rectangle anchor will be added. In any case, continuing on user drag.
- // If `options` is given, it will be passed to the Rectangle class constructor.
- startRectangle: function (latlng, options) {
- const corner = latlng || L.latLng([0, 0])
- const bounds = new L.LatLngBounds(corner, corner)
- const rectangle = this.createRectangle(bounds, options)
- rectangle.enableEdit(this.map).startDrawing()
- return rectangle
- },
-
- // 馃崅method startCircle(latlng: L.LatLng, options: hash): L.Circle
- // Start drawing a Circle. If `latlng` is given, the Circle anchor will be added. In any case, continuing on user drag.
- // If `options` is given, it will be passed to the Circle class constructor.
- startCircle: function (latlng, options) {
- latlng = latlng || this.map.getCenter().clone()
- const circle = this.createCircle(latlng, options)
- circle.enableEdit(this.map).startDrawing()
- return circle
- },
-
- startHole: function (editor, latlng) {
- editor.newHole(latlng)
- },
-
- createLayer: function (Klass, latlngs, options) {
- options = L.Util.extend({ editOptions: { editTools: this } }, options)
- const layer = new Klass(latlngs, options)
- // 馃崅namespace Editable
- // 馃崅event editable:created: LayerEvent
- // Fired when a new feature (Marker, Polyline鈥�) is created.
- this.fireAndForward('editable:created', { layer: layer })
- return layer
- },
-
- createPolyline: function (latlngs, options) {
- return this.createLayer((options && options.polylineClass) || this.options.polylineClass, latlngs, options)
- },
-
- createPolygon: function (latlngs, options) {
- return this.createLayer((options && options.polygonClass) || this.options.polygonClass, latlngs, options)
- },
-
- createMarker: function (latlng, options) {
- return this.createLayer((options && options.markerClass) || this.options.markerClass, latlng, options)
- },
-
- createRectangle: function (bounds, options) {
- return this.createLayer((options && options.rectangleClass) || this.options.rectangleClass, bounds, options)
- },
-
- createCircle: function (latlng, options) {
- return this.createLayer((options && options.circleClass) || this.options.circleClass, latlng, options)
}
+ },
- })
+ anchorForwardLineGuide: function (latlng) {
+ this.forwardLineGuide._latlngs[0] = latlng
+ this.forwardLineGuide._bounds.extend(latlng)
+ this.forwardLineGuide.redraw()
+ },
- L.extend(L.Editable, {
+ anchorBackwardLineGuide: function (latlng) {
+ this.backwardLineGuide._latlngs[0] = latlng
+ this.backwardLineGuide._bounds.extend(latlng)
+ this.backwardLineGuide.redraw()
+ },
- makeCancellable: function (e) {
- e.cancel = function () {
- e._cancelled = true
- }
+ attachForwardLineGuide: function () {
+ this.editLayer.addLayer(this.forwardLineGuide)
+ },
+
+ attachBackwardLineGuide: function () {
+ this.editLayer.addLayer(this.backwardLineGuide)
+ },
+
+ detachForwardLineGuide: function () {
+ this.forwardLineGuide.setLatLngs([])
+ this.editLayer.removeLayer(this.forwardLineGuide)
+ },
+
+ detachBackwardLineGuide: function () {
+ this.backwardLineGuide.setLatLngs([])
+ this.editLayer.removeLayer(this.backwardLineGuide)
+ },
+
+ blockEvents: function () {
+ // Hack: force map not to listen to other layers events while drawing.
+ if (!this._oldTargets) {
+ this._oldTargets = this.map._targets
+ this.map._targets = {}
}
+ },
- })
+ unblockEvents: function () {
+ if (this._oldTargets) {
+ // Reset, but keep targets created while drawing.
+ this.map._targets = L.extend(this.map._targets, this._oldTargets)
+ delete this._oldTargets
+ }
+ },
- // 馃崅namespace Map; 馃崅class Map
- // Leaflet.Editable add options and events to the `L.Map` object.
- // See `Editable` events for the list of events fired on the Map.
- // 馃崅example
+ registerForDrawing: function (editor) {
+ if (this._drawingEditor) this.unregisterForDrawing(this._drawingEditor)
+ this.blockEvents()
+ editor.reset() // Make sure editor tools still receive events.
+ this._drawingEditor = editor
+ this.map.on('mousemove touchmove', editor.onDrawingMouseMove, editor)
+ this.map.on('mousedown', this.onMousedown, this)
+ this.map.on('mouseup', this.onMouseup, this)
+ L.DomUtil.addClass(this.map._container, this.options.drawingCSSClass)
+ this.defaultMapCursor = this.map._container.style.cursor
+ this.map._container.style.cursor = this.options.drawingCursor
+ },
+
+ unregisterForDrawing: function (editor) {
+ this.unblockEvents()
+ L.DomUtil.removeClass(this.map._container, this.options.drawingCSSClass)
+ this.map._container.style.cursor = this.defaultMapCursor
+ editor = editor || this._drawingEditor
+ if (!editor) return
+ this.map.off('mousemove touchmove', editor.onDrawingMouseMove, editor)
+ this.map.off('mousedown', this.onMousedown, this)
+ this.map.off('mouseup', this.onMouseup, this)
+ if (editor !== this._drawingEditor) return
+ delete this._drawingEditor
+ if (editor._drawing) editor.cancelDrawing()
+ },
+
+ onMousedown: function (e) {
+ if (e.originalEvent.which !== 1) return
+ this._mouseDown = e
+ this._drawingEditor.onDrawingMouseDown(e)
+ },
+
+ onMouseup: function (e) {
+ if (this._mouseDown) {
+ const editor = this._drawingEditor
+ const mouseDown = this._mouseDown
+ this._mouseDown = null
+ editor.onDrawingMouseUp(e)
+ if (this._drawingEditor !== editor) return // onDrawingMouseUp may call unregisterFromDrawing.
+ const origin = L.point(mouseDown.originalEvent.clientX, mouseDown.originalEvent.clientY)
+ const distance = L.point(e.originalEvent.clientX, e.originalEvent.clientY).distanceTo(origin)
+ if (Math.abs(distance) < 9 * (window.devicePixelRatio || 1)) this._drawingEditor.onDrawingClick(e)
+ }
+ },
+
+ // 馃崅section Public methods
+ // You will generally access them by the `map.editTools`
+ // instance:
//
- // ```js
- // let map = L.map('map', {
- // editable: true,
- // editOptions: {
- // 鈥�
- // }
- // });
- // ```
- // 馃崅section Editable Map Options
- L.Map.mergeOptions({
+ // `map.editTools.startPolyline();`
- // 馃崅namespace Map
- // 馃崅section Map Options
- // 馃崅option EditToolsClass: class = L.Editable
- // Class to be used as vertex, for path editing.
- EditToolsClass: L.Editable,
+ // 馃崅method drawing(): boolean
+ // Return true if any drawing action is ongoing.
+ drawing: function () {
+ return this._drawingEditor && this._drawingEditor.drawing()
+ },
- // 馃崅option editable: boolean = false
- // Whether to create a L.Editable instance at map init.
- editable: false,
+ // 馃崅method stopDrawing()
+ // When you need to stop any ongoing drawing, without needing to know which editor is active.
+ stopDrawing: function () {
+ this.unregisterForDrawing()
+ },
- // 馃崅option editOptions: hash = {}
- // Options to pass to L.Editable when instantiating.
- editOptions: {}
+ // 馃崅method commitDrawing()
+ // When you need to commit any ongoing drawing, without needing to know which editor is active.
+ commitDrawing: function (e) {
+ if (!this._drawingEditor) return
+ this._drawingEditor.commitDrawing(e)
+ },
- })
+ connectCreatedToMap: function (layer) {
+ return this.featuresLayer.addLayer(layer)
+ },
+ // 馃崅method startPolyline(latlng: L.LatLng, options: hash): L.Polyline
+ // Start drawing a Polyline. If `latlng` is given, a first point will be added. In any case, continuing on user click.
+ // If `options` is given, it will be passed to the Polyline class constructor.
+ // 鐢荤嚎
+ startPolyline: function (latlng, options) {
+ const line = this.createPolyline([], options)
+ line.enableEdit(this.map).newShape(latlng)
+ return line
+ },
- L.Map.addInitHook(function () {
- this.whenReady(function () {
- if (this.options.editable) {
- this.editTools = new this.options.EditToolsClass(this, this.options.editOptions)
- }
- })
- })
+ // 馃崅method startPolygon(latlng: L.LatLng, options: hash): L.Polygon
+ // Start drawing a Polygon. If `latlng` is given, a first point will be added. In any case, continuing on user click.
+ // If `options` is given, it will be passed to the Polygon class constructor.
+ startPolygon: function (latlng, options) {
+ const polygon = this.createPolygon([], options)
+ polygon.enableEdit(this.map).newShape(latlng)
+ return polygon
+ },
- L.Editable.VertexIcon = L.DivIcon.extend({
+ // 馃崅method startMarker(latlng: L.LatLng, options: hash): L.Marker
+ // Start adding a Marker. If `latlng` is given, the Marker will be shown first at this point.
+ // In any case, it will follow the user mouse, and will have a final `latlng` on next click (or touch).
+ // If `options` is given, it will be passed to the Marker class constructor.
+ startMarker: function (latlng, options) {
+ latlng = latlng || this.map.getCenter().clone()
+ const marker = this.createMarker(latlng, options)
+ marker.enableEdit(this.map).startDrawing()
+ return marker
+ },
- options: {
- iconSize: new L.Point(8, 8)
- }
+ // 馃崅method startRectangle(latlng: L.LatLng, options: hash): L.Rectangle
+ // Start drawing a Rectangle. If `latlng` is given, the Rectangle anchor will be added. In any case, continuing on user drag.
+ // If `options` is given, it will be passed to the Rectangle class constructor.
+ startRectangle: function (latlng, options) {
+ const corner = latlng || L.latLng([0, 0])
+ const bounds = new L.LatLngBounds(corner, corner)
+ const rectangle = this.createRectangle(bounds, options)
+ rectangle.enableEdit(this.map).startDrawing()
+ return rectangle
+ },
- })
+ // 馃崅method startCircle(latlng: L.LatLng, options: hash): L.Circle
+ // Start drawing a Circle. If `latlng` is given, the Circle anchor will be added. In any case, continuing on user drag.
+ // If `options` is given, it will be passed to the Circle class constructor.
+ startCircle: function (latlng, options) {
+ latlng = latlng || this.map.getCenter().clone()
+ const circle = this.createCircle(latlng, options)
+ circle.enableEdit(this.map).startDrawing()
+ return circle
+ },
- L.Editable.TouchVertexIcon = L.Editable.VertexIcon.extend({
+ startHole: function (editor, latlng) {
+ editor.newHole(latlng)
+ },
- options: {
- iconSize: new L.Point(20, 20)
- }
-
- })
-
- // 馃崅namespace Editable; 馃崅class VertexMarker; Handler for dragging path vertices.
- L.Editable.VertexMarker = L.Marker.extend({
-
- options: {
- draggable: true,
- className: 'leaflet-vertex-icon leaflet-custom-icon'
- },
-
- // 馃崅section Public methods
- // The marker used to handle path vertex. You will usually interact with a `VertexMarker`
- // instance when listening for events like `editable:vertex:ctrlclick`.
-
- initialize: function (latlng, latlngs, editor, options) {
- // We don't use this._latlng, because on drag Leaflet replace it while
- // we want to keep reference.
- this.latlng = latlng
- this.latlngs = latlngs
- this.editor = editor
- L.Marker.prototype.initialize.call(this, latlng, options)
- this.options.icon = this.editor.tools.createVertexIcon({ className: this.options.className })
- this.latlng.__vertex = this
- this.editor.editLayer.addLayer(this)
- this.setZIndexOffset(editor.tools._lastZIndex + 1)
- },
-
- onAdd: function (map) {
- L.Marker.prototype.onAdd.call(this, map)
- this.on('drag', this.onDrag)
- this.on('dragstart', this.onDragStart)
- this.on('dragend', this.onDragEnd)
- this.on('mouseup', this.onMouseup)
- this.on('click', this.onClick)
- this.on('contextmenu', this.onContextMenu)
- this.on('mousedown touchstart', this.onMouseDown)
- this.on('mouseover', this.onMouseOver)
- this.on('mouseout', this.onMouseOut)
- this.addMiddleMarkers()
- },
-
- onRemove: function (map) {
- if (this.middleMarker) this.middleMarker.delete()
- delete this.latlng.__vertex
- this.off('drag', this.onDrag)
- this.off('dragstart', this.onDragStart)
- this.off('dragend', this.onDragEnd)
- this.off('mouseup', this.onMouseup)
- this.off('click', this.onClick)
- this.off('contextmenu', this.onContextMenu)
- this.off('mousedown touchstart', this.onMouseDown)
- this.off('mouseover', this.onMouseOver)
- this.off('mouseout', this.onMouseOut)
- L.Marker.prototype.onRemove.call(this, map)
- },
-
- onDrag: function (e) {
- e.vertex = this
- this.editor.onVertexMarkerDrag(e)
- const iconPos = L.DomUtil.getPosition(this._icon)
- const latlng = this._map.layerPointToLatLng(iconPos)
- this.latlng.update(latlng)
- this._latlng = this.latlng // Push back to Leaflet our reference.
- this.editor.refresh()
- if (this.middleMarker) this.middleMarker.updateLatLng()
- const next = this.getNext()
- if (next && next.middleMarker) next.middleMarker.updateLatLng()
- },
-
- onDragStart: function (e) {
- e.vertex = this
- this.editor.onVertexMarkerDragStart(e)
- },
-
- onDragEnd: function (e) {
- e.vertex = this
- this.editor.onVertexMarkerDragEnd(e)
- },
-
- onClick: function (e) {
- e.vertex = this
- this.editor.onVertexMarkerClick(e)
- },
-
- onMouseup: function (e) {
- L.DomEvent.stop(e)
- e.vertex = this
- this.editor.map.fire('mouseup', e)
- },
-
- onContextMenu: function (e) {
- e.vertex = this
- this.editor.onVertexMarkerContextMenu(e)
- },
-
- onMouseDown: function (e) {
- e.vertex = this
- this.editor.onVertexMarkerMouseDown(e)
- },
-
- onMouseOver: function (e) {
- e.vertex = this
- this.editor.onVertexMarkerMouseOver(e)
- },
-
- onMouseOut: function (e) {
- e.vertex = this
- this.editor.onVertexMarkerMouseOut(e)
- },
-
- // 馃崅method delete()
- // Delete a vertex and the related LatLng.
- delete: function () {
- const next = this.getNext() // Compute before changing latlng
- this.latlngs.splice(this.getIndex(), 1)
- this.editor.editLayer.removeLayer(this)
- this.editor.onVertexDeleted({
- latlng: this.latlng,
- vertex: this
- })
- if (!this.latlngs.length) this.editor.deleteShape(this.latlngs)
- if (next) next.resetMiddleMarker()
- this.editor.refresh()
- },
-
- // 馃崅method getIndex(): int
- // Get the index of the current vertex among others of the same LatLngs group.
- getIndex: function () {
- return this.latlngs.indexOf(this.latlng)
- },
-
- // 馃崅method getLastIndex(): int
- // Get last vertex index of the LatLngs group of the current vertex.
- getLastIndex: function () {
- return this.latlngs.length - 1
- },
-
- // 馃崅method getPrevious(): VertexMarker
- // Get the previous VertexMarker in the same LatLngs group.
- getPrevious: function () {
- if (this.latlngs.length < 2) return
- const index = this.getIndex()
- let previousIndex = index - 1
- if (index === 0 && this.editor.CLOSED) previousIndex = this.getLastIndex()
- const previous = this.latlngs[previousIndex]
- if (previous) return previous.__vertex
- },
-
- // 馃崅method getNext(): VertexMarker
- // Get the next VertexMarker in the same LatLngs group.
- getNext: function () {
- if (this.latlngs.length < 2) return
- const index = this.getIndex()
- let nextIndex = index + 1
- if (index === this.getLastIndex() && this.editor.CLOSED) nextIndex = 0
- const next = this.latlngs[nextIndex]
- if (next) return next.__vertex
- },
-
- addMiddleMarker: function (previous) {
- if (!this.editor.hasMiddleMarkers()) return
- previous = previous || this.getPrevious()
- if (previous && !this.middleMarker) this.middleMarker = this.editor.addMiddleMarker(previous, this, this.latlngs, this.editor)
- },
-
- addMiddleMarkers: function () {
- if (!this.editor.hasMiddleMarkers()) return
- const previous = this.getPrevious()
- if (previous) this.addMiddleMarker(previous)
- const next = this.getNext()
- if (next) next.resetMiddleMarker()
- },
-
- resetMiddleMarker: function () {
- if (this.middleMarker) this.middleMarker.delete()
- this.addMiddleMarker()
- },
-
- // 馃崅method split()
- // Split the vertex LatLngs group at its index, if possible.
- split: function () {
- if (!this.editor.splitShape) return // Only for PolylineEditor
- this.editor.splitShape(this.latlngs, this.getIndex())
- },
-
- // 馃崅method continue()
- // Continue the vertex LatLngs from this vertex. Only active for first and last vertices of a Polyline.
- continue: function () {
- if (!this.editor.continueBackward) return // Only for PolylineEditor
- const index = this.getIndex()
- if (index === 0) {
- this.editor.continueBackward(this.latlngs)
- } else if (index === this.getLastIndex()) this.editor.continueForward(this.latlngs)
- }
-
- })
-
- L.Editable.mergeOptions({
-
+ createLayer: function (Klass, latlngs, options) {
+ options = L.Util.extend({ editOptions: { editTools: this } }, options)
+ const layer = new Klass(latlngs, options)
// 馃崅namespace Editable
- // 馃崅option VertexMarkerClass: class = VertexMarker
- // Class to be used as vertex, for path editing.
- VertexMarkerClass: L.Editable.VertexMarker
+ // 馃崅event editable:created: LayerEvent
+ // Fired when a new feature (Marker, Polyline鈥�) is created.
+ this.fireAndForward('editable:created', { layer: layer })
+ return layer
+ },
- })
+ createPolyline: function (latlngs, options) {
+ return this.createLayer((options && options.polylineClass) || this.options.polylineClass, latlngs, options)
+ },
- L.Editable.MiddleMarker = L.Marker.extend({
+ createPolygon: function (latlngs, options) {
+ return this.createLayer((options && options.polygonClass) || this.options.polygonClass, latlngs, options)
+ },
- options: {
- opacity: 0.5,
- className: 'leaflet-div-icon leaflet-middle-icon',
- draggable: true
- },
+ createMarker: function (latlng, options) {
+ return this.createLayer((options && options.markerClass) || this.options.markerClass, latlng, options)
+ },
- initialize: function (left, right, latlngs, editor, options) {
- this.left = left
- this.right = right
- this.editor = editor
- this.latlngs = latlngs
- L.Marker.prototype.initialize.call(this, this.computeLatLng(), options)
- this._opacity = this.options.opacity
- this.options.icon = this.editor.tools.createVertexIcon({ className: this.options.className })
- this.editor.editLayer.addLayer(this)
- this.setVisibility()
- },
+ createRectangle: function (bounds, options) {
+ return this.createLayer((options && options.rectangleClass) || this.options.rectangleClass, bounds, options)
+ },
- setVisibility: function () {
- const leftPoint = this._map.latLngToContainerPoint(this.left.latlng)
- const rightPoint = this._map.latLngToContainerPoint(this.right.latlng)
- const size = L.point(this.options.icon.options.iconSize)
- if (leftPoint.distanceTo(rightPoint) < size.x * 3) {
- this.hide()
- } else {
- this.show()
- }
- },
-
- show: function () {
- this.setOpacity(this._opacity)
- },
-
- hide: function () {
- this.setOpacity(0)
- },
-
- updateLatLng: function () {
- this.setLatLng(this.computeLatLng())
- this.setVisibility()
- },
-
- computeLatLng: function () {
- const leftPoint = this.editor.map.latLngToContainerPoint(this.left.latlng)
- const rightPoint = this.editor.map.latLngToContainerPoint(this.right.latlng)
- const y = (leftPoint.y + rightPoint.y) / 2
- const x = (leftPoint.x + rightPoint.x) / 2
- return this.editor.map.containerPointToLatLng([x, y])
- },
-
- onAdd: function (map) {
- L.Marker.prototype.onAdd.call(this, map)
- L.DomEvent.on(this._icon, 'mousedown touchstart', this.onMouseDown, this)
- map.on('zoomend', this.setVisibility, this)
- },
-
- onRemove: function (map) {
- delete this.right.middleMarker
- L.DomEvent.off(this._icon, 'mousedown touchstart', this.onMouseDown, this)
- map.off('zoomend', this.setVisibility, this)
- L.Marker.prototype.onRemove.call(this, map)
- },
-
- onMouseDown: function (e) {
- const iconPos = L.DomUtil.getPosition(this._icon)
- const latlng = this.editor.map.layerPointToLatLng(iconPos)
- e = {
- originalEvent: e,
- latlng: latlng
- }
- if (this.options.opacity === 0) return
- L.Editable.makeCancellable(e)
- this.editor.onMiddleMarkerMouseDown(e)
- if (e._cancelled) return
- this.latlngs.splice(this.index(), 0, e.latlng)
- this.editor.refresh()
- const icon = this._icon
- const marker = this.editor.addVertexMarker(e.latlng, this.latlngs)
- this.editor.onNewVertex(marker)
- /* Hack to workaround browser not firing touchend when element is no more on DOM */
- const parent = marker._icon.parentNode
- parent.removeChild(marker._icon)
- marker._icon = icon
- parent.appendChild(marker._icon)
- marker._initIcon()
- marker._initInteraction()
- marker.setOpacity(1)
- /* End hack */
- // Transfer ongoing dragging to real marker
- L.Draggable._dragging = false
- marker.dragging._draggable._onDown(e.originalEvent)
- this.delete()
- },
-
- delete: function () {
- this.editor.editLayer.removeLayer(this)
- },
-
- index: function () {
- return this.latlngs.indexOf(this.right.latlng)
- }
-
- })
-
- L.Editable.mergeOptions({
-
- // 馃崅namespace Editable
- // 馃崅option MiddleMarkerClass: class = VertexMarker
- // Class to be used as middle vertex, pulled by the user to create a new point in the middle of a path.
- MiddleMarkerClass: L.Editable.MiddleMarker
-
- })
-
- // 馃崅namespace Editable; 馃崅class BaseEditor; 馃崅aka L.Editable.BaseEditor
- // When editing a feature (Marker, Polyline鈥�), an editor is attached to it. This
- // editor basically knows how to handle the edition.
- L.Editable.BaseEditor = L.Handler.extend({
-
- initialize: function (map, feature, options) {
- L.setOptions(this, options)
- this.map = map
- this.feature = feature
- this.feature.editor = this
- this.editLayer = new L.LayerGroup()
- this.tools = this.options.editTools || map.editTools
- },
-
- // 馃崅method enable(): this
- // Set up the drawing tools for the feature to be editable.
- addHooks: function () {
- if (this.isConnected()) {
- this.onFeatureAdd()
- } else {
- this.feature.once('add', this.onFeatureAdd, this)
- }
- this.onEnable()
- this.feature.on(this._getEvents(), this)
- },
-
- // 馃崅method disable(): this
- // Remove the drawing tools for the feature.
- removeHooks: function () {
- this.feature.off(this._getEvents(), this)
- if (this.feature.dragging) this.feature.dragging.disable()
- this.editLayer.clearLayers()
- this.tools.editLayer.removeLayer(this.editLayer)
- this.onDisable()
- if (this._drawing) this.cancelDrawing()
- },
-
- // 馃崅method drawing(): boolean
- // Return true if any drawing action is ongoing with this editor.
- drawing: function () {
- return !!this._drawing
- },
-
- reset: function () {
- },
-
- onFeatureAdd: function () {
- this.tools.editLayer.addLayer(this.editLayer)
- if (this.feature.dragging) this.feature.dragging.enable()
- },
-
- hasMiddleMarkers: function () {
- return !this.options.skipMiddleMarkers && !this.tools.options.skipMiddleMarkers
- },
-
- fireAndForward: function (type, e) {
- e = e || {}
- e.layer = this.feature
- this.feature.fire(type, e)
- this.tools.fireAndForward(type, e)
- },
-
- onEnable: function () {
- // 馃崅namespace Editable
- // 馃崅event editable:enable: Event
- // Fired when an existing feature is ready to be edited.
- this.fireAndForward('editable:enable')
- },
-
- onDisable: function () {
- // 馃崅namespace Editable
- // 馃崅event editable:disable: Event
- // Fired when an existing feature is not ready anymore to be edited.
- this.fireAndForward('editable:disable')
- },
-
- onEditing: function () {
- // 馃崅namespace Editable
- // 馃崅event editable:editing: Event
- // Fired as soon as any change is made to the feature geometry.
- this.fireAndForward('editable:editing')
- },
-
- onStartDrawing: function () {
- // 馃崅namespace Editable
- // 馃崅section Drawing events
- // 馃崅event editable:drawing:start: Event
- // Fired when a feature is to be drawn.
- this.fireAndForward('editable:drawing:start')
- },
-
- onEndDrawing: function () {
- // 馃崅namespace Editable
- // 馃崅section Drawing events
- // 馃崅event editable:drawing:end: Event
- // Fired when a feature is not drawn anymore.
- this.fireAndForward('editable:drawing:end')
- },
-
- onCancelDrawing: function () {
- // 馃崅namespace Editable
- // 馃崅section Drawing events
- // 馃崅event editable:drawing:cancel: Event
- // Fired when user cancel drawing while a feature is being drawn.
- this.fireAndForward('editable:drawing:cancel')
- },
-
- onCommitDrawing: function (e) {
- // 馃崅namespace Editable
- // 馃崅section Drawing events
- // 馃崅event editable:drawing:commit: Event
- // Fired when user finish drawing a feature.
- this.fireAndForward('editable:drawing:commit', e)
- },
-
- onDrawingMouseDown: function (e) {
- // 馃崅namespace Editable
- // 馃崅section Drawing events
- // 馃崅event editable:drawing:mousedown: Event
- // Fired when user `mousedown` while drawing.
- this.fireAndForward('editable:drawing:mousedown', e)
- },
-
- onDrawingMouseUp: function (e) {
- // 馃崅namespace Editable
- // 馃崅section Drawing events
- // 馃崅event editable:drawing:mouseup: Event
- // Fired when user `mouseup` while drawing.
- this.fireAndForward('editable:drawing:mouseup', e)
- },
-
- startDrawing: function () {
- if (!this._drawing) this._drawing = L.Editable.FORWARD
- this.tools.registerForDrawing(this)
- this.onStartDrawing()
- },
-
- commitDrawing: function (e) {
- this.onCommitDrawing(e)
- this.endDrawing()
- },
-
- cancelDrawing: function () {
- // If called during a vertex drag, the vertex will be removed before
- // the mouseup fires on it. This is a workaround. Maybe better fix is
- // To have L.Draggable reset it's status on disable (Leaflet side).
- L.Draggable._dragging = false
- this.onCancelDrawing()
- this.endDrawing()
- },
-
- endDrawing: function () {
- this._drawing = false
- this.tools.unregisterForDrawing(this)
- this.onEndDrawing()
- },
-
- onDrawingClick: function (e) {
- if (!this.drawing()) return
- L.Editable.makeCancellable(e)
- // 馃崅namespace Editable
- // 馃崅section Drawing events
- // 馃崅event editable:drawing:click: CancelableEvent
- // Fired when user `click` while drawing, before any internal action is being processed.
- this.fireAndForward('editable:drawing:click', e)
- if (e._cancelled) return
- if (!this.isConnected()) this.connect(e)
- this.processDrawingClick(e)
- },
-
- isConnected: function () {
- return this.map.hasLayer(this.feature)
- },
-
- connect: function () {
- this.tools.connectCreatedToMap(this.feature)
- this.tools.editLayer.addLayer(this.editLayer)
- },
-
- onMove: function (e) {
- // 馃崅namespace Editable
- // 馃崅section Drawing events
- // 馃崅event editable:drawing:move: Event
- // Fired when `move` mouse while drawing, while dragging a marker, and while dragging a vertex.
- this.fireAndForward('editable:drawing:move', e)
- },
-
- onDrawingMouseMove: function (e) {
- this.onMove(e)
- },
-
- _getEvents: function () {
- return {
- dragstart: this.onDragStart,
- drag: this.onDrag,
- dragend: this.onDragEnd,
- remove: this.disable
- }
- },
-
- onDragStart: function (e) {
- this.onEditing()
- // 馃崅namespace Editable
- // 馃崅event editable:dragstart: Event
- // Fired before a path feature is dragged.
- this.fireAndForward('editable:dragstart', e)
- },
-
- onDrag: function (e) {
- this.onMove(e)
- // 馃崅namespace Editable
- // 馃崅event editable:drag: Event
- // Fired when a path feature is being dragged.
- this.fireAndForward('editable:drag', e)
- },
-
- onDragEnd: function (e) {
- // 馃崅namespace Editable
- // 馃崅event editable:dragend: Event
- // Fired after a path feature has been dragged.
- this.fireAndForward('editable:dragend', e)
- }
-
- })
-
- // 馃崅namespace Editable; 馃崅class MarkerEditor; 馃崅aka L.Editable.MarkerEditor
- // 馃崅inherits BaseEditor
- // Editor for Marker.
- L.Editable.MarkerEditor = L.Editable.BaseEditor.extend({
-
- onDrawingMouseMove: function (e) {
- L.Editable.BaseEditor.prototype.onDrawingMouseMove.call(this, e)
- if (this._drawing) this.feature.setLatLng(e.latlng)
- },
-
- processDrawingClick: function (e) {
- // 馃崅namespace Editable
- // 馃崅section Drawing events
- // 馃崅event editable:drawing:clicked: Event
- // Fired when user `click` while drawing, after all internal actions.
- this.fireAndForward('editable:drawing:clicked', e)
- this.commitDrawing(e)
- },
-
- connect: function (e) {
- // On touch, the latlng has not been updated because there is
- // no mousemove.
- if (e) this.feature._latlng = e.latlng
- L.Editable.BaseEditor.prototype.connect.call(this, e)
- }
-
- })
-
- // 馃崅namespace Editable; 馃崅class PathEditor; 馃崅aka L.Editable.PathEditor
- // 馃崅inherits BaseEditor
- // Base class for all path editors.
- L.Editable.PathEditor = L.Editable.BaseEditor.extend({
-
- CLOSED: false,
- MIN_VERTEX: 2,
-
- addHooks: function () {
- L.Editable.BaseEditor.prototype.addHooks.call(this)
- if (this.feature) this.initVertexMarkers()
- return this
- },
-
- initVertexMarkers: function (latlngs) {
- if (!this.enabled()) return
- latlngs = latlngs || this.getLatLngs()
- if (isFlat(latlngs)) {
- this.addVertexMarkers(latlngs)
- } else {
- for (let i = 0; i < latlngs.length; i++) this.initVertexMarkers(latlngs[i])
- }
- },
-
- getLatLngs: function () {
- return this.feature.getLatLngs()
- },
-
- // 馃崅method reset()
- // Rebuild edit elements (Vertex, MiddleMarker, etc.).
- reset: function () {
- this.editLayer.clearLayers()
- this.initVertexMarkers()
- },
-
- addVertexMarker: function (latlng, latlngs) {
- return new this.tools.options.VertexMarkerClass(latlng, latlngs, this)
- },
-
- onNewVertex: function (vertex) {
- // 馃崅namespace Editable
- // 馃崅section Vertex events
- // 馃崅event editable:vertex:new: VertexEvent
- // Fired when a new vertex is created.
- this.fireAndForward('editable:vertex:new', {
- latlng: vertex.latlng,
- vertex: vertex
- })
- },
-
- addVertexMarkers: function (latlngs) {
- for (let i = 0; i < latlngs.length; i++) {
- this.addVertexMarker(latlngs[i], latlngs)
- }
- },
-
- refreshVertexMarkers: function (latlngs) {
- latlngs = latlngs || this.getDefaultLatLngs()
- for (let i = 0; i < latlngs.length; i++) {
- latlngs[i].__vertex.update()
- }
- },
-
- addMiddleMarker: function (left, right, latlngs) {
- return new this.tools.options.MiddleMarkerClass(left, right, latlngs, this)
- },
-
- onVertexMarkerClick: function (e) {
- L.Editable.makeCancellable(e)
- // 馃崅namespace Editable
- // 馃崅section Vertex events
- // 馃崅event editable:vertex:click: CancelableVertexEvent
- // Fired when a `click` is issued on a vertex, before any internal action is being processed.
- this.fireAndForward('editable:vertex:click', e)
- if (e._cancelled) return
- if (this.tools.drawing() && this.tools._drawingEditor !== this) return
- const index = e.vertex.getIndex()
- let commit
- if (e.originalEvent.ctrlKey) {
- this.onVertexMarkerCtrlClick(e)
- } else if (e.originalEvent.altKey) {
- this.onVertexMarkerAltClick(e)
- } else if (e.originalEvent.shiftKey) {
- this.onVertexMarkerShiftClick(e)
- } else if (e.originalEvent.metaKey) {
- this.onVertexMarkerMetaKeyClick(e)
- } else if (index === e.vertex.getLastIndex() && this._drawing === L.Editable.FORWARD) {
- if (index >= this.MIN_VERTEX - 1) commit = true
- } else if (index === 0 && this._drawing === L.Editable.BACKWARD && this._drawnLatLngs.length >= this.MIN_VERTEX) {
- commit = true
- } else if (index === 0 && this._drawing === L.Editable.FORWARD && this._drawnLatLngs.length >= this.MIN_VERTEX && this.CLOSED) {
- commit = true // Allow to close on first point also for polygons
- } else {
- this.onVertexRawMarkerClick(e)
- }
- // 馃崅namespace Editable
- // 馃崅section Vertex events
- // 馃崅event editable:vertex:clicked: VertexEvent
- // Fired when a `click` is issued on a vertex, after all internal actions.
- this.fireAndForward('editable:vertex:clicked', e)
- if (commit) this.commitDrawing(e)
- },
-
- onVertexRawMarkerClick: function (e) {
- // 馃崅namespace Editable
- // 馃崅section Vertex events
- // 馃崅event editable:vertex:rawclick: CancelableVertexEvent
- // Fired when a `click` is issued on a vertex without any special key and without being in drawing mode.
- this.fireAndForward('editable:vertex:rawclick', e)
- if (e._cancelled) return
- if (!this.vertexCanBeDeleted(e.vertex)) return
- e.vertex.delete()
- },
-
- vertexCanBeDeleted: function (vertex) {
- return vertex.latlngs.length > this.MIN_VERTEX
- },
-
- onVertexDeleted: function (e) {
- // 馃崅namespace Editable
- // 馃崅section Vertex events
- // 馃崅event editable:vertex:deleted: VertexEvent
- // Fired after a vertex has been deleted by user.
- this.fireAndForward('editable:vertex:deleted', e)
- },
-
- onVertexMarkerCtrlClick: function (e) {
- // 馃崅namespace Editable
- // 馃崅section Vertex events
- // 馃崅event editable:vertex:ctrlclick: VertexEvent
- // Fired when a `click` with `ctrlKey` is issued on a vertex.
- this.fireAndForward('editable:vertex:ctrlclick', e)
- },
-
- onVertexMarkerShiftClick: function (e) {
- // 馃崅namespace Editable
- // 馃崅section Vertex events
- // 馃崅event editable:vertex:shiftclick: VertexEvent
- // Fired when a `click` with `shiftKey` is issued on a vertex.
- this.fireAndForward('editable:vertex:shiftclick', e)
- },
-
- onVertexMarkerMetaKeyClick: function (e) {
- // 馃崅namespace Editable
- // 馃崅section Vertex events
- // 馃崅event editable:vertex:metakeyclick: VertexEvent
- // Fired when a `click` with `metaKey` is issued on a vertex.
- this.fireAndForward('editable:vertex:metakeyclick', e)
- },
-
- onVertexMarkerAltClick: function (e) {
- // 馃崅namespace Editable
- // 馃崅section Vertex events
- // 馃崅event editable:vertex:altclick: VertexEvent
- // Fired when a `click` with `altKey` is issued on a vertex.
- this.fireAndForward('editable:vertex:altclick', e)
- },
-
- onVertexMarkerContextMenu: function (e) {
- // 馃崅namespace Editable
- // 馃崅section Vertex events
- // 馃崅event editable:vertex:contextmenu: VertexEvent
- // Fired when a `contextmenu` is issued on a vertex.
- this.fireAndForward('editable:vertex:contextmenu', e)
- },
-
- onVertexMarkerMouseDown: function (e) {
- // 馃崅namespace Editable
- // 馃崅section Vertex events
- // 馃崅event editable:vertex:mousedown: VertexEvent
- // Fired when user `mousedown` a vertex.
- this.fireAndForward('editable:vertex:mousedown', e)
- },
-
- onVertexMarkerMouseOver: function (e) {
- // 馃崅namespace Editable
- // 馃崅section Vertex events
- // 馃崅event editable:vertex:mouseover: VertexEvent
- // Fired when a user's mouse enters the vertex
- this.fireAndForward('editable:vertex:mouseover', e)
- },
-
- onVertexMarkerMouseOut: function (e) {
- // 馃崅namespace Editable
- // 馃崅section Vertex events
- // 馃崅event editable:vertex:mouseout: VertexEvent
- // Fired when a user's mouse leaves the vertex
- this.fireAndForward('editable:vertex:mouseout', e)
- },
-
- onMiddleMarkerMouseDown: function (e) {
- // 馃崅namespace Editable
- // 馃崅section MiddleMarker events
- // 馃崅event editable:middlemarker:mousedown: VertexEvent
- // Fired when user `mousedown` a middle marker.
- this.fireAndForward('editable:middlemarker:mousedown', e)
- },
-
- onVertexMarkerDrag: function (e) {
- this.onMove(e)
- if (this.feature._bounds) this.extendBounds(e)
- // 馃崅namespace Editable
- // 馃崅section Vertex events
- // 馃崅event editable:vertex:drag: VertexEvent
- // Fired when a vertex is dragged by user.
- this.fireAndForward('editable:vertex:drag', e)
- },
-
- onVertexMarkerDragStart: function (e) {
- // 馃崅namespace Editable
- // 馃崅section Vertex events
- // 馃崅event editable:vertex:dragstart: VertexEvent
- // Fired before a vertex is dragged by user.
- this.fireAndForward('editable:vertex:dragstart', e)
- },
-
- onVertexMarkerDragEnd: function (e) {
- // 馃崅namespace Editable
- // 馃崅section Vertex events
- // 馃崅event editable:vertex:dragend: VertexEvent
- // Fired after a vertex is dragged by user.
- this.fireAndForward('editable:vertex:dragend', e)
- },
-
- setDrawnLatLngs: function (latlngs) {
- this._drawnLatLngs = latlngs || this.getDefaultLatLngs()
- },
-
- startDrawing: function () {
- if (!this._drawnLatLngs) this.setDrawnLatLngs()
- L.Editable.BaseEditor.prototype.startDrawing.call(this)
- },
-
- startDrawingForward: function () {
- this.startDrawing()
- },
-
- endDrawing: function () {
- this.tools.detachForwardLineGuide()
- this.tools.detachBackwardLineGuide()
- if (this._drawnLatLngs && this._drawnLatLngs.length < this.MIN_VERTEX) this.deleteShape(this._drawnLatLngs)
- L.Editable.BaseEditor.prototype.endDrawing.call(this)
- delete this._drawnLatLngs
- },
-
- addLatLng: function (latlng) {
- if (this._drawing === L.Editable.FORWARD) {
- this._drawnLatLngs.push(latlng)
- } else {
- this._drawnLatLngs.unshift(latlng)
- }
- this.feature._bounds.extend(latlng)
- const vertex = this.addVertexMarker(latlng, this._drawnLatLngs)
- this.onNewVertex(vertex)
- this.refresh()
- },
-
- newPointForward: function (latlng) {
- this.addLatLng(latlng)
- this.tools.attachForwardLineGuide()
- this.tools.anchorForwardLineGuide(latlng)
- },
-
- newPointBackward: function (latlng) {
- this.addLatLng(latlng)
- this.tools.anchorBackwardLineGuide(latlng)
- },
-
- // 馃崅namespace PathEditor
- // 馃崅method push()
- // Programmatically add a point while drawing.
- push: function (latlng) {
- if (!latlng) return console.error('L.Editable.PathEditor.push expect a valid latlng as parameter')
- if (this._drawing === L.Editable.FORWARD) {
- this.newPointForward(latlng)
- } else {
- this.newPointBackward(latlng)
- }
- },
-
- removeLatLng: function (latlng) {
- latlng.__vertex.delete()
- this.refresh()
- },
-
- // 馃崅method pop(): L.LatLng or null
- // Programmatically remove last point (if any) while drawing.
- pop: function () {
- if (this._drawnLatLngs.length <= 1) return
- let latlng
- if (this._drawing === L.Editable.FORWARD) {
- latlng = this._drawnLatLngs[this._drawnLatLngs.length - 1]
- } else {
- latlng = this._drawnLatLngs[0]
- }
- this.removeLatLng(latlng)
- if (this._drawing === L.Editable.FORWARD) {
- this.tools.anchorForwardLineGuide(this._drawnLatLngs[this._drawnLatLngs.length - 1])
- } else {
- this.tools.anchorForwardLineGuide(this._drawnLatLngs[0])
- }
- return latlng
- },
-
- processDrawingClick: function (e) {
- if (e.vertex && e.vertex.editor === this) return
- if (this._drawing === L.Editable.FORWARD) {
- this.newPointForward(e.latlng)
- } else {
- this.newPointBackward(e.latlng)
- }
- this.fireAndForward('editable:drawing:clicked', e)
- },
-
- onDrawingMouseMove: function (e) {
- L.Editable.BaseEditor.prototype.onDrawingMouseMove.call(this, e)
- if (this._drawing) {
- this.tools.moveForwardLineGuide(e.latlng)
- this.tools.moveBackwardLineGuide(e.latlng)
- }
- },
-
- refresh: function () {
- this.feature.redraw()
- this.onEditing()
- },
-
- // 馃崅namespace PathEditor
- // 馃崅method newShape(latlng?: L.LatLng)
- // Add a new shape (Polyline, Polygon) in a multi, and setup up drawing tools to draw it;
- // if optional `latlng` is given, start a path at this point.
- newShape: function (latlng) {
- const shape = this.addNewEmptyShape()
- if (!shape) return
- this.setDrawnLatLngs(shape[0] || shape) // Polygon or polyline
- this.startDrawingForward()
- // 馃崅namespace Editable
- // 馃崅section Shape events
- // 馃崅event editable:shape:new: ShapeEvent
- // Fired when a new shape is created in a multi (Polygon or Polyline).
- this.fireAndForward('editable:shape:new', { shape: shape })
- if (latlng) this.newPointForward(latlng)
- },
-
- deleteShape: function (shape, latlngs) {
- const e = { shape: shape }
- L.Editable.makeCancellable(e)
- // 馃崅namespace Editable
- // 馃崅section Shape events
- // 馃崅event editable:shape:delete: CancelableShapeEvent
- // Fired before a new shape is deleted in a multi (Polygon or Polyline).
- this.fireAndForward('editable:shape:delete', e)
- if (e._cancelled) return
- shape = this._deleteShape(shape, latlngs)
- if (this.ensureNotFlat) this.ensureNotFlat() // Polygon.
- this.feature.setLatLngs(this.getLatLngs()) // Force bounds reset.
- this.refresh()
- this.reset()
- // 馃崅namespace Editable
- // 馃崅section Shape events
- // 馃崅event editable:shape:deleted: ShapeEvent
- // Fired after a new shape is deleted in a multi (Polygon or Polyline).
- this.fireAndForward('editable:shape:deleted', { shape: shape })
- return shape
- },
-
- _deleteShape: function (shape, latlngs) {
- latlngs = latlngs || this.getLatLngs()
- if (!latlngs.length) return
- const self = this
- const inplaceDelete = function (latlngs, shape) {
- // Called when deleting a flat latlngs
- shape = latlngs.splice(0, Number.MAX_VALUE)
- return shape
- }
- const spliceDelete = function (latlngs, shape) {
- // Called when removing a latlngs inside an array
- latlngs.splice(latlngs.indexOf(shape), 1)
- if (!latlngs.length) self._deleteShape(latlngs)
- return shape
- }
- if (latlngs === shape) return inplaceDelete(latlngs, shape)
- for (let i = 0; i < latlngs.length; i++) {
- if (latlngs[i] === shape) {
- return spliceDelete(latlngs, shape)
- } else if (latlngs[i].indexOf(shape) !== -1) return spliceDelete(latlngs[i], shape)
- }
- },
-
- // 馃崅namespace PathEditor
- // 馃崅method deleteShapeAt(latlng: L.LatLng): Array
- // Remove a path shape at the given `latlng`.
- deleteShapeAt: function (latlng) {
- const shape = this.feature.shapeAt(latlng)
- if (shape) return this.deleteShape(shape)
- },
-
- // 馃崅method appendShape(shape: Array)
- // Append a new shape to the Polygon or Polyline.
- appendShape: function (shape) {
- this.insertShape(shape)
- },
-
- // 馃崅method prependShape(shape: Array)
- // Prepend a new shape to the Polygon or Polyline.
- prependShape: function (shape) {
- this.insertShape(shape, 0)
- },
-
- // 馃崅method insertShape(shape: Array, index: int)
- // Insert a new shape to the Polygon or Polyline at given index (default is to append).
- insertShape: function (shape, index) {
- this.ensureMulti()
- shape = this.formatShape(shape)
- if (typeof index === 'undefined') index = this.feature._latlngs.length
- this.feature._latlngs.splice(index, 0, shape)
- this.feature.redraw()
- if (this._enabled) this.reset()
- },
-
- extendBounds: function (e) {
- this.feature._bounds.extend(e.vertex.latlng)
- },
-
- onDragStart: function (e) {
- this.editLayer.clearLayers()
- L.Editable.BaseEditor.prototype.onDragStart.call(this, e)
- },
-
- onDragEnd: function (e) {
- this.initVertexMarkers()
- L.Editable.BaseEditor.prototype.onDragEnd.call(this, e)
- }
-
- })
-
- // 馃崅namespace Editable; 馃崅class PolylineEditor; 馃崅aka L.Editable.PolylineEditor
- // 馃崅inherits PathEditor
- L.Editable.PolylineEditor = L.Editable.PathEditor.extend({
-
- startDrawingBackward: function () {
- this._drawing = L.Editable.BACKWARD
- this.startDrawing()
- },
-
- // 馃崅method continueBackward(latlngs?: Array)
- // Set up drawing tools to continue the line backward.
- continueBackward: function (latlngs) {
- if (this.drawing()) return
- latlngs = latlngs || this.getDefaultLatLngs()
- this.setDrawnLatLngs(latlngs)
- if (latlngs.length > 0) {
- this.tools.attachBackwardLineGuide()
- this.tools.anchorBackwardLineGuide(latlngs[0])
- }
- this.startDrawingBackward()
- },
-
- // 馃崅method continueForward(latlngs?: Array)
- // Set up drawing tools to continue the line forward.
- continueForward: function (latlngs) {
- if (this.drawing()) return
- latlngs = latlngs || this.getDefaultLatLngs()
- this.setDrawnLatLngs(latlngs)
- if (latlngs.length > 0) {
- this.tools.attachForwardLineGuide()
- this.tools.anchorForwardLineGuide(latlngs[latlngs.length - 1])
- }
- this.startDrawingForward()
- },
-
- getDefaultLatLngs: function (latlngs) {
- latlngs = latlngs || this.feature._latlngs
- if (!latlngs.length || latlngs[0] instanceof L.LatLng) {
- return latlngs
- } else {
- return this.getDefaultLatLngs(latlngs[0])
- }
- },
-
- ensureMulti: function () {
- if (this.feature._latlngs.length && isFlat(this.feature._latlngs)) {
- this.feature._latlngs = [this.feature._latlngs]
- }
- },
-
- addNewEmptyShape: function () {
- if (this.feature._latlngs.length) {
- const shape = []
- this.appendShape(shape)
- return shape
- } else {
- return this.feature._latlngs
- }
- },
-
- formatShape: function (shape) {
- if (isFlat(shape)) {
- return shape
- } else if (shape[0]) return this.formatShape(shape[0])
- },
-
- // 馃崅method splitShape(latlngs?: Array, index: int)
- // Split the given `latlngs` shape at index `index` and integrate new shape in instance `latlngs`.
- splitShape: function (shape, index) {
- if (!index || index >= shape.length - 1) return
- this.ensureMulti()
- const shapeIndex = this.feature._latlngs.indexOf(shape)
- if (shapeIndex === -1) return
- const first = shape.slice(0, index + 1)
- const second = shape.slice(index)
- // We deal with reference, we don't want twice the same latlng around.
- second[0] = L.latLng(second[0].lat, second[0].lng, second[0].alt)
- this.feature._latlngs.splice(shapeIndex, 1, first, second)
- this.refresh()
- this.reset()
- }
-
- })
-
- // 馃崅namespace Editable; 馃崅class PolygonEditor; 馃崅aka L.Editable.PolygonEditor
- // 馃崅inherits PathEditor
- L.Editable.PolygonEditor = L.Editable.PathEditor.extend({
-
- CLOSED: true,
- MIN_VERTEX: 3,
-
- newPointForward: function (latlng) {
- L.Editable.PathEditor.prototype.newPointForward.call(this, latlng)
- if (!this.tools.backwardLineGuide._latlngs.length) this.tools.anchorBackwardLineGuide(latlng)
- if (this._drawnLatLngs.length === 2) this.tools.attachBackwardLineGuide()
- },
-
- addNewEmptyHole: function (latlng) {
- this.ensureNotFlat()
- const latlngs = this.feature.shapeAt(latlng)
- if (!latlngs) return
- const holes = []
- latlngs.push(holes)
- return holes
- },
-
- // 馃崅method newHole(latlng?: L.LatLng, index: int)
- // Set up drawing tools for creating a new hole on the Polygon. If the `latlng` param is given, a first point is created.
- newHole: function (latlng) {
- const holes = this.addNewEmptyHole(latlng)
- if (!holes) return
- this.setDrawnLatLngs(holes)
- this.startDrawingForward()
- if (latlng) this.newPointForward(latlng)
- },
-
- addNewEmptyShape: function () {
- if (this.feature._latlngs.length && this.feature._latlngs[0].length) {
- const shape = []
- this.appendShape(shape)
- return shape
- } else {
- return this.feature._latlngs
- }
- },
-
- ensureMulti: function () {
- if (this.feature._latlngs.length && isFlat(this.feature._latlngs[0])) {
- this.feature._latlngs = [this.feature._latlngs]
- }
- },
-
- ensureNotFlat: function () {
- if (!this.feature._latlngs.length || isFlat(this.feature._latlngs)) this.feature._latlngs = [this.feature._latlngs]
- },
-
- vertexCanBeDeleted: function (vertex) {
- const parent = this.feature.parentShape(vertex.latlngs)
- const idx = L.Util.indexOf(parent, vertex.latlngs)
- if (idx > 0) return true // Holes can be totally deleted without removing the layer itself.
- return L.Editable.PathEditor.prototype.vertexCanBeDeleted.call(this, vertex)
- },
-
- getDefaultLatLngs: function () {
- if (!this.feature._latlngs.length) this.feature._latlngs.push([])
- return this.feature._latlngs[0]
- },
-
- formatShape: function (shape) {
- // [[1, 2], [3, 4]] => must be nested
- // [] => must be nested
- // [[]] => is already nested
- if (isFlat(shape) && (!shape[0] || shape[0].length !== 0)) {
- return [shape]
- } else {
- return shape
- }
- }
-
- })
-
- // 馃崅namespace Editable; 馃崅class RectangleEditor; 馃崅aka L.Editable.RectangleEditor
- // 馃崅inherits PathEditor
- L.Editable.RectangleEditor = L.Editable.PathEditor.extend({
-
- CLOSED: true,
- MIN_VERTEX: 4,
-
- options: {
- skipMiddleMarkers: true
- },
-
- extendBounds: function (e) {
- const index = e.vertex.getIndex()
- const next = e.vertex.getNext()
- const previous = e.vertex.getPrevious()
- const oppositeIndex = (index + 2) % 4
- const opposite = e.vertex.latlngs[oppositeIndex]
- const bounds = new L.LatLngBounds(e.latlng, opposite)
- // Update latlngs by hand to preserve order.
- previous.latlng.update([e.latlng.lat, opposite.lng])
- next.latlng.update([opposite.lat, e.latlng.lng])
- this.updateBounds(bounds)
- this.refreshVertexMarkers()
- },
-
- onDrawingMouseDown: function (e) {
- L.Editable.PathEditor.prototype.onDrawingMouseDown.call(this, e)
- this.connect()
- const latlngs = this.getDefaultLatLngs()
- // L.Polygon._convertLatLngs removes last latlng if it equals first point,
- // which is the case here as all latlngs are [0, 0]
- if (latlngs.length === 3) latlngs.push(e.latlng)
- const bounds = new L.LatLngBounds(e.latlng, e.latlng)
- this.updateBounds(bounds)
- this.updateLatLngs(bounds)
- this.refresh()
- this.reset()
- // Stop dragging map.
- // L.Draggable has two workflows:
- // - mousedown => mousemove => mouseup
- // - touchstart => touchmove => touchend
- // Problem: L.Map.Tap does not allow us to listen to touchstart, so we only
- // can deal with mousedown, but then when in a touch device, we are dealing with
- // simulated events (actually simulated by L.Map.Tap), which are no more taken
- // into account by L.Draggable.
- // Ref.: https://github.com/Leaflet/Leaflet.Editable/issues/103
- e.originalEvent._simulated = false
- this.map.dragging._draggable._onUp(e.originalEvent)
- // Now transfer ongoing drag action to the bottom right corner.
- // Should we refine which corner will handle the drag according to
- // drag direction?
- latlngs[3].__vertex.dragging._draggable._onDown(e.originalEvent)
- },
-
- onDrawingMouseUp: function (e) {
- this.commitDrawing(e)
- e.originalEvent._simulated = false
- L.Editable.PathEditor.prototype.onDrawingMouseUp.call(this, e)
- },
-
- onDrawingMouseMove: function (e) {
- e.originalEvent._simulated = false
- L.Editable.PathEditor.prototype.onDrawingMouseMove.call(this, e)
- },
-
- getDefaultLatLngs: function (latlngs) {
- return latlngs || this.feature._latlngs[0]
- },
-
- updateBounds: function (bounds) {
- this.feature._bounds = bounds
- },
-
- updateLatLngs: function (bounds) {
- const latlngs = this.getDefaultLatLngs()
- const newLatlngs = this.feature._boundsToLatLngs(bounds)
- // Keep references.
- for (let i = 0; i < latlngs.length; i++) {
- latlngs[i].update(newLatlngs[i])
- }
- }
-
- })
-
- // 馃崅namespace Editable; 馃崅class CircleEditor; 馃崅aka L.Editable.CircleEditor
- // 馃崅inherits PathEditor
- L.Editable.CircleEditor = L.Editable.PathEditor.extend({
-
- MIN_VERTEX: 2,
-
- options: {
- skipMiddleMarkers: true
- },
-
- initialize: function (map, feature, options) {
- L.Editable.PathEditor.prototype.initialize.call(this, map, feature, options)
- // C.Y.B Modify
-
- const latlng = this.computeResizeLatLng()
-
- // latlng.lat = latlng.lat-0.007855;
- // latlng.lng= latlng.lng-0.1;
- this._resizeLatLng = latlng
- // 鍘熷鏂规硶
- // this._resizeLatLng = this.computeResizeLatLng();
- },
-
- computeResizeLatLng: function () {
- // While circle is not added to the map, _radius is not set.
- // let delta = (this.feature._radius || this.feature._mRadius) * Math.cos(Math.PI / 4)
- const delta = (this.feature._radius || this.feature._mRadius)
- const point = this.map.project(this.feature._latlng)
- // return this.map.unproject([point.x + delta, point.y - delta])
- return this.map.unproject([point.x + delta, point.y])
- },
-
- updateResizeLatLng: function () {
- this._resizeLatLng.update(this.computeResizeLatLng())
- this._resizeLatLng.__vertex.update()
- },
-
- getLatLngs: function () {
- return [this.feature._latlng, this._resizeLatLng]
- },
-
- getDefaultLatLngs: function () {
- return this.getLatLngs()
- },
-
- onVertexMarkerDrag: function (e) {
- if (e.vertex.getIndex() === 1) {
- this.resize(e)
- } else {
- this.updateResizeLatLng(e)
- }
- L.Editable.PathEditor.prototype.onVertexMarkerDrag.call(this, e)
- },
-
- resize: function (e) {
- const radius = this.feature._latlng.distanceTo(e.latlng)
- this.feature.setRadius(radius)
- },
-
- onDrawingMouseDown: function (e) {
- L.Editable.PathEditor.prototype.onDrawingMouseDown.call(this, e)
- this._resizeLatLng.update(e.latlng)
- this.feature._latlng.update(e.latlng)
- this.connect()
- // Stop dragging map.
- e.originalEvent._simulated = false
- this.map.dragging._draggable._onUp(e.originalEvent)
- // Now transfer ongoing drag action to the radius handler.
- this._resizeLatLng.__vertex.dragging._draggable._onDown(e.originalEvent)
- },
-
- onDrawingMouseUp: function (e) {
- this.commitDrawing(e)
- e.originalEvent._simulated = false
- L.Editable.PathEditor.prototype.onDrawingMouseUp.call(this, e)
- },
-
- onDrawingMouseMove: function (e) {
- e.originalEvent._simulated = false
- L.Editable.PathEditor.prototype.onDrawingMouseMove.call(this, e)
- },
-
- onDrag: function (e) {
- L.Editable.PathEditor.prototype.onDrag.call(this, e)
- this.feature.dragging.updateLatLng(this._resizeLatLng)
- }
-
- })
-
- // 馃崅namespace Editable; 馃崅class EditableMixin
- // `EditableMixin` is included to `L.Polyline`, `L.Polygon`, `L.Rectangle`, `L.Circle`
- // and `L.Marker`. It adds some methods to them.
- // *When editing is enabled, the editor is accessible on the instance with the
- // `editor` property.*
- const EditableMixin = {
-
- createEditor: function (map) {
- map = map || this._map
- const tools = (this.options.editOptions || {}).editTools || map.editTools
- if (!tools) throw Error('Unable to detect Editable instance.')
- const Klass = this.options.editorClass || this.getEditorClass(tools)
- return new Klass(map, this, this.options.editOptions)
- },
-
- // 馃崅method enableEdit(map?: L.Map): this.editor
- // Enable editing, by creating an editor if not existing, and then calling `enable` on it.
- enableEdit: function (map) {
- if (!this.editor) this.createEditor(map)
- this.editor.enable()
- return this.editor
- },
-
- // 馃崅method editEnabled(): boolean
- // Return true if current instance has an editor attached, and this editor is enabled.
- editEnabled: function () {
- return this.editor && this.editor.enabled()
- },
-
- // 馃崅method disableEdit()
- // Disable editing, also remove the editor property reference.
- disableEdit: function () {
- if (this.editor) {
- this.editor.disable()
- delete this.editor
- }
- },
-
- // 馃崅method toggleEdit()
- // Enable or disable editing, according to current status.
- toggleEdit: function () {
- if (this.editEnabled()) {
- this.disableEdit()
- } else {
- this.enableEdit()
- }
- },
-
- _onEditableAdd: function () {
- if (this.editor) this.enableEdit()
- }
-
+ createCircle: function (latlng, options) {
+ return this.createLayer((options && options.circleClass) || this.options.circleClass, latlng, options)
}
- const PolylineMixin = {
+ })
- getEditorClass: function (tools) {
- return (tools && tools.options.polylineEditorClass) ? tools.options.polylineEditorClass : L.Editable.PolylineEditor
- },
+ L.extend(L.Editable, {
- shapeAt: function (latlng, latlngs) {
- // We can have those cases:
- // - latlngs are just a flat array of latlngs, use this
- // - latlngs is an array of arrays of latlngs, loop over
- let shape = null
- latlngs = latlngs || this._latlngs
- if (!latlngs.length) {
- return shape
- } else if (isFlat(latlngs) && this.isInLatLngs(latlng, latlngs)) {
- shape = latlngs
- } else {
- for (let i = 0; i < latlngs.length; i++) if (this.isInLatLngs(latlng, latlngs[i])) return latlngs[i]
- }
+ makeCancellable: function (e) {
+ e.cancel = function () {
+ e._cancelled = true
+ }
+ }
+
+ })
+
+ // 馃崅namespace Map; 馃崅class Map
+ // Leaflet.Editable add options and events to the `L.Map` object.
+ // See `Editable` events for the list of events fired on the Map.
+ // 馃崅example
+ //
+ // ```js
+ // let map = L.map('map', {
+ // editable: true,
+ // editOptions: {
+ // 鈥�
+ // }
+ // });
+ // ```
+ // 馃崅section Editable Map Options
+ L.Map.mergeOptions({
+
+ // 馃崅namespace Map
+ // 馃崅section Map Options
+ // 馃崅option EditToolsClass: class = L.Editable
+ // Class to be used as vertex, for path editing.
+ EditToolsClass: L.Editable,
+
+ // 馃崅option editable: boolean = false
+ // Whether to create a L.Editable instance at map init.
+ editable: false,
+
+ // 馃崅option editOptions: hash = {}
+ // Options to pass to L.Editable when instantiating.
+ editOptions: {}
+
+ })
+
+ L.Map.addInitHook(function () {
+ this.whenReady(function () {
+ if (this.options.editable) {
+ this.editTools = new this.options.EditToolsClass(this, this.options.editOptions)
+ }
+ })
+ })
+
+ L.Editable.VertexIcon = L.DivIcon.extend({
+
+ options: {
+ iconSize: new L.Point(8, 8)
+ }
+
+ })
+
+ L.Editable.TouchVertexIcon = L.Editable.VertexIcon.extend({
+
+ options: {
+ iconSize: new L.Point(20, 20)
+ }
+
+ })
+
+ // 馃崅namespace Editable; 馃崅class VertexMarker; Handler for dragging path vertices.
+ L.Editable.VertexMarker = L.Marker.extend({
+
+ options: {
+ draggable: true,
+ className: 'leaflet-vertex-icon leaflet-custom-icon'
+ },
+
+ // 馃崅section Public methods
+ // The marker used to handle path vertex. You will usually interact with a `VertexMarker`
+ // instance when listening for events like `editable:vertex:ctrlclick`.
+
+ initialize: function (latlng, latlngs, editor, options) {
+ // We don't use this._latlng, because on drag Leaflet replace it while
+ // we want to keep reference.
+ this.latlng = latlng
+ this.latlngs = latlngs
+ this.editor = editor
+ L.Marker.prototype.initialize.call(this, latlng, options)
+ this.options.icon = this.editor.tools.createVertexIcon({ className: this.options.className })
+ this.latlng.__vertex = this
+ this.editor.editLayer.addLayer(this)
+ this.setZIndexOffset(editor.tools._lastZIndex + 1)
+ },
+
+ onAdd: function (map) {
+ L.Marker.prototype.onAdd.call(this, map)
+ this.on('drag', this.onDrag)
+ this.on('dragstart', this.onDragStart)
+ this.on('dragend', this.onDragEnd)
+ this.on('mouseup', this.onMouseup)
+ this.on('click', this.onClick)
+ this.on('contextmenu', this.onContextMenu)
+ this.on('mousedown touchstart', this.onMouseDown)
+ this.on('mouseover', this.onMouseOver)
+ this.on('mouseout', this.onMouseOut)
+ this.addMiddleMarkers()
+ },
+
+ onRemove: function (map) {
+ if (this.middleMarker) this.middleMarker.delete()
+ delete this.latlng.__vertex
+ this.off('drag', this.onDrag)
+ this.off('dragstart', this.onDragStart)
+ this.off('dragend', this.onDragEnd)
+ this.off('mouseup', this.onMouseup)
+ this.off('click', this.onClick)
+ this.off('contextmenu', this.onContextMenu)
+ this.off('mousedown touchstart', this.onMouseDown)
+ this.off('mouseover', this.onMouseOver)
+ this.off('mouseout', this.onMouseOut)
+ L.Marker.prototype.onRemove.call(this, map)
+ },
+
+ onDrag: function (e) {
+ e.vertex = this
+ this.editor.onVertexMarkerDrag(e)
+ const iconPos = L.DomUtil.getPosition(this._icon)
+ const latlng = this._map.layerPointToLatLng(iconPos)
+ this.latlng.update(latlng)
+ this._latlng = this.latlng // Push back to Leaflet our reference.
+ this.editor.refresh()
+ if (this.middleMarker) this.middleMarker.updateLatLng()
+ const next = this.getNext()
+ if (next && next.middleMarker) next.middleMarker.updateLatLng()
+ },
+
+ onDragStart: function (e) {
+ e.vertex = this
+ this.editor.onVertexMarkerDragStart(e)
+ },
+
+ onDragEnd: function (e) {
+ e.vertex = this
+ this.editor.onVertexMarkerDragEnd(e)
+ },
+
+ onClick: function (e) {
+ e.vertex = this
+ this.editor.onVertexMarkerClick(e)
+ },
+
+ onMouseup: function (e) {
+ L.DomEvent.stop(e)
+ e.vertex = this
+ this.editor.map.fire('mouseup', e)
+ },
+
+ onContextMenu: function (e) {
+ e.vertex = this
+ this.editor.onVertexMarkerContextMenu(e)
+ },
+
+ onMouseDown: function (e) {
+ e.vertex = this
+ this.editor.onVertexMarkerMouseDown(e)
+ },
+
+ onMouseOver: function (e) {
+ e.vertex = this
+ this.editor.onVertexMarkerMouseOver(e)
+ },
+
+ onMouseOut: function (e) {
+ e.vertex = this
+ this.editor.onVertexMarkerMouseOut(e)
+ },
+
+ // 馃崅method delete()
+ // Delete a vertex and the related LatLng.
+ delete: function () {
+ const next = this.getNext() // Compute before changing latlng
+ this.latlngs.splice(this.getIndex(), 1)
+ this.editor.editLayer.removeLayer(this)
+ this.editor.onVertexDeleted({
+ latlng: this.latlng,
+ vertex: this
+ })
+ if (!this.latlngs.length) this.editor.deleteShape(this.latlngs)
+ if (next) next.resetMiddleMarker()
+ this.editor.refresh()
+ },
+
+ // 馃崅method getIndex(): int
+ // Get the index of the current vertex among others of the same LatLngs group.
+ getIndex: function () {
+ return this.latlngs.indexOf(this.latlng)
+ },
+
+ // 馃崅method getLastIndex(): int
+ // Get last vertex index of the LatLngs group of the current vertex.
+ getLastIndex: function () {
+ return this.latlngs.length - 1
+ },
+
+ // 馃崅method getPrevious(): VertexMarker
+ // Get the previous VertexMarker in the same LatLngs group.
+ getPrevious: function () {
+ if (this.latlngs.length < 2) return
+ const index = this.getIndex()
+ let previousIndex = index - 1
+ if (index === 0 && this.editor.CLOSED) previousIndex = this.getLastIndex()
+ const previous = this.latlngs[previousIndex]
+ if (previous) return previous.__vertex
+ },
+
+ // 馃崅method getNext(): VertexMarker
+ // Get the next VertexMarker in the same LatLngs group.
+ getNext: function () {
+ if (this.latlngs.length < 2) return
+ const index = this.getIndex()
+ let nextIndex = index + 1
+ if (index === this.getLastIndex() && this.editor.CLOSED) nextIndex = 0
+ const next = this.latlngs[nextIndex]
+ if (next) return next.__vertex
+ },
+
+ addMiddleMarker: function (previous) {
+ if (!this.editor.hasMiddleMarkers()) return
+ previous = previous || this.getPrevious()
+ if (previous && !this.middleMarker) this.middleMarker = this.editor.addMiddleMarker(previous, this, this.latlngs, this.editor)
+ },
+
+ addMiddleMarkers: function () {
+ if (!this.editor.hasMiddleMarkers()) return
+ const previous = this.getPrevious()
+ if (previous) this.addMiddleMarker(previous)
+ const next = this.getNext()
+ if (next) next.resetMiddleMarker()
+ },
+
+ resetMiddleMarker: function () {
+ if (this.middleMarker) this.middleMarker.delete()
+ this.addMiddleMarker()
+ },
+
+ // 馃崅method split()
+ // Split the vertex LatLngs group at its index, if possible.
+ split: function () {
+ if (!this.editor.splitShape) return // Only for PolylineEditor
+ this.editor.splitShape(this.latlngs, this.getIndex())
+ },
+
+ // 馃崅method continue()
+ // Continue the vertex LatLngs from this vertex. Only active for first and last vertices of a Polyline.
+ continue: function () {
+ if (!this.editor.continueBackward) return // Only for PolylineEditor
+ const index = this.getIndex()
+ if (index === 0) {
+ this.editor.continueBackward(this.latlngs)
+ } else if (index === this.getLastIndex()) this.editor.continueForward(this.latlngs)
+ }
+
+ })
+
+ L.Editable.mergeOptions({
+
+ // 馃崅namespace Editable
+ // 馃崅option VertexMarkerClass: class = VertexMarker
+ // Class to be used as vertex, for path editing.
+ VertexMarkerClass: L.Editable.VertexMarker
+
+ })
+
+ L.Editable.MiddleMarker = L.Marker.extend({
+
+ options: {
+ opacity: 0.5,
+ className: 'leaflet-div-icon leaflet-middle-icon',
+ draggable: true
+ },
+
+ initialize: function (left, right, latlngs, editor, options) {
+ this.left = left
+ this.right = right
+ this.editor = editor
+ this.latlngs = latlngs
+ L.Marker.prototype.initialize.call(this, this.computeLatLng(), options)
+ this._opacity = this.options.opacity
+ this.options.icon = this.editor.tools.createVertexIcon({ className: this.options.className })
+ this.editor.editLayer.addLayer(this)
+ this.setVisibility()
+ },
+
+ setVisibility: function () {
+ const leftPoint = this._map.latLngToContainerPoint(this.left.latlng)
+ const rightPoint = this._map.latLngToContainerPoint(this.right.latlng)
+ const size = L.point(this.options.icon.options.iconSize)
+ if (leftPoint.distanceTo(rightPoint) < size.x * 3) {
+ this.hide()
+ } else {
+ this.show()
+ }
+ },
+
+ show: function () {
+ this.setOpacity(this._opacity)
+ },
+
+ hide: function () {
+ this.setOpacity(0)
+ },
+
+ updateLatLng: function () {
+ this.setLatLng(this.computeLatLng())
+ this.setVisibility()
+ },
+
+ computeLatLng: function () {
+ const leftPoint = this.editor.map.latLngToContainerPoint(this.left.latlng)
+ const rightPoint = this.editor.map.latLngToContainerPoint(this.right.latlng)
+ const y = (leftPoint.y + rightPoint.y) / 2
+ const x = (leftPoint.x + rightPoint.x) / 2
+ return this.editor.map.containerPointToLatLng([x, y])
+ },
+
+ onAdd: function (map) {
+ L.Marker.prototype.onAdd.call(this, map)
+ L.DomEvent.on(this._icon, 'mousedown touchstart', this.onMouseDown, this)
+ map.on('zoomend', this.setVisibility, this)
+ },
+
+ onRemove: function (map) {
+ delete this.right.middleMarker
+ L.DomEvent.off(this._icon, 'mousedown touchstart', this.onMouseDown, this)
+ map.off('zoomend', this.setVisibility, this)
+ L.Marker.prototype.onRemove.call(this, map)
+ },
+
+ onMouseDown: function (e) {
+ const iconPos = L.DomUtil.getPosition(this._icon)
+ const latlng = this.editor.map.layerPointToLatLng(iconPos)
+ e = {
+ originalEvent: e,
+ latlng: latlng
+ }
+ if (this.options.opacity === 0) return
+ L.Editable.makeCancellable(e)
+ this.editor.onMiddleMarkerMouseDown(e)
+ if (e._cancelled) return
+ this.latlngs.splice(this.index(), 0, e.latlng)
+ this.editor.refresh()
+ const icon = this._icon
+ const marker = this.editor.addVertexMarker(e.latlng, this.latlngs)
+ this.editor.onNewVertex(marker)
+ /* Hack to workaround browser not firing touchend when element is no more on DOM */
+ const parent = marker._icon.parentNode
+ parent.removeChild(marker._icon)
+ marker._icon = icon
+ parent.appendChild(marker._icon)
+ marker._initIcon()
+ marker._initInteraction()
+ marker.setOpacity(1)
+ /* End hack */
+ // Transfer ongoing dragging to real marker
+ L.Draggable._dragging = false
+ marker.dragging._draggable._onDown(e.originalEvent)
+ this.delete()
+ },
+
+ delete: function () {
+ this.editor.editLayer.removeLayer(this)
+ },
+
+ index: function () {
+ return this.latlngs.indexOf(this.right.latlng)
+ }
+
+ })
+
+ L.Editable.mergeOptions({
+
+ // 馃崅namespace Editable
+ // 馃崅option MiddleMarkerClass: class = VertexMarker
+ // Class to be used as middle vertex, pulled by the user to create a new point in the middle of a path.
+ MiddleMarkerClass: L.Editable.MiddleMarker
+
+ })
+
+ // 馃崅namespace Editable; 馃崅class BaseEditor; 馃崅aka L.Editable.BaseEditor
+ // When editing a feature (Marker, Polyline鈥�), an editor is attached to it. This
+ // editor basically knows how to handle the edition.
+ L.Editable.BaseEditor = L.Handler.extend({
+
+ initialize: function (map, feature, options) {
+ L.setOptions(this, options)
+ this.map = map
+ this.feature = feature
+ this.feature.editor = this
+ this.editLayer = new L.LayerGroup()
+ this.tools = this.options.editTools || map.editTools
+ },
+
+ // 馃崅method enable(): this
+ // Set up the drawing tools for the feature to be editable.
+ addHooks: function () {
+ if (this.isConnected()) {
+ this.onFeatureAdd()
+ } else {
+ this.feature.once('add', this.onFeatureAdd, this)
+ }
+ this.onEnable()
+ this.feature.on(this._getEvents(), this)
+ },
+
+ // 馃崅method disable(): this
+ // Remove the drawing tools for the feature.
+ removeHooks: function () {
+ this.feature.off(this._getEvents(), this)
+ if (this.feature.dragging) this.feature.dragging.disable()
+ this.editLayer.clearLayers()
+ this.tools.editLayer.removeLayer(this.editLayer)
+ this.onDisable()
+ if (this._drawing) this.cancelDrawing()
+ },
+
+ // 馃崅method drawing(): boolean
+ // Return true if any drawing action is ongoing with this editor.
+ drawing: function () {
+ return !!this._drawing
+ },
+
+ reset: function () {
+ },
+
+ onFeatureAdd: function () {
+ this.tools.editLayer.addLayer(this.editLayer)
+ if (this.feature.dragging) this.feature.dragging.enable()
+ },
+
+ hasMiddleMarkers: function () {
+ return !this.options.skipMiddleMarkers && !this.tools.options.skipMiddleMarkers
+ },
+
+ fireAndForward: function (type, e) {
+ e = e || {}
+ e.layer = this.feature
+ this.feature.fire(type, e)
+ this.tools.fireAndForward(type, e)
+ },
+
+ onEnable: function () {
+ // 馃崅namespace Editable
+ // 馃崅event editable:enable: Event
+ // Fired when an existing feature is ready to be edited.
+ this.fireAndForward('editable:enable')
+ },
+
+ onDisable: function () {
+ // 馃崅namespace Editable
+ // 馃崅event editable:disable: Event
+ // Fired when an existing feature is not ready anymore to be edited.
+ this.fireAndForward('editable:disable')
+ },
+
+ onEditing: function () {
+ // 馃崅namespace Editable
+ // 馃崅event editable:editing: Event
+ // Fired as soon as any change is made to the feature geometry.
+ this.fireAndForward('editable:editing')
+ },
+
+ onStartDrawing: function () {
+ // 馃崅namespace Editable
+ // 馃崅section Drawing events
+ // 馃崅event editable:drawing:start: Event
+ // Fired when a feature is to be drawn.
+ this.fireAndForward('editable:drawing:start')
+ },
+
+ onEndDrawing: function () {
+ // 馃崅namespace Editable
+ // 馃崅section Drawing events
+ // 馃崅event editable:drawing:end: Event
+ // Fired when a feature is not drawn anymore.
+ this.fireAndForward('editable:drawing:end')
+ },
+
+ onCancelDrawing: function () {
+ // 馃崅namespace Editable
+ // 馃崅section Drawing events
+ // 馃崅event editable:drawing:cancel: Event
+ // Fired when user cancel drawing while a feature is being drawn.
+ this.fireAndForward('editable:drawing:cancel')
+ },
+
+ onCommitDrawing: function (e) {
+ // 馃崅namespace Editable
+ // 馃崅section Drawing events
+ // 馃崅event editable:drawing:commit: Event
+ // Fired when user finish drawing a feature.
+ this.fireAndForward('editable:drawing:commit', e)
+ },
+
+ onDrawingMouseDown: function (e) {
+ // 馃崅namespace Editable
+ // 馃崅section Drawing events
+ // 馃崅event editable:drawing:mousedown: Event
+ // Fired when user `mousedown` while drawing.
+ this.fireAndForward('editable:drawing:mousedown', e)
+ },
+
+ onDrawingMouseUp: function (e) {
+ // 馃崅namespace Editable
+ // 馃崅section Drawing events
+ // 馃崅event editable:drawing:mouseup: Event
+ // Fired when user `mouseup` while drawing.
+ this.fireAndForward('editable:drawing:mouseup', e)
+ },
+
+ startDrawing: function () {
+ if (!this._drawing) this._drawing = L.Editable.FORWARD
+ this.tools.registerForDrawing(this)
+ this.onStartDrawing()
+ },
+
+ commitDrawing: function (e) {
+ this.onCommitDrawing(e)
+ this.endDrawing()
+ },
+
+ cancelDrawing: function () {
+ // If called during a vertex drag, the vertex will be removed before
+ // the mouseup fires on it. This is a workaround. Maybe better fix is
+ // To have L.Draggable reset it's status on disable (Leaflet side).
+ L.Draggable._dragging = false
+ this.onCancelDrawing()
+ this.endDrawing()
+ },
+
+ endDrawing: function () {
+ this._drawing = false
+ this.tools.unregisterForDrawing(this)
+ this.onEndDrawing()
+ },
+
+ onDrawingClick: function (e) {
+ if (!this.drawing()) return
+ L.Editable.makeCancellable(e)
+ // 馃崅namespace Editable
+ // 馃崅section Drawing events
+ // 馃崅event editable:drawing:click: CancelableEvent
+ // Fired when user `click` while drawing, before any internal action is being processed.
+ this.fireAndForward('editable:drawing:click', e)
+ if (e._cancelled) return
+ if (!this.isConnected()) this.connect(e)
+ this.processDrawingClick(e)
+ },
+
+ isConnected: function () {
+ return this.map.hasLayer(this.feature)
+ },
+
+ connect: function () {
+ this.tools.connectCreatedToMap(this.feature)
+ this.tools.editLayer.addLayer(this.editLayer)
+ },
+
+ onMove: function (e) {
+ // 馃崅namespace Editable
+ // 馃崅section Drawing events
+ // 馃崅event editable:drawing:move: Event
+ // Fired when `move` mouse while drawing, while dragging a marker, and while dragging a vertex.
+ this.fireAndForward('editable:drawing:move', e)
+ },
+
+ onDrawingMouseMove: function (e) {
+ this.onMove(e)
+ },
+
+ _getEvents: function () {
+ return {
+ dragstart: this.onDragStart,
+ drag: this.onDrag,
+ dragend: this.onDragEnd,
+ remove: this.disable
+ }
+ },
+
+ onDragStart: function (e) {
+ this.onEditing()
+ // 馃崅namespace Editable
+ // 馃崅event editable:dragstart: Event
+ // Fired before a path feature is dragged.
+ this.fireAndForward('editable:dragstart', e)
+ },
+
+ onDrag: function (e) {
+ this.onMove(e)
+ // 馃崅namespace Editable
+ // 馃崅event editable:drag: Event
+ // Fired when a path feature is being dragged.
+ this.fireAndForward('editable:drag', e)
+ },
+
+ onDragEnd: function (e) {
+ // 馃崅namespace Editable
+ // 馃崅event editable:dragend: Event
+ // Fired after a path feature has been dragged.
+ this.fireAndForward('editable:dragend', e)
+ }
+
+ })
+
+ // 馃崅namespace Editable; 馃崅class MarkerEditor; 馃崅aka L.Editable.MarkerEditor
+ // 馃崅inherits BaseEditor
+ // Editor for Marker.
+ L.Editable.MarkerEditor = L.Editable.BaseEditor.extend({
+
+ onDrawingMouseMove: function (e) {
+ L.Editable.BaseEditor.prototype.onDrawingMouseMove.call(this, e)
+ if (this._drawing) this.feature.setLatLng(e.latlng)
+ },
+
+ processDrawingClick: function (e) {
+ // 馃崅namespace Editable
+ // 馃崅section Drawing events
+ // 馃崅event editable:drawing:clicked: Event
+ // Fired when user `click` while drawing, after all internal actions.
+ this.fireAndForward('editable:drawing:clicked', e)
+ this.commitDrawing(e)
+ },
+
+ connect: function (e) {
+ // On touch, the latlng has not been updated because there is
+ // no mousemove.
+ if (e) this.feature._latlng = e.latlng
+ L.Editable.BaseEditor.prototype.connect.call(this, e)
+ }
+
+ })
+
+ // 馃崅namespace Editable; 馃崅class PathEditor; 馃崅aka L.Editable.PathEditor
+ // 馃崅inherits BaseEditor
+ // Base class for all path editors.
+ L.Editable.PathEditor = L.Editable.BaseEditor.extend({
+
+ CLOSED: false,
+ MIN_VERTEX: 2,
+
+ addHooks: function () {
+ L.Editable.BaseEditor.prototype.addHooks.call(this)
+ if (this.feature) this.initVertexMarkers()
+ return this
+ },
+
+ initVertexMarkers: function (latlngs) {
+ if (!this.enabled()) return
+ latlngs = latlngs || this.getLatLngs()
+ if (isFlat(latlngs)) {
+ this.addVertexMarkers(latlngs)
+ } else {
+ for (let i = 0; i < latlngs.length; i++) this.initVertexMarkers(latlngs[i])
+ }
+ },
+
+ getLatLngs: function () {
+ return this.feature.getLatLngs()
+ },
+
+ // 馃崅method reset()
+ // Rebuild edit elements (Vertex, MiddleMarker, etc.).
+ reset: function () {
+ this.editLayer.clearLayers()
+ this.initVertexMarkers()
+ },
+
+ addVertexMarker: function (latlng, latlngs) {
+ return new this.tools.options.VertexMarkerClass(latlng, latlngs, this)
+ },
+
+ onNewVertex: function (vertex) {
+ // 馃崅namespace Editable
+ // 馃崅section Vertex events
+ // 馃崅event editable:vertex:new: VertexEvent
+ // Fired when a new vertex is created.
+ this.fireAndForward('editable:vertex:new', {
+ latlng: vertex.latlng,
+ vertex: vertex
+ })
+ },
+
+ addVertexMarkers: function (latlngs) {
+ for (let i = 0; i < latlngs.length; i++) {
+ this.addVertexMarker(latlngs[i], latlngs)
+ }
+ },
+
+ refreshVertexMarkers: function (latlngs) {
+ latlngs = latlngs || this.getDefaultLatLngs()
+ for (let i = 0; i < latlngs.length; i++) {
+ latlngs[i].__vertex.update()
+ }
+ },
+
+ addMiddleMarker: function (left, right, latlngs) {
+ return new this.tools.options.MiddleMarkerClass(left, right, latlngs, this)
+ },
+
+ onVertexMarkerClick: function (e) {
+ L.Editable.makeCancellable(e)
+ // 馃崅namespace Editable
+ // 馃崅section Vertex events
+ // 馃崅event editable:vertex:click: CancelableVertexEvent
+ // Fired when a `click` is issued on a vertex, before any internal action is being processed.
+ this.fireAndForward('editable:vertex:click', e)
+ if (e._cancelled) return
+ if (this.tools.drawing() && this.tools._drawingEditor !== this) return
+ const index = e.vertex.getIndex()
+ let commit
+ if (e.originalEvent.ctrlKey) {
+ this.onVertexMarkerCtrlClick(e)
+ } else if (e.originalEvent.altKey) {
+ this.onVertexMarkerAltClick(e)
+ } else if (e.originalEvent.shiftKey) {
+ this.onVertexMarkerShiftClick(e)
+ } else if (e.originalEvent.metaKey) {
+ this.onVertexMarkerMetaKeyClick(e)
+ } else if (index === e.vertex.getLastIndex() && this._drawing === L.Editable.FORWARD) {
+ if (index >= this.MIN_VERTEX - 1) commit = true
+ } else if (index === 0 && this._drawing === L.Editable.BACKWARD && this._drawnLatLngs.length >= this.MIN_VERTEX) {
+ commit = true
+ } else if (index === 0 && this._drawing === L.Editable.FORWARD && this._drawnLatLngs.length >= this.MIN_VERTEX && this.CLOSED) {
+ commit = true // Allow to close on first point also for polygons
+ } else {
+ this.onVertexRawMarkerClick(e)
+ }
+ // 馃崅namespace Editable
+ // 馃崅section Vertex events
+ // 馃崅event editable:vertex:clicked: VertexEvent
+ // Fired when a `click` is issued on a vertex, after all internal actions.
+ this.fireAndForward('editable:vertex:clicked', e)
+ if (commit) this.commitDrawing(e)
+ },
+
+ onVertexRawMarkerClick: function (e) {
+ // 馃崅namespace Editable
+ // 馃崅section Vertex events
+ // 馃崅event editable:vertex:rawclick: CancelableVertexEvent
+ // Fired when a `click` is issued on a vertex without any special key and without being in drawing mode.
+ this.fireAndForward('editable:vertex:rawclick', e)
+ if (e._cancelled) return
+ if (!this.vertexCanBeDeleted(e.vertex)) return
+ e.vertex.delete()
+ },
+
+ vertexCanBeDeleted: function (vertex) {
+ return vertex.latlngs.length > this.MIN_VERTEX
+ },
+
+ onVertexDeleted: function (e) {
+ // 馃崅namespace Editable
+ // 馃崅section Vertex events
+ // 馃崅event editable:vertex:deleted: VertexEvent
+ // Fired after a vertex has been deleted by user.
+ this.fireAndForward('editable:vertex:deleted', e)
+ },
+
+ onVertexMarkerCtrlClick: function (e) {
+ // 馃崅namespace Editable
+ // 馃崅section Vertex events
+ // 馃崅event editable:vertex:ctrlclick: VertexEvent
+ // Fired when a `click` with `ctrlKey` is issued on a vertex.
+ this.fireAndForward('editable:vertex:ctrlclick', e)
+ },
+
+ onVertexMarkerShiftClick: function (e) {
+ // 馃崅namespace Editable
+ // 馃崅section Vertex events
+ // 馃崅event editable:vertex:shiftclick: VertexEvent
+ // Fired when a `click` with `shiftKey` is issued on a vertex.
+ this.fireAndForward('editable:vertex:shiftclick', e)
+ },
+
+ onVertexMarkerMetaKeyClick: function (e) {
+ // 馃崅namespace Editable
+ // 馃崅section Vertex events
+ // 馃崅event editable:vertex:metakeyclick: VertexEvent
+ // Fired when a `click` with `metaKey` is issued on a vertex.
+ this.fireAndForward('editable:vertex:metakeyclick', e)
+ },
+
+ onVertexMarkerAltClick: function (e) {
+ // 馃崅namespace Editable
+ // 馃崅section Vertex events
+ // 馃崅event editable:vertex:altclick: VertexEvent
+ // Fired when a `click` with `altKey` is issued on a vertex.
+ this.fireAndForward('editable:vertex:altclick', e)
+ },
+
+ onVertexMarkerContextMenu: function (e) {
+ // 馃崅namespace Editable
+ // 馃崅section Vertex events
+ // 馃崅event editable:vertex:contextmenu: VertexEvent
+ // Fired when a `contextmenu` is issued on a vertex.
+ this.fireAndForward('editable:vertex:contextmenu', e)
+ },
+
+ onVertexMarkerMouseDown: function (e) {
+ // 馃崅namespace Editable
+ // 馃崅section Vertex events
+ // 馃崅event editable:vertex:mousedown: VertexEvent
+ // Fired when user `mousedown` a vertex.
+ this.fireAndForward('editable:vertex:mousedown', e)
+ },
+
+ onVertexMarkerMouseOver: function (e) {
+ // 馃崅namespace Editable
+ // 馃崅section Vertex events
+ // 馃崅event editable:vertex:mouseover: VertexEvent
+ // Fired when a user's mouse enters the vertex
+ this.fireAndForward('editable:vertex:mouseover', e)
+ },
+
+ onVertexMarkerMouseOut: function (e) {
+ // 馃崅namespace Editable
+ // 馃崅section Vertex events
+ // 馃崅event editable:vertex:mouseout: VertexEvent
+ // Fired when a user's mouse leaves the vertex
+ this.fireAndForward('editable:vertex:mouseout', e)
+ },
+
+ onMiddleMarkerMouseDown: function (e) {
+ // 馃崅namespace Editable
+ // 馃崅section MiddleMarker events
+ // 馃崅event editable:middlemarker:mousedown: VertexEvent
+ // Fired when user `mousedown` a middle marker.
+ this.fireAndForward('editable:middlemarker:mousedown', e)
+ },
+
+ onVertexMarkerDrag: function (e) {
+ this.onMove(e)
+ if (this.feature._bounds) this.extendBounds(e)
+ // 馃崅namespace Editable
+ // 馃崅section Vertex events
+ // 馃崅event editable:vertex:drag: VertexEvent
+ // Fired when a vertex is dragged by user.
+ this.fireAndForward('editable:vertex:drag', e)
+ },
+
+ onVertexMarkerDragStart: function (e) {
+ // 馃崅namespace Editable
+ // 馃崅section Vertex events
+ // 馃崅event editable:vertex:dragstart: VertexEvent
+ // Fired before a vertex is dragged by user.
+ this.fireAndForward('editable:vertex:dragstart', e)
+ },
+
+ onVertexMarkerDragEnd: function (e) {
+ // 馃崅namespace Editable
+ // 馃崅section Vertex events
+ // 馃崅event editable:vertex:dragend: VertexEvent
+ // Fired after a vertex is dragged by user.
+ this.fireAndForward('editable:vertex:dragend', e)
+ },
+
+ setDrawnLatLngs: function (latlngs) {
+ this._drawnLatLngs = latlngs || this.getDefaultLatLngs()
+ },
+
+ startDrawing: function () {
+ if (!this._drawnLatLngs) this.setDrawnLatLngs()
+ L.Editable.BaseEditor.prototype.startDrawing.call(this)
+ },
+
+ startDrawingForward: function () {
+ this.startDrawing()
+ },
+
+ endDrawing: function () {
+ this.tools.detachForwardLineGuide()
+ this.tools.detachBackwardLineGuide()
+ if (this._drawnLatLngs && this._drawnLatLngs.length < this.MIN_VERTEX) this.deleteShape(this._drawnLatLngs)
+ L.Editable.BaseEditor.prototype.endDrawing.call(this)
+ delete this._drawnLatLngs
+ },
+
+ addLatLng: function (latlng) {
+ if (this._drawing === L.Editable.FORWARD) {
+ this._drawnLatLngs.push(latlng)
+ } else {
+ this._drawnLatLngs.unshift(latlng)
+ }
+ this.feature._bounds.extend(latlng)
+ const vertex = this.addVertexMarker(latlng, this._drawnLatLngs)
+ this.onNewVertex(vertex)
+ this.refresh()
+ },
+
+ newPointForward: function (latlng) {
+ this.addLatLng(latlng)
+ this.tools.attachForwardLineGuide()
+ this.tools.anchorForwardLineGuide(latlng)
+ },
+
+ newPointBackward: function (latlng) {
+ this.addLatLng(latlng)
+ this.tools.anchorBackwardLineGuide(latlng)
+ },
+
+ // 馃崅namespace PathEditor
+ // 馃崅method push()
+ // Programmatically add a point while drawing.
+ push: function (latlng) {
+ if (!latlng) return console.error('L.Editable.PathEditor.push expect a valid latlng as parameter')
+ if (this._drawing === L.Editable.FORWARD) {
+ this.newPointForward(latlng)
+ } else {
+ this.newPointBackward(latlng)
+ }
+ },
+
+ removeLatLng: function (latlng) {
+ latlng.__vertex.delete()
+ this.refresh()
+ },
+
+ // 馃崅method pop(): L.LatLng or null
+ // Programmatically remove last point (if any) while drawing.
+ pop: function () {
+ if (this._drawnLatLngs.length <= 1) return
+ let latlng
+ if (this._drawing === L.Editable.FORWARD) {
+ latlng = this._drawnLatLngs[this._drawnLatLngs.length - 1]
+ } else {
+ latlng = this._drawnLatLngs[0]
+ }
+ this.removeLatLng(latlng)
+ if (this._drawing === L.Editable.FORWARD) {
+ this.tools.anchorForwardLineGuide(this._drawnLatLngs[this._drawnLatLngs.length - 1])
+ } else {
+ this.tools.anchorForwardLineGuide(this._drawnLatLngs[0])
+ }
+ return latlng
+ },
+
+ processDrawingClick: function (e) {
+ if (e.vertex && e.vertex.editor === this) return
+ if (this._drawing === L.Editable.FORWARD) {
+ this.newPointForward(e.latlng)
+ } else {
+ this.newPointBackward(e.latlng)
+ }
+ this.fireAndForward('editable:drawing:clicked', e)
+ },
+
+ onDrawingMouseMove: function (e) {
+ L.Editable.BaseEditor.prototype.onDrawingMouseMove.call(this, e)
+ if (this._drawing) {
+ this.tools.moveForwardLineGuide(e.latlng)
+ this.tools.moveBackwardLineGuide(e.latlng)
+ }
+ },
+
+ refresh: function () {
+ this.feature.redraw()
+ this.onEditing()
+ },
+
+ // 馃崅namespace PathEditor
+ // 馃崅method newShape(latlng?: L.LatLng)
+ // Add a new shape (Polyline, Polygon) in a multi, and setup up drawing tools to draw it;
+ // if optional `latlng` is given, start a path at this point.
+ newShape: function (latlng) {
+ const shape = this.addNewEmptyShape()
+ if (!shape) return
+ this.setDrawnLatLngs(shape[0] || shape) // Polygon or polyline
+ this.startDrawingForward()
+ // 馃崅namespace Editable
+ // 馃崅section Shape events
+ // 馃崅event editable:shape:new: ShapeEvent
+ // Fired when a new shape is created in a multi (Polygon or Polyline).
+ this.fireAndForward('editable:shape:new', { shape: shape })
+ if (latlng) this.newPointForward(latlng)
+ },
+
+ deleteShape: function (shape, latlngs) {
+ const e = { shape: shape }
+ L.Editable.makeCancellable(e)
+ // 馃崅namespace Editable
+ // 馃崅section Shape events
+ // 馃崅event editable:shape:delete: CancelableShapeEvent
+ // Fired before a new shape is deleted in a multi (Polygon or Polyline).
+ this.fireAndForward('editable:shape:delete', e)
+ if (e._cancelled) return
+ shape = this._deleteShape(shape, latlngs)
+ if (this.ensureNotFlat) this.ensureNotFlat() // Polygon.
+ this.feature.setLatLngs(this.getLatLngs()) // Force bounds reset.
+ this.refresh()
+ this.reset()
+ // 馃崅namespace Editable
+ // 馃崅section Shape events
+ // 馃崅event editable:shape:deleted: ShapeEvent
+ // Fired after a new shape is deleted in a multi (Polygon or Polyline).
+ this.fireAndForward('editable:shape:deleted', { shape: shape })
+ return shape
+ },
+
+ _deleteShape: function (shape, latlngs) {
+ latlngs = latlngs || this.getLatLngs()
+ if (!latlngs.length) return
+ const self = this
+ const inplaceDelete = function (latlngs, shape) {
+ // Called when deleting a flat latlngs
+ shape = latlngs.splice(0, Number.MAX_VALUE)
return shape
- },
+ }
+ const spliceDelete = function (latlngs, shape) {
+ // Called when removing a latlngs inside an array
+ latlngs.splice(latlngs.indexOf(shape), 1)
+ if (!latlngs.length) self._deleteShape(latlngs)
+ return shape
+ }
+ if (latlngs === shape) return inplaceDelete(latlngs, shape)
+ for (let i = 0; i < latlngs.length; i++) {
+ if (latlngs[i] === shape) {
+ return spliceDelete(latlngs, shape)
+ } else if (latlngs[i].indexOf(shape) !== -1) return spliceDelete(latlngs[i], shape)
+ }
+ },
- isInLatLngs: function (l, latlngs) {
- if (!latlngs) return false
- let i, k, len
- let part = []
- const w = this._clickTolerance()
- this._projectLatlngs(latlngs, part, this._pxBounds)
- part = part[0]
- const p = this._map.latLngToLayerPoint(l)
+ // 馃崅namespace PathEditor
+ // 馃崅method deleteShapeAt(latlng: L.LatLng): Array
+ // Remove a path shape at the given `latlng`.
+ deleteShapeAt: function (latlng) {
+ const shape = this.feature.shapeAt(latlng)
+ if (shape) return this.deleteShape(shape)
+ },
- if (!this._pxBounds.contains(p)) {
- return false
- }
- for (i = 1, len = part.length, k = 0; i < len; k = i++) {
- if (L.LineUtil.pointToSegmentDistance(p, part[k], part[i]) <= w) {
- return true
- }
- }
+ // 馃崅method appendShape(shape: Array)
+ // Append a new shape to the Polygon or Polyline.
+ appendShape: function (shape) {
+ this.insertShape(shape)
+ },
+
+ // 馃崅method prependShape(shape: Array)
+ // Prepend a new shape to the Polygon or Polyline.
+ prependShape: function (shape) {
+ this.insertShape(shape, 0)
+ },
+
+ // 馃崅method insertShape(shape: Array, index: int)
+ // Insert a new shape to the Polygon or Polyline at given index (default is to append).
+ insertShape: function (shape, index) {
+ this.ensureMulti()
+ shape = this.formatShape(shape)
+ if (typeof index === 'undefined') index = this.feature._latlngs.length
+ this.feature._latlngs.splice(index, 0, shape)
+ this.feature.redraw()
+ if (this._enabled) this.reset()
+ },
+
+ extendBounds: function (e) {
+ this.feature._bounds.extend(e.vertex.latlng)
+ },
+
+ onDragStart: function (e) {
+ this.editLayer.clearLayers()
+ L.Editable.BaseEditor.prototype.onDragStart.call(this, e)
+ },
+
+ onDragEnd: function (e) {
+ this.initVertexMarkers()
+ L.Editable.BaseEditor.prototype.onDragEnd.call(this, e)
+ }
+
+ })
+
+ // 馃崅namespace Editable; 馃崅class PolylineEditor; 馃崅aka L.Editable.PolylineEditor
+ // 馃崅inherits PathEditor
+ L.Editable.PolylineEditor = L.Editable.PathEditor.extend({
+
+ startDrawingBackward: function () {
+ this._drawing = L.Editable.BACKWARD
+ this.startDrawing()
+ },
+
+ // 馃崅method continueBackward(latlngs?: Array)
+ // Set up drawing tools to continue the line backward.
+ continueBackward: function (latlngs) {
+ if (this.drawing()) return
+ latlngs = latlngs || this.getDefaultLatLngs()
+ this.setDrawnLatLngs(latlngs)
+ if (latlngs.length > 0) {
+ this.tools.attachBackwardLineGuide()
+ this.tools.anchorBackwardLineGuide(latlngs[0])
+ }
+ this.startDrawingBackward()
+ },
+
+ // 馃崅method continueForward(latlngs?: Array)
+ // Set up drawing tools to continue the line forward.
+ continueForward: function (latlngs) {
+ if (this.drawing()) return
+ latlngs = latlngs || this.getDefaultLatLngs()
+ this.setDrawnLatLngs(latlngs)
+ if (latlngs.length > 0) {
+ this.tools.attachForwardLineGuide()
+ this.tools.anchorForwardLineGuide(latlngs[latlngs.length - 1])
+ }
+ this.startDrawingForward()
+ },
+
+ getDefaultLatLngs: function (latlngs) {
+ latlngs = latlngs || this.feature._latlngs
+ if (!latlngs.length || latlngs[0] instanceof L.LatLng) {
+ return latlngs
+ } else {
+ return this.getDefaultLatLngs(latlngs[0])
+ }
+ },
+
+ ensureMulti: function () {
+ if (this.feature._latlngs.length && isFlat(this.feature._latlngs)) {
+ this.feature._latlngs = [this.feature._latlngs]
+ }
+ },
+
+ addNewEmptyShape: function () {
+ if (this.feature._latlngs.length) {
+ const shape = []
+ this.appendShape(shape)
+ return shape
+ } else {
+ return this.feature._latlngs
+ }
+ },
+
+ formatShape: function (shape) {
+ if (isFlat(shape)) {
+ return shape
+ } else if (shape[0]) return this.formatShape(shape[0])
+ },
+
+ // 馃崅method splitShape(latlngs?: Array, index: int)
+ // Split the given `latlngs` shape at index `index` and integrate new shape in instance `latlngs`.
+ splitShape: function (shape, index) {
+ if (!index || index >= shape.length - 1) return
+ this.ensureMulti()
+ const shapeIndex = this.feature._latlngs.indexOf(shape)
+ if (shapeIndex === -1) return
+ const first = shape.slice(0, index + 1)
+ const second = shape.slice(index)
+ // We deal with reference, we don't want twice the same latlng around.
+ second[0] = L.latLng(second[0].lat, second[0].lng, second[0].alt)
+ this.feature._latlngs.splice(shapeIndex, 1, first, second)
+ this.refresh()
+ this.reset()
+ }
+
+ })
+
+ // 馃崅namespace Editable; 馃崅class PolygonEditor; 馃崅aka L.Editable.PolygonEditor
+ // 馃崅inherits PathEditor
+ L.Editable.PolygonEditor = L.Editable.PathEditor.extend({
+
+ CLOSED: true,
+ MIN_VERTEX: 3,
+
+ newPointForward: function (latlng) {
+ L.Editable.PathEditor.prototype.newPointForward.call(this, latlng)
+ if (!this.tools.backwardLineGuide._latlngs.length) this.tools.anchorBackwardLineGuide(latlng)
+ if (this._drawnLatLngs.length === 2) this.tools.attachBackwardLineGuide()
+ },
+
+ addNewEmptyHole: function (latlng) {
+ this.ensureNotFlat()
+ const latlngs = this.feature.shapeAt(latlng)
+ if (!latlngs) return
+ const holes = []
+ latlngs.push(holes)
+ return holes
+ },
+
+ // 馃崅method newHole(latlng?: L.LatLng, index: int)
+ // Set up drawing tools for creating a new hole on the Polygon. If the `latlng` param is given, a first point is created.
+ newHole: function (latlng) {
+ const holes = this.addNewEmptyHole(latlng)
+ if (!holes) return
+ this.setDrawnLatLngs(holes)
+ this.startDrawingForward()
+ if (latlng) this.newPointForward(latlng)
+ },
+
+ addNewEmptyShape: function () {
+ if (this.feature._latlngs.length && this.feature._latlngs[0].length) {
+ const shape = []
+ this.appendShape(shape)
+ return shape
+ } else {
+ return this.feature._latlngs
+ }
+ },
+
+ ensureMulti: function () {
+ if (this.feature._latlngs.length && isFlat(this.feature._latlngs[0])) {
+ this.feature._latlngs = [this.feature._latlngs]
+ }
+ },
+
+ ensureNotFlat: function () {
+ if (!this.feature._latlngs.length || isFlat(this.feature._latlngs)) this.feature._latlngs = [this.feature._latlngs]
+ },
+
+ vertexCanBeDeleted: function (vertex) {
+ const parent = this.feature.parentShape(vertex.latlngs)
+ const idx = L.Util.indexOf(parent, vertex.latlngs)
+ if (idx > 0) return true // Holes can be totally deleted without removing the layer itself.
+ return L.Editable.PathEditor.prototype.vertexCanBeDeleted.call(this, vertex)
+ },
+
+ getDefaultLatLngs: function () {
+ if (!this.feature._latlngs.length) this.feature._latlngs.push([])
+ return this.feature._latlngs[0]
+ },
+
+ formatShape: function (shape) {
+ // [[1, 2], [3, 4]] => must be nested
+ // [] => must be nested
+ // [[]] => is already nested
+ if (isFlat(shape) && (!shape[0] || shape[0].length !== 0)) {
+ return [shape]
+ } else {
+ return shape
+ }
+ }
+
+ })
+
+ // 馃崅namespace Editable; 馃崅class RectangleEditor; 馃崅aka L.Editable.RectangleEditor
+ // 馃崅inherits PathEditor
+ L.Editable.RectangleEditor = L.Editable.PathEditor.extend({
+
+ CLOSED: true,
+ MIN_VERTEX: 4,
+
+ options: {
+ skipMiddleMarkers: true
+ },
+
+ extendBounds: function (e) {
+ const index = e.vertex.getIndex()
+ const next = e.vertex.getNext()
+ const previous = e.vertex.getPrevious()
+ const oppositeIndex = (index + 2) % 4
+ const opposite = e.vertex.latlngs[oppositeIndex]
+ const bounds = new L.LatLngBounds(e.latlng, opposite)
+ // Update latlngs by hand to preserve order.
+ previous.latlng.update([e.latlng.lat, opposite.lng])
+ next.latlng.update([opposite.lat, e.latlng.lng])
+ this.updateBounds(bounds)
+ this.refreshVertexMarkers()
+ },
+
+ onDrawingMouseDown: function (e) {
+ L.Editable.PathEditor.prototype.onDrawingMouseDown.call(this, e)
+ this.connect()
+ const latlngs = this.getDefaultLatLngs()
+ // L.Polygon._convertLatLngs removes last latlng if it equals first point,
+ // which is the case here as all latlngs are [0, 0]
+ if (latlngs.length === 3) latlngs.push(e.latlng)
+ const bounds = new L.LatLngBounds(e.latlng, e.latlng)
+ this.updateBounds(bounds)
+ this.updateLatLngs(bounds)
+ this.refresh()
+ this.reset()
+ // Stop dragging map.
+ // L.Draggable has two workflows:
+ // - mousedown => mousemove => mouseup
+ // - touchstart => touchmove => touchend
+ // Problem: L.Map.Tap does not allow us to listen to touchstart, so we only
+ // can deal with mousedown, but then when in a touch device, we are dealing with
+ // simulated events (actually simulated by L.Map.Tap), which are no more taken
+ // into account by L.Draggable.
+ // Ref.: https://github.com/Leaflet/Leaflet.Editable/issues/103
+ e.originalEvent._simulated = false
+ this.map.dragging._draggable._onUp(e.originalEvent)
+ // Now transfer ongoing drag action to the bottom right corner.
+ // Should we refine which corner will handle the drag according to
+ // drag direction?
+ latlngs[3].__vertex.dragging._draggable._onDown(e.originalEvent)
+ },
+
+ onDrawingMouseUp: function (e) {
+ this.commitDrawing(e)
+ e.originalEvent._simulated = false
+ L.Editable.PathEditor.prototype.onDrawingMouseUp.call(this, e)
+ },
+
+ onDrawingMouseMove: function (e) {
+ e.originalEvent._simulated = false
+ L.Editable.PathEditor.prototype.onDrawingMouseMove.call(this, e)
+ },
+
+ getDefaultLatLngs: function (latlngs) {
+ return latlngs || this.feature._latlngs[0]
+ },
+
+ updateBounds: function (bounds) {
+ this.feature._bounds = bounds
+ },
+
+ updateLatLngs: function (bounds) {
+ const latlngs = this.getDefaultLatLngs()
+ const newLatlngs = this.feature._boundsToLatLngs(bounds)
+ // Keep references.
+ for (let i = 0; i < latlngs.length; i++) {
+ latlngs[i].update(newLatlngs[i])
+ }
+ }
+
+ })
+
+ // 馃崅namespace Editable; 馃崅class CircleEditor; 馃崅aka L.Editable.CircleEditor
+ // 馃崅inherits PathEditor
+ L.Editable.CircleEditor = L.Editable.PathEditor.extend({
+
+ MIN_VERTEX: 2,
+
+ options: {
+ skipMiddleMarkers: true
+ },
+
+ initialize: function (map, feature, options) {
+ L.Editable.PathEditor.prototype.initialize.call(this, map, feature, options)
+ // C.Y.B Modify
+
+ const latlng = this.computeResizeLatLng()
+
+ // latlng.lat = latlng.lat-0.007855;
+ // latlng.lng= latlng.lng-0.1;
+ this._resizeLatLng = latlng
+ // 鍘熷鏂规硶
+ // this._resizeLatLng = this.computeResizeLatLng();
+ },
+
+ computeResizeLatLng: function () {
+ // While circle is not added to the map, _radius is not set.
+ // let delta = (this.feature._radius || this.feature._mRadius) * Math.cos(Math.PI / 4)
+ const delta = (this.feature._radius || this.feature._mRadius)
+ const point = this.map.project(this.feature._latlng)
+ // return this.map.unproject([point.x + delta, point.y - delta])
+ return this.map.unproject([point.x + delta, point.y])
+ },
+
+ updateResizeLatLng: function () {
+ this._resizeLatLng.update(this.computeResizeLatLng())
+ this._resizeLatLng.__vertex.update()
+ },
+
+ getLatLngs: function () {
+ return [this.feature._latlng, this._resizeLatLng]
+ },
+
+ getDefaultLatLngs: function () {
+ return this.getLatLngs()
+ },
+
+ onVertexMarkerDrag: function (e) {
+ if (e.vertex.getIndex() === 1) {
+ this.resize(e)
+ } else {
+ this.updateResizeLatLng(e)
+ }
+ L.Editable.PathEditor.prototype.onVertexMarkerDrag.call(this, e)
+ },
+
+ resize: function (e) {
+ const radius = this.feature._latlng.distanceTo(e.latlng)
+ this.feature.setRadius(radius)
+ },
+
+ onDrawingMouseDown: function (e) {
+ L.Editable.PathEditor.prototype.onDrawingMouseDown.call(this, e)
+ this._resizeLatLng.update(e.latlng)
+ this.feature._latlng.update(e.latlng)
+ this.connect()
+ // Stop dragging map.
+ e.originalEvent._simulated = false
+ this.map.dragging._draggable._onUp(e.originalEvent)
+ // Now transfer ongoing drag action to the radius handler.
+ this._resizeLatLng.__vertex.dragging._draggable._onDown(e.originalEvent)
+ },
+
+ onDrawingMouseUp: function (e) {
+ this.commitDrawing(e)
+ e.originalEvent._simulated = false
+ L.Editable.PathEditor.prototype.onDrawingMouseUp.call(this, e)
+ },
+
+ onDrawingMouseMove: function (e) {
+ e.originalEvent._simulated = false
+ L.Editable.PathEditor.prototype.onDrawingMouseMove.call(this, e)
+ },
+
+ onDrag: function (e) {
+ L.Editable.PathEditor.prototype.onDrag.call(this, e)
+ this.feature.dragging.updateLatLng(this._resizeLatLng)
+ }
+
+ })
+
+ // 馃崅namespace Editable; 馃崅class EditableMixin
+ // `EditableMixin` is included to `L.Polyline`, `L.Polygon`, `L.Rectangle`, `L.Circle`
+ // and `L.Marker`. It adds some methods to them.
+ // *When editing is enabled, the editor is accessible on the instance with the
+ // `editor` property.*
+ const EditableMixin = {
+
+ createEditor: function (map) {
+ map = map || this._map
+ const tools = (this.options.editOptions || {}).editTools || map.editTools
+ if (!tools) throw Error('Unable to detect Editable instance.')
+ const Klass = this.options.editorClass || this.getEditorClass(tools)
+ return new Klass(map, this, this.options.editOptions)
+ },
+
+ // 馃崅method enableEdit(map?: L.Map): this.editor
+ // Enable editing, by creating an editor if not existing, and then calling `enable` on it.
+ enableEdit: function (map) {
+ if (!this.editor) this.createEditor(map)
+ this.editor.enable()
+ return this.editor
+ },
+
+ // 馃崅method editEnabled(): boolean
+ // Return true if current instance has an editor attached, and this editor is enabled.
+ editEnabled: function () {
+ return this.editor && this.editor.enabled()
+ },
+
+ // 馃崅method disableEdit()
+ // Disable editing, also remove the editor property reference.
+ disableEdit: function () {
+ if (this.editor) {
+ this.editor.disable()
+ delete this.editor
+ }
+ },
+
+ // 馃崅method toggleEdit()
+ // Enable or disable editing, according to current status.
+ toggleEdit: function () {
+ if (this.editEnabled()) {
+ this.disableEdit()
+ } else {
+ this.enableEdit()
+ }
+ },
+
+ _onEditableAdd: function () {
+ if (this.editor) this.enableEdit()
+ }
+
+ }
+
+ const PolylineMixin = {
+
+ getEditorClass: function (tools) {
+ return (tools && tools.options.polylineEditorClass) ? tools.options.polylineEditorClass : L.Editable.PolylineEditor
+ },
+
+ shapeAt: function (latlng, latlngs) {
+ // We can have those cases:
+ // - latlngs are just a flat array of latlngs, use this
+ // - latlngs is an array of arrays of latlngs, loop over
+ let shape = null
+ latlngs = latlngs || this._latlngs
+ if (!latlngs.length) {
+ return shape
+ } else if (isFlat(latlngs) && this.isInLatLngs(latlng, latlngs)) {
+ shape = latlngs
+ } else {
+ for (let i = 0; i < latlngs.length; i++) if (this.isInLatLngs(latlng, latlngs[i])) return latlngs[i]
+ }
+ return shape
+ },
+
+ isInLatLngs: function (l, latlngs) {
+ if (!latlngs) return false
+ let i, k, len
+ let part = []
+ const w = this._clickTolerance()
+ this._projectLatlngs(latlngs, part, this._pxBounds)
+ part = part[0]
+ const p = this._map.latLngToLayerPoint(l)
+
+ if (!this._pxBounds.contains(p)) {
return false
}
-
+ for (i = 1, len = part.length, k = 0; i < len; k = i++) {
+ if (L.LineUtil.pointToSegmentDistance(p, part[k], part[i]) <= w) {
+ return true
+ }
+ }
+ return false
}
- const PolygonMixin = {
+ }
- getEditorClass: function (tools) {
- return (tools && tools.options.polygonEditorClass) ? tools.options.polygonEditorClass : L.Editable.PolygonEditor
- },
+ const PolygonMixin = {
- shapeAt: function (latlng, latlngs) {
- // We can have those cases:
- // - latlngs are just a flat array of latlngs, use this
- // - latlngs is an array of arrays of latlngs, this is a simple polygon (maybe with holes), use the first
- // - latlngs is an array of arrays of arrays, this is a multi, loop over
- let shape = null
- latlngs = latlngs || this._latlngs
- if (!latlngs.length) {
- return shape
- } else if (isFlat(latlngs) && this.isInLatLngs(latlng, latlngs)) {
- shape = latlngs
- } else if (isFlat(latlngs[0]) && this.isInLatLngs(latlng, latlngs[0])) {
- shape = latlngs
- } else {
- for (let i = 0; i < latlngs.length; i++) if (this.isInLatLngs(latlng, latlngs[i][0])) return latlngs[i]
- }
+ getEditorClass: function (tools) {
+ return (tools && tools.options.polygonEditorClass) ? tools.options.polygonEditorClass : L.Editable.PolygonEditor
+ },
+
+ shapeAt: function (latlng, latlngs) {
+ // We can have those cases:
+ // - latlngs are just a flat array of latlngs, use this
+ // - latlngs is an array of arrays of latlngs, this is a simple polygon (maybe with holes), use the first
+ // - latlngs is an array of arrays of arrays, this is a multi, loop over
+ let shape = null
+ latlngs = latlngs || this._latlngs
+ if (!latlngs.length) {
return shape
- },
+ } else if (isFlat(latlngs) && this.isInLatLngs(latlng, latlngs)) {
+ shape = latlngs
+ } else if (isFlat(latlngs[0]) && this.isInLatLngs(latlng, latlngs[0])) {
+ shape = latlngs
+ } else {
+ for (let i = 0; i < latlngs.length; i++) if (this.isInLatLngs(latlng, latlngs[i][0])) return latlngs[i]
+ }
+ return shape
+ },
- isInLatLngs: function (l, latlngs) {
- let inside = false
- let l1
- let l2
- let j
- let k
- let len2
- for (j = 0, len2 = latlngs.length, k = len2 - 1; j < len2; k = j++) {
- l1 = latlngs[j]
- l2 = latlngs[k]
+ isInLatLngs: function (l, latlngs) {
+ let inside = false
+ let l1
+ let l2
+ let j
+ let k
+ let len2
+ for (j = 0, len2 = latlngs.length, k = len2 - 1; j < len2; k = j++) {
+ l1 = latlngs[j]
+ l2 = latlngs[k]
- if (((l1.lat > l.lat) !== (l2.lat > l.lat)) &&
- (l.lng < (l2.lng - l1.lng) * (l.lat - l1.lat) / (l2.lat - l1.lat) + l1.lng)) {
- inside = !inside
- }
- }
-
- return inside
- },
-
- parentShape: function (shape, latlngs) {
- latlngs = latlngs || this._latlngs
- if (!latlngs) return
- let idx = L.Util.indexOf(latlngs, shape)
- if (idx !== -1) return latlngs
- for (let i = 0; i < latlngs.length; i++) {
- idx = L.Util.indexOf(latlngs[i], shape)
- if (idx !== -1) return latlngs[i]
+ if (((l1.lat > l.lat) !== (l2.lat > l.lat)) &&
+ (l.lng < (l2.lng - l1.lng) * (l.lat - l1.lat) / (l2.lat - l1.lat) + l1.lng)) {
+ inside = !inside
}
}
- }
+ return inside
+ },
- const MarkerMixin = {
-
- getEditorClass: function (tools) {
- return (tools && tools.options.markerEditorClass) ? tools.options.markerEditorClass : L.Editable.MarkerEditor
+ parentShape: function (shape, latlngs) {
+ latlngs = latlngs || this._latlngs
+ if (!latlngs) return
+ let idx = L.Util.indexOf(latlngs, shape)
+ if (idx !== -1) return latlngs
+ for (let i = 0; i < latlngs.length; i++) {
+ idx = L.Util.indexOf(latlngs[i], shape)
+ if (idx !== -1) return latlngs[i]
}
-
}
- const RectangleMixin = {
+ }
- getEditorClass: function (tools) {
- return (tools && tools.options.rectangleEditorClass) ? tools.options.rectangleEditorClass : L.Editable.RectangleEditor
- }
+ const MarkerMixin = {
+ getEditorClass: function (tools) {
+ return (tools && tools.options.markerEditorClass) ? tools.options.markerEditorClass : L.Editable.MarkerEditor
}
- const CircleMixin = {
+ }
- getEditorClass: function (tools) {
- return (tools && tools.options.circleEditorClass) ? tools.options.circleEditorClass : L.Editable.CircleEditor
- }
+ const RectangleMixin = {
+ getEditorClass: function (tools) {
+ return (tools && tools.options.rectangleEditorClass) ? tools.options.rectangleEditorClass : L.Editable.RectangleEditor
}
- const keepEditable = function () {
- // Make sure you can remove/readd an editable layer.
- this.on('add', this._onEditableAdd)
+ }
+
+ const CircleMixin = {
+
+ getEditorClass: function (tools) {
+ return (tools && tools.options.circleEditorClass) ? tools.options.circleEditorClass : L.Editable.CircleEditor
}
- const isFlat = L.LineUtil.isFlat || L.LineUtil._flat || L.Polyline._flat // <=> 1.1 compat.
+ }
- if (L.Polyline) {
- L.Polyline.include(EditableMixin)
- L.Polyline.include(PolylineMixin)
- L.Polyline.addInitHook(keepEditable)
- }
- if (L.Polygon) {
- L.Polygon.include(EditableMixin)
- L.Polygon.include(PolygonMixin)
- }
- if (L.Marker) {
- L.Marker.include(EditableMixin)
- L.Marker.include(MarkerMixin)
- L.Marker.addInitHook(keepEditable)
- }
- if (L.Rectangle) {
- L.Rectangle.include(EditableMixin)
- L.Rectangle.include(RectangleMixin)
- }
- if (L.Circle) {
- L.Circle.include(EditableMixin)
- L.Circle.include(CircleMixin)
- }
+ const keepEditable = function () {
+ // Make sure you can remove/readd an editable layer.
+ this.on('add', this._onEditableAdd)
+ }
- L.LatLng.prototype.update = function (latlng) {
- latlng = L.latLng(latlng)
- this.lat = latlng.lat
- this.lng = latlng.lng
- }
- }, window))
-}
+ const isFlat = L.LineUtil.isFlat || L.LineUtil._flat || L.Polyline._flat // <=> 1.1 compat.
-export default {
- init
-}
+ if (L.Polyline) {
+ L.Polyline.include(EditableMixin)
+ L.Polyline.include(PolylineMixin)
+ L.Polyline.addInitHook(keepEditable)
+ }
+ if (L.Polygon) {
+ L.Polygon.include(EditableMixin)
+ L.Polygon.include(PolygonMixin)
+ }
+ if (L.Marker) {
+ L.Marker.include(EditableMixin)
+ L.Marker.include(MarkerMixin)
+ L.Marker.addInitHook(keepEditable)
+ }
+ if (L.Rectangle) {
+ L.Rectangle.include(EditableMixin)
+ L.Rectangle.include(RectangleMixin)
+ }
+ if (L.Circle) {
+ L.Circle.include(EditableMixin)
+ L.Circle.include(CircleMixin)
+ }
+
+ L.LatLng.prototype.update = function (latlng) {
+ latlng = L.latLng(latlng)
+ this.lat = latlng.lat
+ this.lng = latlng.lng
+ }
+}, window))
--
Gitblit v1.8.0