leaflet-with-dashoffset-canvas-fix 1.9.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2191 -0
- package/LICENSE +26 -0
- package/README.md +3 -0
- package/package.json +149 -0
- package/src/Leaflet.js +24 -0
- package/src/control/Control.Attribution.js +148 -0
- package/src/control/Control.Layers.js +443 -0
- package/src/control/Control.Scale.js +132 -0
- package/src/control/Control.Zoom.js +146 -0
- package/src/control/Control.js +174 -0
- package/src/control/index.js +17 -0
- package/src/core/Browser.js +220 -0
- package/src/core/Class.js +135 -0
- package/src/core/Events.js +344 -0
- package/src/core/Handler.js +57 -0
- package/src/core/Util.js +241 -0
- package/src/core/index.js +15 -0
- package/src/dom/DomEvent.DoubleTap.js +91 -0
- package/src/dom/DomEvent.Pointer.js +97 -0
- package/src/dom/DomEvent.js +315 -0
- package/src/dom/DomUtil.js +349 -0
- package/src/dom/Draggable.js +220 -0
- package/src/dom/PosAnimation.js +113 -0
- package/src/dom/index.js +9 -0
- package/src/geo/LatLng.js +137 -0
- package/src/geo/LatLngBounds.js +251 -0
- package/src/geo/crs/CRS.EPSG3395.js +20 -0
- package/src/geo/crs/CRS.EPSG3857.js +27 -0
- package/src/geo/crs/CRS.EPSG4326.js +23 -0
- package/src/geo/crs/CRS.Earth.js +33 -0
- package/src/geo/crs/CRS.Simple.js +36 -0
- package/src/geo/crs/CRS.js +139 -0
- package/src/geo/crs/index.js +15 -0
- package/src/geo/index.js +7 -0
- package/src/geo/projection/Projection.LonLat.js +28 -0
- package/src/geo/projection/Projection.Mercator.js +49 -0
- package/src/geo/projection/Projection.SphericalMercator.js +44 -0
- package/src/geo/projection/index.js +26 -0
- package/src/geometry/Bounds.js +219 -0
- package/src/geometry/LineUtil.js +306 -0
- package/src/geometry/Point.js +222 -0
- package/src/geometry/PolyUtil.js +129 -0
- package/src/geometry/Transformation.js +79 -0
- package/src/geometry/index.js +8 -0
- package/src/images/layers.svg +1 -0
- package/src/images/logo.svg +1 -0
- package/src/images/marker.svg +1 -0
- package/src/layer/DivOverlay.js +348 -0
- package/src/layer/FeatureGroup.js +94 -0
- package/src/layer/GeoJSON.js +452 -0
- package/src/layer/ImageOverlay.js +270 -0
- package/src/layer/Layer.js +275 -0
- package/src/layer/LayerGroup.js +159 -0
- package/src/layer/Popup.js +506 -0
- package/src/layer/SVGOverlay.js +50 -0
- package/src/layer/Tooltip.js +444 -0
- package/src/layer/VideoOverlay.js +106 -0
- package/src/layer/index.js +24 -0
- package/src/layer/marker/DivIcon.js +74 -0
- package/src/layer/marker/Icon.Default.js +66 -0
- package/src/layer/marker/Icon.js +165 -0
- package/src/layer/marker/Marker.Drag.js +161 -0
- package/src/layer/marker/Marker.js +419 -0
- package/src/layer/marker/index.js +8 -0
- package/src/layer/tile/GridLayer.js +923 -0
- package/src/layer/tile/TileLayer.WMS.js +137 -0
- package/src/layer/tile/TileLayer.js +289 -0
- package/src/layer/tile/index.js +6 -0
- package/src/layer/vector/Canvas.js +493 -0
- package/src/layer/vector/Circle.js +113 -0
- package/src/layer/vector/CircleMarker.js +109 -0
- package/src/layer/vector/Path.js +148 -0
- package/src/layer/vector/Polygon.js +159 -0
- package/src/layer/vector/Polyline.js +307 -0
- package/src/layer/vector/Rectangle.js +57 -0
- package/src/layer/vector/Renderer.getRenderer.js +45 -0
- package/src/layer/vector/Renderer.js +133 -0
- package/src/layer/vector/SVG.Util.js +39 -0
- package/src/layer/vector/SVG.VML.js +144 -0
- package/src/layer/vector/SVG.js +207 -0
- package/src/layer/vector/index.js +14 -0
- package/src/map/Map.js +1751 -0
- package/src/map/handler/Map.BoxZoom.js +152 -0
- package/src/map/handler/Map.DoubleClickZoom.js +55 -0
- package/src/map/handler/Map.Drag.js +235 -0
- package/src/map/handler/Map.Keyboard.js +183 -0
- package/src/map/handler/Map.ScrollWheelZoom.js +91 -0
- package/src/map/handler/Map.TapHold.js +102 -0
- package/src/map/handler/Map.TouchZoom.js +130 -0
- package/src/map/index.js +17 -0
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
import * as DomEvent from './DomEvent';
|
|
2
|
+
import * as Util from '../core/Util';
|
|
3
|
+
import {Point} from '../geometry/Point';
|
|
4
|
+
import Browser from '../core/Browser';
|
|
5
|
+
|
|
6
|
+
/*
|
|
7
|
+
* @namespace DomUtil
|
|
8
|
+
*
|
|
9
|
+
* Utility functions to work with the [DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model)
|
|
10
|
+
* tree, used by Leaflet internally.
|
|
11
|
+
*
|
|
12
|
+
* Most functions expecting or returning a `HTMLElement` also work for
|
|
13
|
+
* SVG elements. The only difference is that classes refer to CSS classes
|
|
14
|
+
* in HTML and SVG classes in SVG.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
// @property TRANSFORM: String
|
|
19
|
+
// Vendor-prefixed transform style name (e.g. `'webkitTransform'` for WebKit).
|
|
20
|
+
export var TRANSFORM = testProp(
|
|
21
|
+
['transform', 'webkitTransform', 'OTransform', 'MozTransform', 'msTransform']);
|
|
22
|
+
|
|
23
|
+
// webkitTransition comes first because some browser versions that drop vendor prefix don't do
|
|
24
|
+
// the same for the transitionend event, in particular the Android 4.1 stock browser
|
|
25
|
+
|
|
26
|
+
// @property TRANSITION: String
|
|
27
|
+
// Vendor-prefixed transition style name.
|
|
28
|
+
export var TRANSITION = testProp(
|
|
29
|
+
['webkitTransition', 'transition', 'OTransition', 'MozTransition', 'msTransition']);
|
|
30
|
+
|
|
31
|
+
// @property TRANSITION_END: String
|
|
32
|
+
// Vendor-prefixed transitionend event name.
|
|
33
|
+
export var TRANSITION_END =
|
|
34
|
+
TRANSITION === 'webkitTransition' || TRANSITION === 'OTransition' ? TRANSITION + 'End' : 'transitionend';
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
// @function get(id: String|HTMLElement): HTMLElement
|
|
38
|
+
// Returns an element given its DOM id, or returns the element itself
|
|
39
|
+
// if it was passed directly.
|
|
40
|
+
export function get(id) {
|
|
41
|
+
return typeof id === 'string' ? document.getElementById(id) : id;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// @function getStyle(el: HTMLElement, styleAttrib: String): String
|
|
45
|
+
// Returns the value for a certain style attribute on an element,
|
|
46
|
+
// including computed values or values set through CSS.
|
|
47
|
+
export function getStyle(el, style) {
|
|
48
|
+
var value = el.style[style] || (el.currentStyle && el.currentStyle[style]);
|
|
49
|
+
|
|
50
|
+
if ((!value || value === 'auto') && document.defaultView) {
|
|
51
|
+
var css = document.defaultView.getComputedStyle(el, null);
|
|
52
|
+
value = css ? css[style] : null;
|
|
53
|
+
}
|
|
54
|
+
return value === 'auto' ? null : value;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// @function create(tagName: String, className?: String, container?: HTMLElement): HTMLElement
|
|
58
|
+
// Creates an HTML element with `tagName`, sets its class to `className`, and optionally appends it to `container` element.
|
|
59
|
+
export function create(tagName, className, container) {
|
|
60
|
+
var el = document.createElement(tagName);
|
|
61
|
+
el.className = className || '';
|
|
62
|
+
|
|
63
|
+
if (container) {
|
|
64
|
+
container.appendChild(el);
|
|
65
|
+
}
|
|
66
|
+
return el;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// @function remove(el: HTMLElement)
|
|
70
|
+
// Removes `el` from its parent element
|
|
71
|
+
export function remove(el) {
|
|
72
|
+
var parent = el.parentNode;
|
|
73
|
+
if (parent) {
|
|
74
|
+
parent.removeChild(el);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// @function empty(el: HTMLElement)
|
|
79
|
+
// Removes all of `el`'s children elements from `el`
|
|
80
|
+
export function empty(el) {
|
|
81
|
+
while (el.firstChild) {
|
|
82
|
+
el.removeChild(el.firstChild);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// @function toFront(el: HTMLElement)
|
|
87
|
+
// Makes `el` the last child of its parent, so it renders in front of the other children.
|
|
88
|
+
export function toFront(el) {
|
|
89
|
+
var parent = el.parentNode;
|
|
90
|
+
if (parent && parent.lastChild !== el) {
|
|
91
|
+
parent.appendChild(el);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// @function toBack(el: HTMLElement)
|
|
96
|
+
// Makes `el` the first child of its parent, so it renders behind the other children.
|
|
97
|
+
export function toBack(el) {
|
|
98
|
+
var parent = el.parentNode;
|
|
99
|
+
if (parent && parent.firstChild !== el) {
|
|
100
|
+
parent.insertBefore(el, parent.firstChild);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// @function hasClass(el: HTMLElement, name: String): Boolean
|
|
105
|
+
// Returns `true` if the element's class attribute contains `name`.
|
|
106
|
+
export function hasClass(el, name) {
|
|
107
|
+
if (el.classList !== undefined) {
|
|
108
|
+
return el.classList.contains(name);
|
|
109
|
+
}
|
|
110
|
+
var className = getClass(el);
|
|
111
|
+
return className.length > 0 && new RegExp('(^|\\s)' + name + '(\\s|$)').test(className);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// @function addClass(el: HTMLElement, name: String)
|
|
115
|
+
// Adds `name` to the element's class attribute.
|
|
116
|
+
export function addClass(el, name) {
|
|
117
|
+
if (el.classList !== undefined) {
|
|
118
|
+
var classes = Util.splitWords(name);
|
|
119
|
+
for (var i = 0, len = classes.length; i < len; i++) {
|
|
120
|
+
el.classList.add(classes[i]);
|
|
121
|
+
}
|
|
122
|
+
} else if (!hasClass(el, name)) {
|
|
123
|
+
var className = getClass(el);
|
|
124
|
+
setClass(el, (className ? className + ' ' : '') + name);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// @function removeClass(el: HTMLElement, name: String)
|
|
129
|
+
// Removes `name` from the element's class attribute.
|
|
130
|
+
export function removeClass(el, name) {
|
|
131
|
+
if (el.classList !== undefined) {
|
|
132
|
+
el.classList.remove(name);
|
|
133
|
+
} else {
|
|
134
|
+
setClass(el, Util.trim((' ' + getClass(el) + ' ').replace(' ' + name + ' ', ' ')));
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// @function setClass(el: HTMLElement, name: String)
|
|
139
|
+
// Sets the element's class.
|
|
140
|
+
export function setClass(el, name) {
|
|
141
|
+
if (el.className.baseVal === undefined) {
|
|
142
|
+
el.className = name;
|
|
143
|
+
} else {
|
|
144
|
+
// in case of SVG element
|
|
145
|
+
el.className.baseVal = name;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// @function getClass(el: HTMLElement): String
|
|
150
|
+
// Returns the element's class.
|
|
151
|
+
export function getClass(el) {
|
|
152
|
+
// Check if the element is an SVGElementInstance and use the correspondingElement instead
|
|
153
|
+
// (Required for linked SVG elements in IE11.)
|
|
154
|
+
if (el.correspondingElement) {
|
|
155
|
+
el = el.correspondingElement;
|
|
156
|
+
}
|
|
157
|
+
return el.className.baseVal === undefined ? el.className : el.className.baseVal;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// @function setOpacity(el: HTMLElement, opacity: Number)
|
|
161
|
+
// Set the opacity of an element (including old IE support).
|
|
162
|
+
// `opacity` must be a number from `0` to `1`.
|
|
163
|
+
export function setOpacity(el, value) {
|
|
164
|
+
if ('opacity' in el.style) {
|
|
165
|
+
el.style.opacity = value;
|
|
166
|
+
} else if ('filter' in el.style) {
|
|
167
|
+
_setOpacityIE(el, value);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function _setOpacityIE(el, value) {
|
|
172
|
+
var filter = false,
|
|
173
|
+
filterName = 'DXImageTransform.Microsoft.Alpha';
|
|
174
|
+
|
|
175
|
+
// filters collection throws an error if we try to retrieve a filter that doesn't exist
|
|
176
|
+
try {
|
|
177
|
+
filter = el.filters.item(filterName);
|
|
178
|
+
} catch (e) {
|
|
179
|
+
// don't set opacity to 1 if we haven't already set an opacity,
|
|
180
|
+
// it isn't needed and breaks transparent pngs.
|
|
181
|
+
if (value === 1) { return; }
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
value = Math.round(value * 100);
|
|
185
|
+
|
|
186
|
+
if (filter) {
|
|
187
|
+
filter.Enabled = (value !== 100);
|
|
188
|
+
filter.Opacity = value;
|
|
189
|
+
} else {
|
|
190
|
+
el.style.filter += ' progid:' + filterName + '(opacity=' + value + ')';
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// @function testProp(props: String[]): String|false
|
|
195
|
+
// Goes through the array of style names and returns the first name
|
|
196
|
+
// that is a valid style name for an element. If no such name is found,
|
|
197
|
+
// it returns false. Useful for vendor-prefixed styles like `transform`.
|
|
198
|
+
export function testProp(props) {
|
|
199
|
+
var style = document.documentElement.style;
|
|
200
|
+
|
|
201
|
+
for (var i = 0; i < props.length; i++) {
|
|
202
|
+
if (props[i] in style) {
|
|
203
|
+
return props[i];
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// @function setTransform(el: HTMLElement, offset: Point, scale?: Number)
|
|
210
|
+
// Resets the 3D CSS transform of `el` so it is translated by `offset` pixels
|
|
211
|
+
// and optionally scaled by `scale`. Does not have an effect if the
|
|
212
|
+
// browser doesn't support 3D CSS transforms.
|
|
213
|
+
export function setTransform(el, offset, scale) {
|
|
214
|
+
var pos = offset || new Point(0, 0);
|
|
215
|
+
|
|
216
|
+
el.style[TRANSFORM] =
|
|
217
|
+
(Browser.ie3d ?
|
|
218
|
+
'translate(' + pos.x + 'px,' + pos.y + 'px)' :
|
|
219
|
+
'translate3d(' + pos.x + 'px,' + pos.y + 'px,0)') +
|
|
220
|
+
(scale ? ' scale(' + scale + ')' : '');
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// @function setPosition(el: HTMLElement, position: Point)
|
|
224
|
+
// Sets the position of `el` to coordinates specified by `position`,
|
|
225
|
+
// using CSS translate or top/left positioning depending on the browser
|
|
226
|
+
// (used by Leaflet internally to position its layers).
|
|
227
|
+
export function setPosition(el, point) {
|
|
228
|
+
|
|
229
|
+
/*eslint-disable */
|
|
230
|
+
el._leaflet_pos = point;
|
|
231
|
+
/* eslint-enable */
|
|
232
|
+
|
|
233
|
+
if (Browser.any3d) {
|
|
234
|
+
setTransform(el, point);
|
|
235
|
+
} else {
|
|
236
|
+
el.style.left = point.x + 'px';
|
|
237
|
+
el.style.top = point.y + 'px';
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// @function getPosition(el: HTMLElement): Point
|
|
242
|
+
// Returns the coordinates of an element previously positioned with setPosition.
|
|
243
|
+
export function getPosition(el) {
|
|
244
|
+
// this method is only used for elements previously positioned using setPosition,
|
|
245
|
+
// so it's safe to cache the position for performance
|
|
246
|
+
|
|
247
|
+
return el._leaflet_pos || new Point(0, 0);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// @function disableTextSelection()
|
|
251
|
+
// Prevents the user from generating `selectstart` DOM events, usually generated
|
|
252
|
+
// when the user drags the mouse through a page with text. Used internally
|
|
253
|
+
// by Leaflet to override the behaviour of any click-and-drag interaction on
|
|
254
|
+
// the map. Affects drag interactions on the whole document.
|
|
255
|
+
|
|
256
|
+
// @function enableTextSelection()
|
|
257
|
+
// Cancels the effects of a previous [`L.DomUtil.disableTextSelection`](#domutil-disabletextselection).
|
|
258
|
+
export var disableTextSelection;
|
|
259
|
+
export var enableTextSelection;
|
|
260
|
+
var _userSelect;
|
|
261
|
+
if ('onselectstart' in document) {
|
|
262
|
+
disableTextSelection = function () {
|
|
263
|
+
DomEvent.on(window, 'selectstart', DomEvent.preventDefault);
|
|
264
|
+
};
|
|
265
|
+
enableTextSelection = function () {
|
|
266
|
+
DomEvent.off(window, 'selectstart', DomEvent.preventDefault);
|
|
267
|
+
};
|
|
268
|
+
} else {
|
|
269
|
+
var userSelectProperty = testProp(
|
|
270
|
+
['userSelect', 'WebkitUserSelect', 'OUserSelect', 'MozUserSelect', 'msUserSelect']);
|
|
271
|
+
|
|
272
|
+
disableTextSelection = function () {
|
|
273
|
+
if (userSelectProperty) {
|
|
274
|
+
var style = document.documentElement.style;
|
|
275
|
+
_userSelect = style[userSelectProperty];
|
|
276
|
+
style[userSelectProperty] = 'none';
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
enableTextSelection = function () {
|
|
280
|
+
if (userSelectProperty) {
|
|
281
|
+
document.documentElement.style[userSelectProperty] = _userSelect;
|
|
282
|
+
_userSelect = undefined;
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// @function disableImageDrag()
|
|
288
|
+
// As [`L.DomUtil.disableTextSelection`](#domutil-disabletextselection), but
|
|
289
|
+
// for `dragstart` DOM events, usually generated when the user drags an image.
|
|
290
|
+
export function disableImageDrag() {
|
|
291
|
+
DomEvent.on(window, 'dragstart', DomEvent.preventDefault);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// @function enableImageDrag()
|
|
295
|
+
// Cancels the effects of a previous [`L.DomUtil.disableImageDrag`](#domutil-disabletextselection).
|
|
296
|
+
export function enableImageDrag() {
|
|
297
|
+
DomEvent.off(window, 'dragstart', DomEvent.preventDefault);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
var _outlineElement, _outlineStyle;
|
|
301
|
+
// @function preventOutline(el: HTMLElement)
|
|
302
|
+
// Makes the [outline](https://developer.mozilla.org/docs/Web/CSS/outline)
|
|
303
|
+
// of the element `el` invisible. Used internally by Leaflet to prevent
|
|
304
|
+
// focusable elements from displaying an outline when the user performs a
|
|
305
|
+
// drag interaction on them.
|
|
306
|
+
export function preventOutline(element) {
|
|
307
|
+
while (element.tabIndex === -1) {
|
|
308
|
+
element = element.parentNode;
|
|
309
|
+
}
|
|
310
|
+
if (!element.style) { return; }
|
|
311
|
+
restoreOutline();
|
|
312
|
+
_outlineElement = element;
|
|
313
|
+
_outlineStyle = element.style.outlineStyle;
|
|
314
|
+
element.style.outlineStyle = 'none';
|
|
315
|
+
DomEvent.on(window, 'keydown', restoreOutline);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// @function restoreOutline()
|
|
319
|
+
// Cancels the effects of a previous [`L.DomUtil.preventOutline`]().
|
|
320
|
+
export function restoreOutline() {
|
|
321
|
+
if (!_outlineElement) { return; }
|
|
322
|
+
_outlineElement.style.outlineStyle = _outlineStyle;
|
|
323
|
+
_outlineElement = undefined;
|
|
324
|
+
_outlineStyle = undefined;
|
|
325
|
+
DomEvent.off(window, 'keydown', restoreOutline);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// @function getSizedParentNode(el: HTMLElement): HTMLElement
|
|
329
|
+
// Finds the closest parent node which size (width and height) is not null.
|
|
330
|
+
export function getSizedParentNode(element) {
|
|
331
|
+
do {
|
|
332
|
+
element = element.parentNode;
|
|
333
|
+
} while ((!element.offsetWidth || !element.offsetHeight) && element !== document.body);
|
|
334
|
+
return element;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// @function getScale(el: HTMLElement): Object
|
|
338
|
+
// Computes the CSS scale currently applied on the element.
|
|
339
|
+
// Returns an object with `x` and `y` members as horizontal and vertical scales respectively,
|
|
340
|
+
// and `boundingClientRect` as the result of [`getBoundingClientRect()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect).
|
|
341
|
+
export function getScale(element) {
|
|
342
|
+
var rect = element.getBoundingClientRect(); // Read-only in old browsers.
|
|
343
|
+
|
|
344
|
+
return {
|
|
345
|
+
x: rect.width / element.offsetWidth || 1,
|
|
346
|
+
y: rect.height / element.offsetHeight || 1,
|
|
347
|
+
boundingClientRect: rect
|
|
348
|
+
};
|
|
349
|
+
}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import {Evented} from '../core/Events';
|
|
2
|
+
import Browser from '../core/Browser';
|
|
3
|
+
import * as DomEvent from './DomEvent';
|
|
4
|
+
import * as DomUtil from './DomUtil';
|
|
5
|
+
import * as Util from '../core/Util';
|
|
6
|
+
import {Point} from '../geometry/Point';
|
|
7
|
+
|
|
8
|
+
/*
|
|
9
|
+
* @class Draggable
|
|
10
|
+
* @aka L.Draggable
|
|
11
|
+
* @inherits Evented
|
|
12
|
+
*
|
|
13
|
+
* A class for making DOM elements draggable (including touch support).
|
|
14
|
+
* Used internally for map and marker dragging. Only works for elements
|
|
15
|
+
* that were positioned with [`L.DomUtil.setPosition`](#domutil-setposition).
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```js
|
|
19
|
+
* var draggable = new L.Draggable(elementToDrag);
|
|
20
|
+
* draggable.enable();
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
var START = Browser.touch ? 'touchstart mousedown' : 'mousedown';
|
|
25
|
+
|
|
26
|
+
export var Draggable = Evented.extend({
|
|
27
|
+
|
|
28
|
+
options: {
|
|
29
|
+
// @section
|
|
30
|
+
// @aka Draggable options
|
|
31
|
+
// @option clickTolerance: Number = 3
|
|
32
|
+
// The max number of pixels a user can shift the mouse pointer during a click
|
|
33
|
+
// for it to be considered a valid click (as opposed to a mouse drag).
|
|
34
|
+
clickTolerance: 3
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
// @constructor L.Draggable(el: HTMLElement, dragHandle?: HTMLElement, preventOutline?: Boolean, options?: Draggable options)
|
|
38
|
+
// Creates a `Draggable` object for moving `el` when you start dragging the `dragHandle` element (equals `el` itself by default).
|
|
39
|
+
initialize: function (element, dragStartTarget, preventOutline, options) {
|
|
40
|
+
Util.setOptions(this, options);
|
|
41
|
+
|
|
42
|
+
this._element = element;
|
|
43
|
+
this._dragStartTarget = dragStartTarget || element;
|
|
44
|
+
this._preventOutline = preventOutline;
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
// @method enable()
|
|
48
|
+
// Enables the dragging ability
|
|
49
|
+
enable: function () {
|
|
50
|
+
if (this._enabled) { return; }
|
|
51
|
+
|
|
52
|
+
DomEvent.on(this._dragStartTarget, START, this._onDown, this);
|
|
53
|
+
|
|
54
|
+
this._enabled = true;
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
// @method disable()
|
|
58
|
+
// Disables the dragging ability
|
|
59
|
+
disable: function () {
|
|
60
|
+
if (!this._enabled) { return; }
|
|
61
|
+
|
|
62
|
+
// If we're currently dragging this draggable,
|
|
63
|
+
// disabling it counts as first ending the drag.
|
|
64
|
+
if (Draggable._dragging === this) {
|
|
65
|
+
this.finishDrag(true);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
DomEvent.off(this._dragStartTarget, START, this._onDown, this);
|
|
69
|
+
|
|
70
|
+
this._enabled = false;
|
|
71
|
+
this._moved = false;
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
_onDown: function (e) {
|
|
75
|
+
// Ignore the event if disabled; this happens in IE11
|
|
76
|
+
// under some circumstances, see #3666.
|
|
77
|
+
if (!this._enabled) { return; }
|
|
78
|
+
|
|
79
|
+
this._moved = false;
|
|
80
|
+
|
|
81
|
+
if (DomUtil.hasClass(this._element, 'leaflet-zoom-anim')) { return; }
|
|
82
|
+
|
|
83
|
+
if (e.touches && e.touches.length !== 1) {
|
|
84
|
+
// Finish dragging to avoid conflict with touchZoom
|
|
85
|
+
if (Draggable._dragging === this) {
|
|
86
|
+
this.finishDrag();
|
|
87
|
+
}
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (Draggable._dragging || e.shiftKey || ((e.which !== 1) && (e.button !== 1) && !e.touches)) { return; }
|
|
92
|
+
Draggable._dragging = this; // Prevent dragging multiple objects at once.
|
|
93
|
+
|
|
94
|
+
if (this._preventOutline) {
|
|
95
|
+
DomUtil.preventOutline(this._element);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
DomUtil.disableImageDrag();
|
|
99
|
+
DomUtil.disableTextSelection();
|
|
100
|
+
|
|
101
|
+
if (this._moving) { return; }
|
|
102
|
+
|
|
103
|
+
// @event down: Event
|
|
104
|
+
// Fired when a drag is about to start.
|
|
105
|
+
this.fire('down');
|
|
106
|
+
|
|
107
|
+
var first = e.touches ? e.touches[0] : e,
|
|
108
|
+
sizedParent = DomUtil.getSizedParentNode(this._element);
|
|
109
|
+
|
|
110
|
+
this._startPoint = new Point(first.clientX, first.clientY);
|
|
111
|
+
this._startPos = DomUtil.getPosition(this._element);
|
|
112
|
+
|
|
113
|
+
// Cache the scale, so that we can continuously compensate for it during drag (_onMove).
|
|
114
|
+
this._parentScale = DomUtil.getScale(sizedParent);
|
|
115
|
+
|
|
116
|
+
var mouseevent = e.type === 'mousedown';
|
|
117
|
+
DomEvent.on(document, mouseevent ? 'mousemove' : 'touchmove', this._onMove, this);
|
|
118
|
+
DomEvent.on(document, mouseevent ? 'mouseup' : 'touchend touchcancel', this._onUp, this);
|
|
119
|
+
},
|
|
120
|
+
|
|
121
|
+
_onMove: function (e) {
|
|
122
|
+
// Ignore the event if disabled; this happens in IE11
|
|
123
|
+
// under some circumstances, see #3666.
|
|
124
|
+
if (!this._enabled) { return; }
|
|
125
|
+
|
|
126
|
+
if (e.touches && e.touches.length > 1) {
|
|
127
|
+
this._moved = true;
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
var first = (e.touches && e.touches.length === 1 ? e.touches[0] : e),
|
|
132
|
+
offset = new Point(first.clientX, first.clientY)._subtract(this._startPoint);
|
|
133
|
+
|
|
134
|
+
if (!offset.x && !offset.y) { return; }
|
|
135
|
+
if (Math.abs(offset.x) + Math.abs(offset.y) < this.options.clickTolerance) { return; }
|
|
136
|
+
|
|
137
|
+
// We assume that the parent container's position, border and scale do not change for the duration of the drag.
|
|
138
|
+
// Therefore there is no need to account for the position and border (they are eliminated by the subtraction)
|
|
139
|
+
// and we can use the cached value for the scale.
|
|
140
|
+
offset.x /= this._parentScale.x;
|
|
141
|
+
offset.y /= this._parentScale.y;
|
|
142
|
+
|
|
143
|
+
DomEvent.preventDefault(e);
|
|
144
|
+
|
|
145
|
+
if (!this._moved) {
|
|
146
|
+
// @event dragstart: Event
|
|
147
|
+
// Fired when a drag starts
|
|
148
|
+
this.fire('dragstart');
|
|
149
|
+
|
|
150
|
+
this._moved = true;
|
|
151
|
+
|
|
152
|
+
DomUtil.addClass(document.body, 'leaflet-dragging');
|
|
153
|
+
|
|
154
|
+
this._lastTarget = e.target || e.srcElement;
|
|
155
|
+
// IE and Edge do not give the <use> element, so fetch it
|
|
156
|
+
// if necessary
|
|
157
|
+
if (window.SVGElementInstance && this._lastTarget instanceof window.SVGElementInstance) {
|
|
158
|
+
this._lastTarget = this._lastTarget.correspondingUseElement;
|
|
159
|
+
}
|
|
160
|
+
DomUtil.addClass(this._lastTarget, 'leaflet-drag-target');
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
this._newPos = this._startPos.add(offset);
|
|
164
|
+
this._moving = true;
|
|
165
|
+
|
|
166
|
+
this._lastEvent = e;
|
|
167
|
+
this._updatePosition();
|
|
168
|
+
},
|
|
169
|
+
|
|
170
|
+
_updatePosition: function () {
|
|
171
|
+
var e = {originalEvent: this._lastEvent};
|
|
172
|
+
|
|
173
|
+
// @event predrag: Event
|
|
174
|
+
// Fired continuously during dragging *before* each corresponding
|
|
175
|
+
// update of the element's position.
|
|
176
|
+
this.fire('predrag', e);
|
|
177
|
+
DomUtil.setPosition(this._element, this._newPos);
|
|
178
|
+
|
|
179
|
+
// @event drag: Event
|
|
180
|
+
// Fired continuously during dragging.
|
|
181
|
+
this.fire('drag', e);
|
|
182
|
+
},
|
|
183
|
+
|
|
184
|
+
_onUp: function () {
|
|
185
|
+
// Ignore the event if disabled; this happens in IE11
|
|
186
|
+
// under some circumstances, see #3666.
|
|
187
|
+
if (!this._enabled) { return; }
|
|
188
|
+
this.finishDrag();
|
|
189
|
+
},
|
|
190
|
+
|
|
191
|
+
finishDrag: function (noInertia) {
|
|
192
|
+
DomUtil.removeClass(document.body, 'leaflet-dragging');
|
|
193
|
+
|
|
194
|
+
if (this._lastTarget) {
|
|
195
|
+
DomUtil.removeClass(this._lastTarget, 'leaflet-drag-target');
|
|
196
|
+
this._lastTarget = null;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
DomEvent.off(document, 'mousemove touchmove', this._onMove, this);
|
|
200
|
+
DomEvent.off(document, 'mouseup touchend touchcancel', this._onUp, this);
|
|
201
|
+
|
|
202
|
+
DomUtil.enableImageDrag();
|
|
203
|
+
DomUtil.enableTextSelection();
|
|
204
|
+
|
|
205
|
+
var fireDragend = this._moved && this._moving;
|
|
206
|
+
|
|
207
|
+
this._moving = false;
|
|
208
|
+
Draggable._dragging = false;
|
|
209
|
+
|
|
210
|
+
if (fireDragend) {
|
|
211
|
+
// @event dragend: DragEndEvent
|
|
212
|
+
// Fired when the drag ends.
|
|
213
|
+
this.fire('dragend', {
|
|
214
|
+
noInertia: noInertia,
|
|
215
|
+
distance: this._newPos.distanceTo(this._startPos)
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
});
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import * as Util from '../core/Util';
|
|
2
|
+
import {Evented} from '../core/Events';
|
|
3
|
+
import * as DomUtil from '../dom/DomUtil';
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
/*
|
|
7
|
+
* @class PosAnimation
|
|
8
|
+
* @aka L.PosAnimation
|
|
9
|
+
* @inherits Evented
|
|
10
|
+
* Used internally for panning animations, utilizing CSS3 Transitions for modern browsers and a timer fallback for IE6-9.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```js
|
|
14
|
+
* var myPositionMarker = L.marker([48.864716, 2.294694]).addTo(map);
|
|
15
|
+
*
|
|
16
|
+
* myPositionMarker.on("click", function() {
|
|
17
|
+
* var pos = map.latLngToLayerPoint(myPositionMarker.getLatLng());
|
|
18
|
+
* pos.y -= 25;
|
|
19
|
+
* var fx = new L.PosAnimation();
|
|
20
|
+
*
|
|
21
|
+
* fx.once('end',function() {
|
|
22
|
+
* pos.y += 25;
|
|
23
|
+
* fx.run(myPositionMarker._icon, pos, 0.8);
|
|
24
|
+
* });
|
|
25
|
+
*
|
|
26
|
+
* fx.run(myPositionMarker._icon, pos, 0.3);
|
|
27
|
+
* });
|
|
28
|
+
*
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @constructor L.PosAnimation()
|
|
32
|
+
* Creates a `PosAnimation` object.
|
|
33
|
+
*
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
export var PosAnimation = Evented.extend({
|
|
37
|
+
|
|
38
|
+
// @method run(el: HTMLElement, newPos: Point, duration?: Number, easeLinearity?: Number)
|
|
39
|
+
// Run an animation of a given element to a new position, optionally setting
|
|
40
|
+
// duration in seconds (`0.25` by default) and easing linearity factor (3rd
|
|
41
|
+
// argument of the [cubic bezier curve](https://cubic-bezier.com/#0,0,.5,1),
|
|
42
|
+
// `0.5` by default).
|
|
43
|
+
run: function (el, newPos, duration, easeLinearity) {
|
|
44
|
+
this.stop();
|
|
45
|
+
|
|
46
|
+
this._el = el;
|
|
47
|
+
this._inProgress = true;
|
|
48
|
+
this._duration = duration || 0.25;
|
|
49
|
+
this._easeOutPower = 1 / Math.max(easeLinearity || 0.5, 0.2);
|
|
50
|
+
|
|
51
|
+
this._startPos = DomUtil.getPosition(el);
|
|
52
|
+
this._offset = newPos.subtract(this._startPos);
|
|
53
|
+
this._startTime = +new Date();
|
|
54
|
+
|
|
55
|
+
// @event start: Event
|
|
56
|
+
// Fired when the animation starts
|
|
57
|
+
this.fire('start');
|
|
58
|
+
|
|
59
|
+
this._animate();
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
// @method stop()
|
|
63
|
+
// Stops the animation (if currently running).
|
|
64
|
+
stop: function () {
|
|
65
|
+
if (!this._inProgress) { return; }
|
|
66
|
+
|
|
67
|
+
this._step(true);
|
|
68
|
+
this._complete();
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
_animate: function () {
|
|
72
|
+
// animation loop
|
|
73
|
+
this._animId = Util.requestAnimFrame(this._animate, this);
|
|
74
|
+
this._step();
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
_step: function (round) {
|
|
78
|
+
var elapsed = (+new Date()) - this._startTime,
|
|
79
|
+
duration = this._duration * 1000;
|
|
80
|
+
|
|
81
|
+
if (elapsed < duration) {
|
|
82
|
+
this._runFrame(this._easeOut(elapsed / duration), round);
|
|
83
|
+
} else {
|
|
84
|
+
this._runFrame(1);
|
|
85
|
+
this._complete();
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
_runFrame: function (progress, round) {
|
|
90
|
+
var pos = this._startPos.add(this._offset.multiplyBy(progress));
|
|
91
|
+
if (round) {
|
|
92
|
+
pos._round();
|
|
93
|
+
}
|
|
94
|
+
DomUtil.setPosition(this._el, pos);
|
|
95
|
+
|
|
96
|
+
// @event step: Event
|
|
97
|
+
// Fired continuously during the animation.
|
|
98
|
+
this.fire('step');
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
_complete: function () {
|
|
102
|
+
Util.cancelAnimFrame(this._animId);
|
|
103
|
+
|
|
104
|
+
this._inProgress = false;
|
|
105
|
+
// @event end: Event
|
|
106
|
+
// Fired when the animation ends.
|
|
107
|
+
this.fire('end');
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
_easeOut: function (t) {
|
|
111
|
+
return 1 - Math.pow(1 - t, this._easeOutPower);
|
|
112
|
+
}
|
|
113
|
+
});
|