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,493 @@
|
|
|
1
|
+
import {Renderer} from './Renderer';
|
|
2
|
+
import * as DomUtil from '../../dom/DomUtil';
|
|
3
|
+
import * as DomEvent from '../../dom/DomEvent';
|
|
4
|
+
import Browser from '../../core/Browser';
|
|
5
|
+
import * as Util from '../../core/Util';
|
|
6
|
+
import {Bounds} from '../../geometry/Bounds';
|
|
7
|
+
|
|
8
|
+
/*
|
|
9
|
+
* @class Canvas
|
|
10
|
+
* @inherits Renderer
|
|
11
|
+
* @aka L.Canvas
|
|
12
|
+
*
|
|
13
|
+
* Allows vector layers to be displayed with [`<canvas>`](https://developer.mozilla.org/docs/Web/API/Canvas_API).
|
|
14
|
+
* Inherits `Renderer`.
|
|
15
|
+
*
|
|
16
|
+
* Due to [technical limitations](https://caniuse.com/canvas), Canvas is not
|
|
17
|
+
* available in all web browsers, notably IE8, and overlapping geometries might
|
|
18
|
+
* not display properly in some edge cases.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
*
|
|
22
|
+
* Use Canvas by default for all paths in the map:
|
|
23
|
+
*
|
|
24
|
+
* ```js
|
|
25
|
+
* var map = L.map('map', {
|
|
26
|
+
* renderer: L.canvas()
|
|
27
|
+
* });
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* Use a Canvas renderer with extra padding for specific vector geometries:
|
|
31
|
+
*
|
|
32
|
+
* ```js
|
|
33
|
+
* var map = L.map('map');
|
|
34
|
+
* var myRenderer = L.canvas({ padding: 0.5 });
|
|
35
|
+
* var line = L.polyline( coordinates, { renderer: myRenderer } );
|
|
36
|
+
* var circle = L.circle( center, { renderer: myRenderer } );
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
export var Canvas = Renderer.extend({
|
|
41
|
+
|
|
42
|
+
// @section
|
|
43
|
+
// @aka Canvas options
|
|
44
|
+
options: {
|
|
45
|
+
// @option tolerance: Number = 0
|
|
46
|
+
// How much to extend the click tolerance around a path/object on the map.
|
|
47
|
+
tolerance: 0
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
getEvents: function () {
|
|
51
|
+
var events = Renderer.prototype.getEvents.call(this);
|
|
52
|
+
events.viewprereset = this._onViewPreReset;
|
|
53
|
+
return events;
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
_onViewPreReset: function () {
|
|
57
|
+
// Set a flag so that a viewprereset+moveend+viewreset only updates&redraws once
|
|
58
|
+
this._postponeUpdatePaths = true;
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
onAdd: function () {
|
|
62
|
+
Renderer.prototype.onAdd.call(this);
|
|
63
|
+
|
|
64
|
+
// Redraw vectors since canvas is cleared upon removal,
|
|
65
|
+
// in case of removing the renderer itself from the map.
|
|
66
|
+
this._draw();
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
_initContainer: function () {
|
|
70
|
+
var container = this._container = document.createElement('canvas');
|
|
71
|
+
|
|
72
|
+
DomEvent.on(container, 'mousemove', this._onMouseMove, this);
|
|
73
|
+
DomEvent.on(container, 'click dblclick mousedown mouseup contextmenu', this._onClick, this);
|
|
74
|
+
DomEvent.on(container, 'mouseout', this._handleMouseOut, this);
|
|
75
|
+
container['_leaflet_disable_events'] = true;
|
|
76
|
+
|
|
77
|
+
this._ctx = container.getContext('2d');
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
_destroyContainer: function () {
|
|
81
|
+
Util.cancelAnimFrame(this._redrawRequest);
|
|
82
|
+
delete this._ctx;
|
|
83
|
+
DomUtil.remove(this._container);
|
|
84
|
+
DomEvent.off(this._container);
|
|
85
|
+
delete this._container;
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
_updatePaths: function () {
|
|
89
|
+
if (this._postponeUpdatePaths) { return; }
|
|
90
|
+
|
|
91
|
+
var layer;
|
|
92
|
+
this._redrawBounds = null;
|
|
93
|
+
for (var id in this._layers) {
|
|
94
|
+
layer = this._layers[id];
|
|
95
|
+
layer._update();
|
|
96
|
+
}
|
|
97
|
+
this._redraw();
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
_update: function () {
|
|
101
|
+
if (this._map._animatingZoom && this._bounds) { return; }
|
|
102
|
+
|
|
103
|
+
Renderer.prototype._update.call(this);
|
|
104
|
+
|
|
105
|
+
var b = this._bounds,
|
|
106
|
+
container = this._container,
|
|
107
|
+
size = b.getSize(),
|
|
108
|
+
m = Browser.retina ? 2 : 1;
|
|
109
|
+
|
|
110
|
+
DomUtil.setPosition(container, b.min);
|
|
111
|
+
|
|
112
|
+
// set canvas size (also clearing it); use double size on retina
|
|
113
|
+
container.width = m * size.x;
|
|
114
|
+
container.height = m * size.y;
|
|
115
|
+
container.style.width = size.x + 'px';
|
|
116
|
+
container.style.height = size.y + 'px';
|
|
117
|
+
|
|
118
|
+
if (Browser.retina) {
|
|
119
|
+
this._ctx.scale(2, 2);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// translate so we use the same path coordinates after canvas element moves
|
|
123
|
+
this._ctx.translate(-b.min.x, -b.min.y);
|
|
124
|
+
|
|
125
|
+
// Tell paths to redraw themselves
|
|
126
|
+
this.fire('update');
|
|
127
|
+
},
|
|
128
|
+
|
|
129
|
+
_reset: function () {
|
|
130
|
+
Renderer.prototype._reset.call(this);
|
|
131
|
+
|
|
132
|
+
if (this._postponeUpdatePaths) {
|
|
133
|
+
this._postponeUpdatePaths = false;
|
|
134
|
+
this._updatePaths();
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
|
|
138
|
+
_initPath: function (layer) {
|
|
139
|
+
this._updateDashArray(layer);
|
|
140
|
+
this._layers[Util.stamp(layer)] = layer;
|
|
141
|
+
|
|
142
|
+
var order = layer._order = {
|
|
143
|
+
layer: layer,
|
|
144
|
+
prev: this._drawLast,
|
|
145
|
+
next: null
|
|
146
|
+
};
|
|
147
|
+
if (this._drawLast) { this._drawLast.next = order; }
|
|
148
|
+
this._drawLast = order;
|
|
149
|
+
this._drawFirst = this._drawFirst || this._drawLast;
|
|
150
|
+
},
|
|
151
|
+
|
|
152
|
+
_addPath: function (layer) {
|
|
153
|
+
this._requestRedraw(layer);
|
|
154
|
+
},
|
|
155
|
+
|
|
156
|
+
_removePath: function (layer) {
|
|
157
|
+
var order = layer._order;
|
|
158
|
+
var next = order.next;
|
|
159
|
+
var prev = order.prev;
|
|
160
|
+
|
|
161
|
+
if (next) {
|
|
162
|
+
next.prev = prev;
|
|
163
|
+
} else {
|
|
164
|
+
this._drawLast = prev;
|
|
165
|
+
}
|
|
166
|
+
if (prev) {
|
|
167
|
+
prev.next = next;
|
|
168
|
+
} else {
|
|
169
|
+
this._drawFirst = next;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
delete layer._order;
|
|
173
|
+
|
|
174
|
+
delete this._layers[Util.stamp(layer)];
|
|
175
|
+
|
|
176
|
+
this._requestRedraw(layer);
|
|
177
|
+
},
|
|
178
|
+
|
|
179
|
+
_updatePath: function (layer) {
|
|
180
|
+
// Redraw the union of the layer's old pixel
|
|
181
|
+
// bounds and the new pixel bounds.
|
|
182
|
+
this._extendRedrawBounds(layer);
|
|
183
|
+
layer._project();
|
|
184
|
+
layer._update();
|
|
185
|
+
// The redraw will extend the redraw bounds
|
|
186
|
+
// with the new pixel bounds.
|
|
187
|
+
this._requestRedraw(layer);
|
|
188
|
+
},
|
|
189
|
+
|
|
190
|
+
_updateStyle: function (layer) {
|
|
191
|
+
this._updateDashArray(layer);
|
|
192
|
+
this._requestRedraw(layer);
|
|
193
|
+
},
|
|
194
|
+
|
|
195
|
+
_updateDashArray: function (layer) {
|
|
196
|
+
if (typeof layer.options.dashArray === 'string') {
|
|
197
|
+
var parts = layer.options.dashArray.split(/[, ]+/),
|
|
198
|
+
dashArray = [],
|
|
199
|
+
dashValue,
|
|
200
|
+
i;
|
|
201
|
+
for (i = 0; i < parts.length; i++) {
|
|
202
|
+
dashValue = Number(parts[i]);
|
|
203
|
+
// Ignore dash array containing invalid lengths
|
|
204
|
+
if (isNaN(dashValue)) { return; }
|
|
205
|
+
dashArray.push(dashValue);
|
|
206
|
+
}
|
|
207
|
+
layer.options._dashArray = dashArray;
|
|
208
|
+
} else {
|
|
209
|
+
layer.options._dashArray = layer.options.dashArray;
|
|
210
|
+
}
|
|
211
|
+
},
|
|
212
|
+
|
|
213
|
+
_requestRedraw: function (layer) {
|
|
214
|
+
if (!this._map) { return; }
|
|
215
|
+
|
|
216
|
+
this._extendRedrawBounds(layer);
|
|
217
|
+
this._redrawRequest = this._redrawRequest || Util.requestAnimFrame(this._redraw, this);
|
|
218
|
+
},
|
|
219
|
+
|
|
220
|
+
_extendRedrawBounds: function (layer) {
|
|
221
|
+
if (layer._pxBounds) {
|
|
222
|
+
var padding = (layer.options.weight || 0) + 1;
|
|
223
|
+
this._redrawBounds = this._redrawBounds || new Bounds();
|
|
224
|
+
this._redrawBounds.extend(layer._pxBounds.min.subtract([padding, padding]));
|
|
225
|
+
this._redrawBounds.extend(layer._pxBounds.max.add([padding, padding]));
|
|
226
|
+
}
|
|
227
|
+
},
|
|
228
|
+
|
|
229
|
+
_redraw: function () {
|
|
230
|
+
this._redrawRequest = null;
|
|
231
|
+
|
|
232
|
+
if (this._redrawBounds) {
|
|
233
|
+
this._redrawBounds.min._floor();
|
|
234
|
+
this._redrawBounds.max._ceil();
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
this._clear(); // clear layers in redraw bounds
|
|
238
|
+
this._draw(); // draw layers
|
|
239
|
+
|
|
240
|
+
this._redrawBounds = null;
|
|
241
|
+
},
|
|
242
|
+
|
|
243
|
+
_clear: function () {
|
|
244
|
+
var bounds = this._redrawBounds;
|
|
245
|
+
if (bounds) {
|
|
246
|
+
var size = bounds.getSize();
|
|
247
|
+
this._ctx.clearRect(bounds.min.x, bounds.min.y, size.x, size.y);
|
|
248
|
+
} else {
|
|
249
|
+
this._ctx.save();
|
|
250
|
+
this._ctx.setTransform(1, 0, 0, 1, 0, 0);
|
|
251
|
+
this._ctx.clearRect(0, 0, this._container.width, this._container.height);
|
|
252
|
+
this._ctx.restore();
|
|
253
|
+
}
|
|
254
|
+
},
|
|
255
|
+
|
|
256
|
+
_draw: function () {
|
|
257
|
+
var layer, bounds = this._redrawBounds;
|
|
258
|
+
this._ctx.save();
|
|
259
|
+
if (bounds) {
|
|
260
|
+
var size = bounds.getSize();
|
|
261
|
+
this._ctx.beginPath();
|
|
262
|
+
this._ctx.rect(bounds.min.x, bounds.min.y, size.x, size.y);
|
|
263
|
+
this._ctx.clip();
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
this._drawing = true;
|
|
267
|
+
|
|
268
|
+
for (var order = this._drawFirst; order; order = order.next) {
|
|
269
|
+
layer = order.layer;
|
|
270
|
+
if (!bounds || (layer._pxBounds && layer._pxBounds.intersects(bounds))) {
|
|
271
|
+
layer._updatePath();
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
this._drawing = false;
|
|
276
|
+
|
|
277
|
+
this._ctx.restore(); // Restore state before clipping.
|
|
278
|
+
},
|
|
279
|
+
|
|
280
|
+
_updatePoly: function (layer, closed) {
|
|
281
|
+
if (!this._drawing) { return; }
|
|
282
|
+
|
|
283
|
+
var i, j, len2, p,
|
|
284
|
+
parts = layer._parts,
|
|
285
|
+
len = parts.length,
|
|
286
|
+
ctx = this._ctx;
|
|
287
|
+
|
|
288
|
+
if (!len) { return; }
|
|
289
|
+
|
|
290
|
+
ctx.beginPath();
|
|
291
|
+
|
|
292
|
+
for (i = 0; i < len; i++) {
|
|
293
|
+
for (j = 0, len2 = parts[i].length; j < len2; j++) {
|
|
294
|
+
p = parts[i][j];
|
|
295
|
+
ctx[j ? 'lineTo' : 'moveTo'](p.x, p.y);
|
|
296
|
+
}
|
|
297
|
+
if (closed) {
|
|
298
|
+
ctx.closePath();
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
this._fillStroke(ctx, layer);
|
|
303
|
+
|
|
304
|
+
// TODO optimization: 1 fill/stroke for all features with equal style instead of 1 for each feature
|
|
305
|
+
},
|
|
306
|
+
|
|
307
|
+
_updateCircle: function (layer) {
|
|
308
|
+
|
|
309
|
+
if (!this._drawing || layer._empty()) { return; }
|
|
310
|
+
|
|
311
|
+
var p = layer._point,
|
|
312
|
+
ctx = this._ctx,
|
|
313
|
+
r = Math.max(Math.round(layer._radius), 1),
|
|
314
|
+
s = (Math.max(Math.round(layer._radiusY), 1) || r) / r;
|
|
315
|
+
|
|
316
|
+
if (s !== 1) {
|
|
317
|
+
ctx.save();
|
|
318
|
+
ctx.scale(1, s);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
ctx.beginPath();
|
|
322
|
+
ctx.arc(p.x, p.y / s, r, 0, Math.PI * 2, false);
|
|
323
|
+
|
|
324
|
+
if (s !== 1) {
|
|
325
|
+
ctx.restore();
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
this._fillStroke(ctx, layer);
|
|
329
|
+
},
|
|
330
|
+
|
|
331
|
+
_fillStroke: function (ctx, layer) {
|
|
332
|
+
var options = layer.options;
|
|
333
|
+
|
|
334
|
+
if (options.fill) {
|
|
335
|
+
ctx.globalAlpha = options.fillOpacity;
|
|
336
|
+
ctx.fillStyle = options.fillColor || options.color;
|
|
337
|
+
ctx.fill(options.fillRule || 'evenodd');
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
if (options.stroke && options.weight !== 0) {
|
|
341
|
+
if (ctx.setLineDash) {
|
|
342
|
+
ctx.lineDashOffset = Number(options.dashOffset || 0);
|
|
343
|
+
ctx.setLineDash(options._dashArray || []);
|
|
344
|
+
}
|
|
345
|
+
ctx.globalAlpha = options.opacity;
|
|
346
|
+
ctx.lineWidth = options.weight;
|
|
347
|
+
ctx.strokeStyle = options.color;
|
|
348
|
+
ctx.lineCap = options.lineCap;
|
|
349
|
+
ctx.lineJoin = options.lineJoin;
|
|
350
|
+
ctx.stroke();
|
|
351
|
+
}
|
|
352
|
+
},
|
|
353
|
+
|
|
354
|
+
// Canvas obviously doesn't have mouse events for individual drawn objects,
|
|
355
|
+
// so we emulate that by calculating what's under the mouse on mousemove/click manually
|
|
356
|
+
|
|
357
|
+
_onClick: function (e) {
|
|
358
|
+
var point = this._map.mouseEventToLayerPoint(e), layer, clickedLayer;
|
|
359
|
+
|
|
360
|
+
for (var order = this._drawFirst; order; order = order.next) {
|
|
361
|
+
layer = order.layer;
|
|
362
|
+
if (layer.options.interactive && layer._containsPoint(point)) {
|
|
363
|
+
if (!(e.type === 'click' || e.type === 'preclick') || !this._map._draggableMoved(layer)) {
|
|
364
|
+
clickedLayer = layer;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
this._fireEvent(clickedLayer ? [clickedLayer] : false, e);
|
|
369
|
+
},
|
|
370
|
+
|
|
371
|
+
_onMouseMove: function (e) {
|
|
372
|
+
if (!this._map || this._map.dragging.moving() || this._map._animatingZoom) { return; }
|
|
373
|
+
|
|
374
|
+
var point = this._map.mouseEventToLayerPoint(e);
|
|
375
|
+
this._handleMouseHover(e, point);
|
|
376
|
+
},
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
_handleMouseOut: function (e) {
|
|
380
|
+
var layer = this._hoveredLayer;
|
|
381
|
+
if (layer) {
|
|
382
|
+
// if we're leaving the layer, fire mouseout
|
|
383
|
+
DomUtil.removeClass(this._container, 'leaflet-interactive');
|
|
384
|
+
this._fireEvent([layer], e, 'mouseout');
|
|
385
|
+
this._hoveredLayer = null;
|
|
386
|
+
this._mouseHoverThrottled = false;
|
|
387
|
+
}
|
|
388
|
+
},
|
|
389
|
+
|
|
390
|
+
_handleMouseHover: function (e, point) {
|
|
391
|
+
if (this._mouseHoverThrottled) {
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
var layer, candidateHoveredLayer;
|
|
396
|
+
|
|
397
|
+
for (var order = this._drawFirst; order; order = order.next) {
|
|
398
|
+
layer = order.layer;
|
|
399
|
+
if (layer.options.interactive && layer._containsPoint(point)) {
|
|
400
|
+
candidateHoveredLayer = layer;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
if (candidateHoveredLayer !== this._hoveredLayer) {
|
|
405
|
+
this._handleMouseOut(e);
|
|
406
|
+
|
|
407
|
+
if (candidateHoveredLayer) {
|
|
408
|
+
DomUtil.addClass(this._container, 'leaflet-interactive'); // change cursor
|
|
409
|
+
this._fireEvent([candidateHoveredLayer], e, 'mouseover');
|
|
410
|
+
this._hoveredLayer = candidateHoveredLayer;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
this._fireEvent(this._hoveredLayer ? [this._hoveredLayer] : false, e);
|
|
415
|
+
|
|
416
|
+
this._mouseHoverThrottled = true;
|
|
417
|
+
setTimeout(Util.bind(function () {
|
|
418
|
+
this._mouseHoverThrottled = false;
|
|
419
|
+
}, this), 32);
|
|
420
|
+
},
|
|
421
|
+
|
|
422
|
+
_fireEvent: function (layers, e, type) {
|
|
423
|
+
this._map._fireDOMEvent(e, type || e.type, layers);
|
|
424
|
+
},
|
|
425
|
+
|
|
426
|
+
_bringToFront: function (layer) {
|
|
427
|
+
var order = layer._order;
|
|
428
|
+
|
|
429
|
+
if (!order) { return; }
|
|
430
|
+
|
|
431
|
+
var next = order.next;
|
|
432
|
+
var prev = order.prev;
|
|
433
|
+
|
|
434
|
+
if (next) {
|
|
435
|
+
next.prev = prev;
|
|
436
|
+
} else {
|
|
437
|
+
// Already last
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
if (prev) {
|
|
441
|
+
prev.next = next;
|
|
442
|
+
} else if (next) {
|
|
443
|
+
// Update first entry unless this is the
|
|
444
|
+
// single entry
|
|
445
|
+
this._drawFirst = next;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
order.prev = this._drawLast;
|
|
449
|
+
this._drawLast.next = order;
|
|
450
|
+
|
|
451
|
+
order.next = null;
|
|
452
|
+
this._drawLast = order;
|
|
453
|
+
|
|
454
|
+
this._requestRedraw(layer);
|
|
455
|
+
},
|
|
456
|
+
|
|
457
|
+
_bringToBack: function (layer) {
|
|
458
|
+
var order = layer._order;
|
|
459
|
+
|
|
460
|
+
if (!order) { return; }
|
|
461
|
+
|
|
462
|
+
var next = order.next;
|
|
463
|
+
var prev = order.prev;
|
|
464
|
+
|
|
465
|
+
if (prev) {
|
|
466
|
+
prev.next = next;
|
|
467
|
+
} else {
|
|
468
|
+
// Already first
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
if (next) {
|
|
472
|
+
next.prev = prev;
|
|
473
|
+
} else if (prev) {
|
|
474
|
+
// Update last entry unless this is the
|
|
475
|
+
// single entry
|
|
476
|
+
this._drawLast = prev;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
order.prev = null;
|
|
480
|
+
|
|
481
|
+
order.next = this._drawFirst;
|
|
482
|
+
this._drawFirst.prev = order;
|
|
483
|
+
this._drawFirst = order;
|
|
484
|
+
|
|
485
|
+
this._requestRedraw(layer);
|
|
486
|
+
}
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
// @factory L.canvas(options?: Renderer options)
|
|
490
|
+
// Creates a Canvas renderer with the given options.
|
|
491
|
+
export function canvas(options) {
|
|
492
|
+
return Browser.canvas ? new Canvas(options) : null;
|
|
493
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import {CircleMarker} from './CircleMarker';
|
|
2
|
+
import {Path} from './Path';
|
|
3
|
+
import * as Util from '../../core/Util';
|
|
4
|
+
import {toLatLng} from '../../geo/LatLng';
|
|
5
|
+
import {LatLngBounds} from '../../geo/LatLngBounds';
|
|
6
|
+
import {Earth} from '../../geo/crs/CRS.Earth';
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
/*
|
|
10
|
+
* @class Circle
|
|
11
|
+
* @aka L.Circle
|
|
12
|
+
* @inherits CircleMarker
|
|
13
|
+
*
|
|
14
|
+
* A class for drawing circle overlays on a map. Extends `CircleMarker`.
|
|
15
|
+
*
|
|
16
|
+
* It's an approximation and starts to diverge from a real circle closer to poles (due to projection distortion).
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
*
|
|
20
|
+
* ```js
|
|
21
|
+
* L.circle([50.5, 30.5], {radius: 200}).addTo(map);
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
export var Circle = CircleMarker.extend({
|
|
26
|
+
|
|
27
|
+
initialize: function (latlng, options, legacyOptions) {
|
|
28
|
+
if (typeof options === 'number') {
|
|
29
|
+
// Backwards compatibility with 0.7.x factory (latlng, radius, options?)
|
|
30
|
+
options = Util.extend({}, legacyOptions, {radius: options});
|
|
31
|
+
}
|
|
32
|
+
Util.setOptions(this, options);
|
|
33
|
+
this._latlng = toLatLng(latlng);
|
|
34
|
+
|
|
35
|
+
if (isNaN(this.options.radius)) { throw new Error('Circle radius cannot be NaN'); }
|
|
36
|
+
|
|
37
|
+
// @section
|
|
38
|
+
// @aka Circle options
|
|
39
|
+
// @option radius: Number; Radius of the circle, in meters.
|
|
40
|
+
this._mRadius = this.options.radius;
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
// @method setRadius(radius: Number): this
|
|
44
|
+
// Sets the radius of a circle. Units are in meters.
|
|
45
|
+
setRadius: function (radius) {
|
|
46
|
+
this._mRadius = radius;
|
|
47
|
+
return this.redraw();
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
// @method getRadius(): Number
|
|
51
|
+
// Returns the current radius of a circle. Units are in meters.
|
|
52
|
+
getRadius: function () {
|
|
53
|
+
return this._mRadius;
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
// @method getBounds(): LatLngBounds
|
|
57
|
+
// Returns the `LatLngBounds` of the path.
|
|
58
|
+
getBounds: function () {
|
|
59
|
+
var half = [this._radius, this._radiusY || this._radius];
|
|
60
|
+
|
|
61
|
+
return new LatLngBounds(
|
|
62
|
+
this._map.layerPointToLatLng(this._point.subtract(half)),
|
|
63
|
+
this._map.layerPointToLatLng(this._point.add(half)));
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
setStyle: Path.prototype.setStyle,
|
|
67
|
+
|
|
68
|
+
_project: function () {
|
|
69
|
+
|
|
70
|
+
var lng = this._latlng.lng,
|
|
71
|
+
lat = this._latlng.lat,
|
|
72
|
+
map = this._map,
|
|
73
|
+
crs = map.options.crs;
|
|
74
|
+
|
|
75
|
+
if (crs.distance === Earth.distance) {
|
|
76
|
+
var d = Math.PI / 180,
|
|
77
|
+
latR = (this._mRadius / Earth.R) / d,
|
|
78
|
+
top = map.project([lat + latR, lng]),
|
|
79
|
+
bottom = map.project([lat - latR, lng]),
|
|
80
|
+
p = top.add(bottom).divideBy(2),
|
|
81
|
+
lat2 = map.unproject(p).lat,
|
|
82
|
+
lngR = Math.acos((Math.cos(latR * d) - Math.sin(lat * d) * Math.sin(lat2 * d)) /
|
|
83
|
+
(Math.cos(lat * d) * Math.cos(lat2 * d))) / d;
|
|
84
|
+
|
|
85
|
+
if (isNaN(lngR) || lngR === 0) {
|
|
86
|
+
lngR = latR / Math.cos(Math.PI / 180 * lat); // Fallback for edge case, #2425
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
this._point = p.subtract(map.getPixelOrigin());
|
|
90
|
+
this._radius = isNaN(lngR) ? 0 : p.x - map.project([lat2, lng - lngR]).x;
|
|
91
|
+
this._radiusY = p.y - top.y;
|
|
92
|
+
|
|
93
|
+
} else {
|
|
94
|
+
var latlng2 = crs.unproject(crs.project(this._latlng).subtract([this._mRadius, 0]));
|
|
95
|
+
|
|
96
|
+
this._point = map.latLngToLayerPoint(this._latlng);
|
|
97
|
+
this._radius = this._point.x - map.latLngToLayerPoint(latlng2).x;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
this._updateBounds();
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// @factory L.circle(latlng: LatLng, options?: Circle options)
|
|
105
|
+
// Instantiates a circle object given a geographical point, and an options object
|
|
106
|
+
// which contains the circle radius.
|
|
107
|
+
// @alternative
|
|
108
|
+
// @factory L.circle(latlng: LatLng, radius: Number, options?: Circle options)
|
|
109
|
+
// Obsolete way of instantiating a circle, for compatibility with 0.7.x code.
|
|
110
|
+
// Do not use in new applications or plugins.
|
|
111
|
+
export function circle(latlng, options, legacyOptions) {
|
|
112
|
+
return new Circle(latlng, options, legacyOptions);
|
|
113
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import {Path} from './Path';
|
|
2
|
+
import * as Util from '../../core/Util';
|
|
3
|
+
import {toLatLng} from '../../geo/LatLng';
|
|
4
|
+
import {Bounds} from '../../geometry/Bounds';
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
/*
|
|
8
|
+
* @class CircleMarker
|
|
9
|
+
* @aka L.CircleMarker
|
|
10
|
+
* @inherits Path
|
|
11
|
+
*
|
|
12
|
+
* A circle of a fixed size with radius specified in pixels. Extends `Path`.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
export var CircleMarker = Path.extend({
|
|
16
|
+
|
|
17
|
+
// @section
|
|
18
|
+
// @aka CircleMarker options
|
|
19
|
+
options: {
|
|
20
|
+
fill: true,
|
|
21
|
+
|
|
22
|
+
// @option radius: Number = 10
|
|
23
|
+
// Radius of the circle marker, in pixels
|
|
24
|
+
radius: 10
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
initialize: function (latlng, options) {
|
|
28
|
+
Util.setOptions(this, options);
|
|
29
|
+
this._latlng = toLatLng(latlng);
|
|
30
|
+
this._radius = this.options.radius;
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
// @method setLatLng(latLng: LatLng): this
|
|
34
|
+
// Sets the position of a circle marker to a new location.
|
|
35
|
+
setLatLng: function (latlng) {
|
|
36
|
+
var oldLatLng = this._latlng;
|
|
37
|
+
this._latlng = toLatLng(latlng);
|
|
38
|
+
this.redraw();
|
|
39
|
+
|
|
40
|
+
// @event move: Event
|
|
41
|
+
// Fired when the marker is moved via [`setLatLng`](#circlemarker-setlatlng). Old and new coordinates are included in event arguments as `oldLatLng`, `latlng`.
|
|
42
|
+
return this.fire('move', {oldLatLng: oldLatLng, latlng: this._latlng});
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
// @method getLatLng(): LatLng
|
|
46
|
+
// Returns the current geographical position of the circle marker
|
|
47
|
+
getLatLng: function () {
|
|
48
|
+
return this._latlng;
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
// @method setRadius(radius: Number): this
|
|
52
|
+
// Sets the radius of a circle marker. Units are in pixels.
|
|
53
|
+
setRadius: function (radius) {
|
|
54
|
+
this.options.radius = this._radius = radius;
|
|
55
|
+
return this.redraw();
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
// @method getRadius(): Number
|
|
59
|
+
// Returns the current radius of the circle
|
|
60
|
+
getRadius: function () {
|
|
61
|
+
return this._radius;
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
setStyle : function (options) {
|
|
65
|
+
var radius = options && options.radius || this._radius;
|
|
66
|
+
Path.prototype.setStyle.call(this, options);
|
|
67
|
+
this.setRadius(radius);
|
|
68
|
+
return this;
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
_project: function () {
|
|
72
|
+
this._point = this._map.latLngToLayerPoint(this._latlng);
|
|
73
|
+
this._updateBounds();
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
_updateBounds: function () {
|
|
77
|
+
var r = this._radius,
|
|
78
|
+
r2 = this._radiusY || r,
|
|
79
|
+
w = this._clickTolerance(),
|
|
80
|
+
p = [r + w, r2 + w];
|
|
81
|
+
this._pxBounds = new Bounds(this._point.subtract(p), this._point.add(p));
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
_update: function () {
|
|
85
|
+
if (this._map) {
|
|
86
|
+
this._updatePath();
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
_updatePath: function () {
|
|
91
|
+
this._renderer._updateCircle(this);
|
|
92
|
+
},
|
|
93
|
+
|
|
94
|
+
_empty: function () {
|
|
95
|
+
return this._radius && !this._renderer._bounds.intersects(this._pxBounds);
|
|
96
|
+
},
|
|
97
|
+
|
|
98
|
+
// Needed by the `Canvas` renderer for interactivity
|
|
99
|
+
_containsPoint: function (p) {
|
|
100
|
+
return p.distanceTo(this._point) <= this._radius + this._clickTolerance();
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
// @factory L.circleMarker(latlng: LatLng, options?: CircleMarker options)
|
|
106
|
+
// Instantiates a circle marker object given a geographical point, and an optional options object.
|
|
107
|
+
export function circleMarker(latlng, options) {
|
|
108
|
+
return new CircleMarker(latlng, options);
|
|
109
|
+
}
|