leaflet-rotate 0.2.5 → 0.2.6

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.
@@ -1,1932 +1,2 @@
1
- (function (factory) {
2
- typeof define === 'function' && define.amd ? define(factory) :
3
- factory();
4
- })((function () { 'use strict';
5
-
6
- /**
7
- * @external L.DomUtil
8
- *
9
- * @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/dom/DomUtil.js
10
- */
11
-
12
- const domUtilProto = L.extend({}, L.DomUtil);
13
-
14
- L.extend(L.DomUtil, {
15
-
16
- /**
17
- * Resets the 3D CSS transform of `el` so it is
18
- * translated by `offset` pixels and optionally
19
- * scaled by `scale`. Does not have an effect if
20
- * the browser doesn't support 3D CSS transforms.
21
- *
22
- * @param {HTMLElement} el
23
- * @param {L.Point} offset
24
- * @param {Number} scale
25
- * @param {Number} bearing
26
- * @param {L.Point} pivot
27
- */
28
- setTransform: function(el, offset, scale, bearing, pivot) {
29
- var pos = offset || new L.Point(0, 0);
30
-
31
- if (!bearing) {
32
- offset = pos._round();
33
- return domUtilProto.setTransform.apply(this, arguments);
34
- }
35
-
36
- pos = pos.rotateFrom(bearing, pivot);
37
-
38
- el.style[L.DomUtil.TRANSFORM] =
39
- 'translate3d(' + pos.x + 'px,' + pos.y + 'px' + ',0)' +
40
- (scale ? ' scale(' + scale + ')' : '') +
41
- ' rotate(' + bearing + 'rad)';
42
- },
43
-
44
- /**
45
- * Sets the position of `el` to coordinates specified by
46
- * `position`, using CSS translate or top/left positioning
47
- * depending on the browser (used by Leaflet internally
48
- * to position its layers).
49
- *
50
- * @param {HTMLElement} el
51
- * @param {L.Point} point
52
- * @param {Number} bearing
53
- * @param {L.Point} pivot
54
- * @param {Number} scale
55
- */
56
- setPosition: function(el, point, bearing, pivot, scale) {
57
- if (!bearing) {
58
- return domUtilProto.setPosition.apply(this, arguments);
59
- }
60
-
61
- /*eslint-disable */
62
- el._leaflet_pos = point;
63
- /*eslint-enable */
64
-
65
- if (L.Browser.any3d) {
66
- L.DomUtil.setTransform(el, point, scale, bearing, pivot);
67
- } else {
68
- el.style.left = point.x + 'px';
69
- el.style.top = point.y + 'px';
70
- }
71
- },
72
-
73
- /**
74
- * @constant radians = degrees × π/180°
75
- */
76
- DEG_TO_RAD: Math.PI / 180,
77
-
78
- /**
79
- * @constant degrees = radians × 180°/π
80
- */
81
- RAD_TO_DEG: 180 / Math.PI,
82
-
83
- });
84
-
85
- /**
86
- * @external L.Draggable
87
- *
88
- * @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/dom/Draggable.js
89
- */
90
-
91
- /**
92
- * A class for making DOM elements draggable (including touch support).
93
- * Used internally for map and marker dragging. Only works for elements
94
- * that were positioned with [`L.DomUtil.setPosition`](#domutil-setposition).
95
- */
96
-
97
- L.Draggable.include({
98
-
99
- /** @TODO */
100
- // updateMapBearing: function(mapBearing) {
101
- // this._mapBearing = mapBearing;
102
- // },
103
-
104
- });
105
-
106
- /**
107
- * @external L.Point
108
- *
109
- * @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/geometry/Point.js
110
- */
111
-
112
- L.extend(L.Point.prototype, {
113
-
114
- /**
115
- * Rotate around (0,0) by applying the 2D rotation matrix:
116
- *
117
- * ⎡ x' ⎤ = ⎡ cos θ -sin θ ⎤ ⎡ x ⎤
118
- * ⎣ y' ⎦ ⎣ sin θ cos θ ⎦ ⎣ y ⎦
119
- *
120
- * @param theta must be given in radians.
121
- */
122
- rotate: function(theta) {
123
- return this.rotateFrom(theta, new L.Point(0,0))
124
- },
125
-
126
- /**
127
- * Rotate around (pivot.x, pivot.y) by:
128
- *
129
- * 1. subtract (pivot.x, pivot.y)
130
- * 2. rotate around (0, 0)
131
- * 3. add (pivot.x, pivot.y) back
132
- *
133
- * same as `this.subtract(pivot).rotate(theta).add(pivot)`
134
- *
135
- * @param {Number} theta
136
- * @param {L.Point} pivot
137
- *
138
- * @returns {L.Point}
139
- */
140
- rotateFrom: function(theta, pivot) {
141
- if (!theta) { return this; }
142
- var sinTheta = Math.sin(theta);
143
- var cosTheta = Math.cos(theta);
144
- var cx = pivot.x,
145
- cy = pivot.y;
146
- var x = this.x - cx,
147
- y = this.y - cy;
148
-
149
- return new L.Point(
150
- x * cosTheta - y * sinTheta + cx,
151
- x * sinTheta + y * cosTheta + cy
152
- );
153
- },
154
-
155
- });
156
-
157
- /**
158
- * @external L.DivOverlay
159
- *
160
- * @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/layer/DivOverlay.js
161
- */
162
-
163
- const divOverlayProto = L.extend({}, L.DivOverlay.prototype);
164
-
165
- L.DivOverlay.include({
166
-
167
- /**
168
- * Update L.Popup and L.Tooltip anchor positions after
169
- * the map is moved by calling `map.setBearing(theta)`
170
- *
171
- * @listens L.Map~rotate
172
- */
173
- getEvents: function() {
174
- return L.extend(divOverlayProto.getEvents.apply(this, arguments), { rotate: this._updatePosition });
175
- },
176
-
177
- /**
178
- * 0. update element anchor point (divOverlayProto v1.9.3)
179
- * 1. rotate around anchor point (subtract anchor -> rotate point -> add anchor)
180
- */
181
- _updatePosition: function() {
182
- if (!this._map) { return; }
183
- divOverlayProto._updatePosition.apply(this, arguments);
184
- if (this._map && this._map._rotate && this._zoomAnimated) {
185
- var anchor = this._getAnchor();
186
- var pos = L.DomUtil.getPosition(this._container).subtract(anchor);
187
- L.DomUtil.setPosition(this._container, this._map.rotatedPointToMapPanePoint(pos).add(anchor));
188
- }
189
-
190
- },
191
-
192
- });
193
-
194
- /**
195
- * @external L.Popup
196
- *
197
- * @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/layer/Popup.js
198
- */
199
-
200
- const popupProto = L.extend({}, L.Popup.prototype);
201
-
202
- L.Popup.include({
203
-
204
- /**
205
- * 0. update element anchor point (popupProto v1.9.3)
206
- * 1. rotate around anchor point (subtract anchor -> rotate point -> add anchor)
207
- */
208
- _animateZoom: function(e) {
209
- popupProto._animateZoom.apply(this, arguments);
210
- if (this._map && this._map._rotate) {
211
- var anchor = this._getAnchor();
212
- var pos = L.DomUtil.getPosition(this._container).subtract(anchor);
213
- L.DomUtil.setPosition(this._container, this._map.rotatedPointToMapPanePoint(pos).add(anchor));
214
- }
215
- },
216
-
217
- /**
218
- * Fix for L.popup({ keepInView = true })
219
- *
220
- * @see https://github.com/fnicollet/Leaflet/pull/21
221
- */
222
- _adjustPan: function() {
223
- if (!this.options.autoPan || (this._map._panAnim && this._map._panAnim._inProgress)) { return; }
224
-
225
- // We can endlessly recurse if keepInView is set and the view resets.
226
- // Let's guard against that by exiting early if we're responding to our own autopan.
227
- if (this._autopanning) {
228
- this._autopanning = false;
229
- return;
230
- }
231
-
232
- var map = this._map,
233
- marginBottom = parseInt(L.DomUtil.getStyle(this._container, 'marginBottom'), 10) || 0,
234
- containerHeight = this._container.offsetHeight + marginBottom,
235
- containerWidth = this._containerWidth,
236
- layerPos = new L.Point(this._containerLeft, -containerHeight - this._containerBottom);
237
-
238
- layerPos._add(L.DomUtil.getPosition(this._container));
239
-
240
- /** @TODO use popupProto._adjustPan */
241
- // var containerPos = map.layerPointToContainerPoint(layerPos);
242
- var containerPos = layerPos._add(this._map._getMapPanePos()),
243
- padding = L.point(this.options.autoPanPadding),
244
- paddingTL = L.point(this.options.autoPanPaddingTopLeft || padding),
245
- paddingBR = L.point(this.options.autoPanPaddingBottomRight || padding),
246
- size = map.getSize(),
247
- dx = 0,
248
- dy = 0;
249
-
250
- if (containerPos.x + containerWidth + paddingBR.x > size.x) { // right
251
- dx = containerPos.x + containerWidth - size.x + paddingBR.x;
252
- }
253
- if (containerPos.x - dx - paddingTL.x < 0) { // left
254
- dx = containerPos.x - paddingTL.x;
255
- }
256
- if (containerPos.y + containerHeight + paddingBR.y > size.y) { // bottom
257
- dy = containerPos.y + containerHeight - size.y + paddingBR.y;
258
- }
259
- if (containerPos.y - dy - paddingTL.y < 0) { // top
260
- dy = containerPos.y - paddingTL.y;
261
- }
262
-
263
- // @namespace Map
264
- // @section Popup events
265
- // @event autopanstart: Event
266
- // Fired when the map starts autopanning when opening a popup.
267
- if (dx || dy) {
268
- // Track that we're autopanning, as this function will be re-ran on moveend
269
- if (this.options.keepInView) {
270
- this._autopanning = true;
271
- }
272
- map
273
- .fire('autopanstart')
274
- .panBy([dx, dy]);
275
- }
276
- },
277
-
278
- });
279
-
280
- /**
281
- * @external L.Tooltip
282
- *
283
- * @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/layer/Tooltip.js
284
- */
285
-
286
- const tooltipProto = L.extend({}, L.Tooltip.prototype);
287
-
288
- L.Tooltip.include({
289
-
290
- _animateZoom: function(e) {
291
- if (!this._map._rotate) {
292
- return tooltipProto._animateZoom.apply(this, arguments);
293
- }
294
- var pos = this._map._latLngToNewLayerPoint(this._latlng, e.zoom, e.center);
295
-
296
- pos = this._map.rotatedPointToMapPanePoint(pos);
297
- this._setPosition(pos);
298
- },
299
-
300
- _updatePosition: function() {
301
- if (!this._map._rotate) {
302
- return tooltipProto._updatePosition.apply(this, arguments);
303
- }
304
- var pos = this._map.latLngToLayerPoint(this._latlng);
305
-
306
- pos = this._map.rotatedPointToMapPanePoint(pos);
307
- this._setPosition(pos);
308
- },
309
-
310
- });
311
-
312
- /**
313
- * @external L.Icon
314
- *
315
- * @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/layer/marker/Icon.js
316
- */
317
-
318
- L.extend({}, L.Icon.prototype);
319
-
320
- L.Icon.include({
321
-
322
- _setIconStyles: function(img, name) {
323
- var options = this.options;
324
- var sizeOption = options[name + 'Size'];
325
-
326
- if (typeof sizeOption === 'number') {
327
- sizeOption = [sizeOption, sizeOption];
328
- }
329
-
330
- var size = L.point(sizeOption),
331
- anchor = L.point(name === 'shadow' && options.shadowAnchor || options.iconAnchor ||
332
- size && size.divideBy(2, true));
333
-
334
- img.className = 'leaflet-marker-' + name + ' ' + (options.className || '');
335
-
336
- if (anchor) {
337
- img.style.marginLeft = (-anchor.x) + 'px';
338
- img.style.marginTop = (-anchor.y) + 'px';
339
- /** @TODO use iconProto._setIconStyles */
340
- img.style[L.DomUtil.TRANSFORM + "Origin"] = anchor.x + "px " + anchor.y + "px 0px";
341
- }
342
-
343
- if (size) {
344
- img.style.width = size.x + 'px';
345
- img.style.height = size.y + 'px';
346
- }
347
- },
348
-
349
- });
350
-
351
- /**
352
- * @external L.Marker
353
- * @external L.Handler.MarkerDrag
354
- *
355
- * @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/layer/marker/Marker.js
356
- * @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/layer/marker/Marker.Drag.js
357
- * @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/dom/Draggable.js
358
- */
359
-
360
- const markerProto = L.extend({}, L.Marker.prototype);
361
-
362
- L.Marker.mergeOptions({
363
-
364
- /**
365
- * Rotation of this marker in rad
366
- *
367
- * @type {Number}
368
- */
369
- rotation: 0,
370
-
371
- /**
372
- * Rotate this marker when map rotates
373
- *
374
- * @type {Boolean}
375
- */
376
- rotateWithView: false,
377
-
378
- /**
379
- * Scale of the marker icon
380
- *
381
- * @type {Number}
382
- */
383
- scale: undefined,
384
-
385
- });
386
-
387
- var markerDragProto; // retrived at runtime (see below: L.Marker::_initInteraction())
388
-
389
- var MarkerDrag = {
390
-
391
- // _onDragStart: function() {
392
- // if (!this._marker._map._rotate) {
393
- // return markerDragProto._onDragStart.apply(this, arguments);
394
- // }
395
- // this._draggable.updateMapBearing(this._marker._map._bearing);
396
- // },
397
-
398
- _onDrag: function(e) {
399
- var marker = this._marker,
400
- /** @TODO use markerDragProto._onDrag */
401
- rotated_marker = marker.options.rotation || marker.options.rotateWithView,
402
- shadow = marker._shadow,
403
- iconPos = L.DomUtil.getPosition(marker._icon);
404
-
405
- /** @TODO use markerDragProto._onDrag */
406
- // update shadow position
407
- if (!rotated_marker && shadow) {
408
- L.DomUtil.setPosition(shadow, iconPos);
409
- }
410
-
411
- /** @TODO use markerDragProto._onDrag */
412
- if (marker._map._rotate) {
413
- // Reverse calculation from mapPane coordinates to rotatePane coordinates
414
- iconPos = marker._map.mapPanePointToRotatedPoint(iconPos);
415
- }
416
- var latlng = marker._map.layerPointToLatLng(iconPos);
417
-
418
- marker._latlng = latlng;
419
- e.latlng = latlng;
420
- e.oldLatLng = this._oldLatLng;
421
-
422
- /** @TODO use markerDragProto._onDrag */
423
- if (rotated_marker) marker.setLatLng(latlng); // use `setLatLng` to presisit rotation. low efficiency
424
- else marker.fire('move', e); // `setLatLng` will trig 'move' event. we imitate here.
425
-
426
- // @event drag: Event
427
- // Fired repeatedly while the user drags the marker.
428
- marker
429
- .fire('drag', e);
430
- },
431
-
432
- _onDragEnd: function(e) {
433
- if (this._marker._map._rotate) {
434
- this._marker.update();
435
- }
436
- markerDragProto._onDragEnd.apply(this, arguments);
437
- },
438
-
439
- };
440
-
441
- L.Marker.include({
442
-
443
- /**
444
- * Update L.Marker anchor position after the map
445
- * is moved by calling `map.setBearing(theta)`
446
- *
447
- * @listens L.Map~rotate
448
- */
449
- getEvents: function() {
450
- return L.extend(markerProto.getEvents.apply(this, arguments), { rotate: this.update });
451
- },
452
-
453
- _initInteraction: function() {
454
- var ret = markerProto._initInteraction.apply(this, arguments);
455
- if (this.dragging && this.dragging.enabled() && this._map && this._map._rotate) {
456
- // L.Handler.MarkerDrag is used internally by L.Marker to make the markers draggable
457
- markerDragProto = markerDragProto || Object.getPrototypeOf(this.dragging);
458
- Object.assign(this.dragging, {
459
- // _onDragStart: MarkerDrag._onDragStart.bind(this.dragging),
460
- _onDrag: MarkerDrag._onDrag.bind(this.dragging),
461
- _onDragEnd: MarkerDrag._onDragEnd.bind(this.dragging),
462
- });
463
- this.dragging.disable();
464
- this.dragging.enable();
465
- }
466
- return ret;
467
- },
468
-
469
- _setPos: function(pos) {
470
-
471
- /** @TODO use markerProto._setPos */
472
- if (this._map._rotate) {
473
- pos = this._map.rotatedPointToMapPanePoint(pos);
474
- }
475
-
476
- /** @TODO use markerProto._setPos */
477
- var bearing = this.options.rotation || 0;
478
- if (this.options.rotateWithView) {
479
- bearing += this._map._bearing;
480
- }
481
-
482
- /** @TODO use markerProto._setPos */
483
- if (this._icon) {
484
- L.DomUtil.setPosition(this._icon, pos, bearing, pos, this.options.scale);
485
- }
486
-
487
- /** @TODO use markerProto._setPos */
488
- if (this._shadow) {
489
- L.DomUtil.setPosition(this._shadow, pos, bearing, pos, this.options.scale);
490
- }
491
-
492
- this._zIndex = pos.y + this.options.zIndexOffset;
493
-
494
- this._resetZIndex();
495
- },
496
-
497
- // _updateZIndex: function(offset) {
498
- // if (!this._map._rotate) {
499
- // return markerProto._updateZIndex.apply(this, arguments);
500
- // }
501
- // this._icon.style.zIndex = Math.round(this._zIndex + offset);
502
- // },
503
-
504
- setRotation: function(rotation) {
505
- this.options.rotation = rotation;
506
- this.update();
507
- },
508
-
509
- });
510
-
511
- /**
512
- * @external L.GridLayer
513
- *
514
- * @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/layer/tile/GridLayer.js
515
- */
516
-
517
- const gridLayerProto = L.extend({}, L.GridLayer.prototype);
518
-
519
- L.GridLayer.include({
520
-
521
- /**
522
- * Redraw L.TileLayer bounds after the map is
523
- * moved by just calling `map.setBearing(theta)`
524
- *
525
- * @listens L.Map~rotate
526
- */
527
- getEvents: function() {
528
- var events = gridLayerProto.getEvents.apply(this, arguments);
529
- if (this._map._rotate && !this.options.updateWhenIdle) {
530
- if (!this._onRotate) {
531
- this._onRotate = L.Util.throttle(this._onMoveEnd, this.options.updateInterval, this);
532
- }
533
- events.rotate = this._onRotate;
534
- }
535
- return events;
536
- },
537
-
538
- _getTiledPixelBounds: function(center) {
539
- if (!this._map._rotate) {
540
- return gridLayerProto._getTiledPixelBounds.apply(this, arguments);
541
- }
542
-
543
- return this._map._getNewPixelBounds(center, this._tileZoom);
544
- },
545
-
546
- });
547
-
548
- /**
549
- * @external L.Renderer
550
- *
551
- * @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/layer/vector/Renderer.js
552
- */
553
-
554
- const rendererProto = L.extend({}, L.Renderer.prototype);
555
-
556
- L.Renderer.include({
557
-
558
- /**
559
- * Redraw L.Canvas and L.SVG renderer bounds after the
560
- * map is moved by just calling `map.setBearing(theta)`
561
- *
562
- * @listens L.Map~rotate
563
- */
564
- getEvents: function() {
565
- return L.extend(rendererProto.getEvents.apply(this, arguments), { rotate: this._update });
566
- },
567
-
568
- /**
569
- * Fix for `map.flyTo()` when `false === map.options.zoomAnimation`
570
- *
571
- * @see https://github.com/Leaflet/Leaflet/pull/8794
572
- */
573
- onAdd: function() {
574
- rendererProto.onAdd.apply(this, arguments);
575
- if (L.version <= "1.9.3") {
576
- // always keep transform-origin as 0 0
577
- this._container.classList.add('leaflet-zoom-animated');
578
- }
579
- },
580
-
581
- /**
582
- * @FIXME layer drifts on `map.setZoom()` (eg. zoom during animation)
583
- *
584
- * the main cause seems to be related to `this._updateTransform(path._center, path._zoom))`
585
- * and `this._topLeft = this._map.layerPointToLatLng(this._bounds.min);`
586
- *
587
- * @example
588
- * map.setZoom(2);
589
- * path._renderer._update();
590
- * path._renderer._updateTransform(path._renderer._center, path._renderer._zoom);
591
- *
592
- * @see https://github.com/Leaflet/Leaflet/pull/8794
593
- * @see https://github.com/Leaflet/Leaflet/pull/8103
594
- * @see https://github.com/Leaflet/Leaflet/issues/7466
595
- *
596
- * @TODO rechek this changes from leaflet@v1.9.3
597
- *
598
- * @see https://github.com/Leaflet/Leaflet/compare/v1.7.0...v1.9.3
599
- */
600
- _updateTransform: function(center, zoom) {
601
- if (!this._map._rotate) {
602
- return rendererProto._updateTransform.apply(this, arguments);
603
- }
604
- /**
605
- * @FIXME see path._renderer._reset();
606
- */
607
- var scale = this._map.getZoomScale(zoom, this._zoom),
608
- offset = this._map._latLngToNewLayerPoint(this._topLeft, zoom, center);
609
-
610
- L.DomUtil.setTransform(this._container, offset, scale);
611
-
612
- },
613
-
614
- // getEvents() {
615
- // const events = {
616
- // viewreset: this._reset,
617
- // zoom: this._onZoom,
618
- // moveend: this._update,
619
- // zoomend: this._onZoomEnd
620
- // };
621
- // if (this._zoomAnimated) {
622
- // events.zoomanim = this._onAnimZoom;
623
- // }
624
- // return events;
625
- // },
626
-
627
- // _onAnimZoom(ev) {
628
- // this._updateTransform(ev.center, ev.zoom);
629
- // },
630
-
631
- // _onZoom() {
632
- // this._updateTransform(this._map.getCenter(), this._map.getZoom());
633
- // },
634
-
635
- // _onZoomEnd() {
636
- // for (const id in this._layers) {
637
- // this._layers[id]._project();
638
- // }
639
- // },
640
-
641
- // _reset() {
642
- // this._update();
643
- // this._updateTransform(this._center, this._zoom);
644
-
645
- // for (const id in this._layers) {
646
- // this._layers[id]._reset();
647
- // }
648
- // },
649
-
650
- // _updatePaths() {
651
- // for (const id in this._layers) {
652
- // this._layers[id]._update();
653
- // }
654
- // },
655
-
656
- _update: function() {
657
- if (!this._map._rotate) {
658
- return rendererProto._update.apply(this, arguments);
659
- }
660
- // Update pixel bounds of renderer container (for positioning/sizing/clipping later)
661
- // Subclasses are responsible of firing the 'update' event.
662
- this._bounds = this._map._getPaddedPixelBounds(this.options.padding);
663
- this._topLeft = this._map.layerPointToLatLng(this._bounds.min);
664
- this._center = this._map.getCenter();
665
- this._zoom = this._map.getZoom();
666
- },
667
-
668
- });
669
-
670
- /**
671
- * @external L.Map
672
- *
673
- * @see https://github.com/Leaflet/Leaflet/blob/v1.9.3/src/map/Map.js
674
- */
675
-
676
- const mapProto = L.extend({}, L.Map.prototype);
677
-
678
- L.Map.mergeOptions({ rotate: false, bearing: 0, });
679
-
680
- L.Map.include({
681
-
682
- /**
683
- * @param {(HTMLElement|String)} id html selector
684
- * @param {Object} [options={}] leaflet map options
685
- */
686
- initialize: function(id, options) {
687
- if (options.rotate) {
688
- this._rotate = true;
689
- this._bearing = 0;
690
- }
691
- mapProto.initialize.apply(this, arguments);
692
- if(this.options.rotate){
693
- this.setBearing(this.options.bearing);
694
- }
695
- },
696
-
697
- /**
698
- * Given a pixel coordinate relative to the map container,
699
- * returns the corresponding pixel coordinate relative to
700
- * the [origin pixel](#map-getpixelorigin).
701
- *
702
- * @param {L.Point} point pixel screen coordinates
703
- * @returns {L.Point} transformed pixel point
704
- */
705
- containerPointToLayerPoint: function(point) {
706
- if (!this._rotate) {
707
- return mapProto.containerPointToLayerPoint.apply(this, arguments);
708
- }
709
- return L.point(point)
710
- .subtract(this._getMapPanePos())
711
- .rotateFrom(-this._bearing, this._getRotatePanePos())
712
- .subtract(this._getRotatePanePos());
713
- },
714
-
715
- /**
716
- * Given a pixel coordinate relative to the [origin pixel](#map-getpixelorigin),
717
- * returns the corresponding pixel coordinate relative to the map container.
718
- *
719
- * @param {L.Point} point pixel screen coordinates
720
- * @returns {L.Point} transformed pixel point
721
- */
722
- layerPointToContainerPoint: function(point) {
723
- if (!this._rotate) {
724
- return mapProto.layerPointToContainerPoint.apply(this, arguments);
725
- }
726
- return L.point(point)
727
- .add(this._getRotatePanePos())
728
- .rotateFrom(this._bearing, this._getRotatePanePos())
729
- .add(this._getMapPanePos());
730
- },
731
-
732
- /**
733
- * Converts a coordinate from the rotated pane reference system
734
- * to the reference system of the not rotated map pane.
735
- *
736
- * (rotatePane) --> (mapPane)
737
- * (rotatePane) --> (norotatePane)
738
- *
739
- * @param {L.Point} point pixel screen coordinates
740
- * @returns {L.Point}
741
- *
742
- * @since leaflet-rotate (v0.1)
743
- */
744
- rotatedPointToMapPanePoint: function(point) {
745
- return L.point(point)
746
- .rotate(this._bearing)
747
- ._add(this._getRotatePanePos());
748
- },
749
-
750
- /**
751
- * Converts a coordinate from the not rotated map pane reference system
752
- * to the reference system of the rotated pane.
753
- *
754
- * (mapPane) --> (rotatePane)
755
- * (norotatePane) --> (rotatePane)
756
- *
757
- * @param {L.Point} point pixel screen coordinates
758
- *
759
- * @since leaflet-rotate (v0.1)
760
- */
761
- mapPanePointToRotatedPoint: function(point) {
762
- return L.point(point)
763
- ._subtract(this._getRotatePanePos())
764
- .rotate(-this._bearing);
765
- },
766
-
767
- // latLngToLayerPoint: function (latlng) {
768
- // var projectedPoint = this.project(L.latLng(latlng))._round();
769
- // return projectedPoint._subtract(this.getPixelOrigin());
770
- // },
771
-
772
- // latLngToContainerPoint: function (latlng) {
773
- // return this.layerPointToContainerPoint(this.latLngToLayerPoint(toLatLng(latlng)));
774
- // },
775
-
776
- /**
777
- * Given latlng bounds, returns the bounds in projected pixel
778
- * relative to the map container.
779
- *
780
- * @see https://github.com/ronikar/Leaflet/blob/5c480ef959b947c3beed7065425a5a36c486262b/src/map/Map.js#L1114-L1135
781
- *
782
- * @param {L.LatLngBounds} bounds
783
- * @returns {L.Bounds}
784
- *
785
- * @since leaflet-rotate (v0.2)
786
- */
787
- mapBoundsToContainerBounds: function (bounds) {
788
- if (!this._rotate && mapProto.mapBoundsToContainerBounds) {
789
- return mapProto.mapBoundsToContainerBounds.apply(this, arguments);
790
- }
791
-
792
- // const nw = this.latLngToContainerPoint(bounds.getNorthWest()),
793
- // ne = this.latLngToContainerPoint(bounds.getNorthEast()),
794
- // sw = this.latLngToContainerPoint(bounds.getSouthWest()),
795
- // se = this.latLngToContainerPoint(bounds.getSouthEast());
796
-
797
- // same as `this.latLngToContainerPoint(latlng)` but with floating point precision
798
- const origin = this.getPixelOrigin();
799
- const nw = this.layerPointToContainerPoint(this.project(bounds.getNorthWest())._subtract(origin)),
800
- ne = this.layerPointToContainerPoint(this.project(bounds.getNorthEast())._subtract(origin)),
801
- sw = this.layerPointToContainerPoint(this.project(bounds.getSouthWest())._subtract(origin)),
802
- se = this.layerPointToContainerPoint(this.project(bounds.getSouthEast())._subtract(origin));
803
-
804
- return L.bounds([
805
- L.point(Math.min(nw.x, ne.x, se.x, sw.x), Math.min(nw.y, ne.y, se.y, sw.y)), // [ minX, minY ]
806
- L.point(Math.max(nw.x, ne.x, se.x, sw.x), Math.max(nw.y, ne.y, se.y, sw.y)) // [ maxX, maxY ]
807
- ]);
808
- },
809
-
810
- /**
811
- * Returns geographical bounds visible in the current map view
812
- *
813
- * @TODO find out if map bounds calculated by `L.Map::getBounds()`
814
- * function should match the `rotatePane` or `norotatePane` bounds
815
- *
816
- * @see https://github.com/fnicollet/Leaflet/issues/7
817
- *
818
- * @returns {L.LatLngBounds}
819
- */
820
- getBounds: function() {
821
- if (!this._rotate) {
822
- return mapProto.getBounds.apply(this, arguments);
823
- }
824
-
825
- // SEE: https://github.com/fnicollet/Leaflet/pull/22
826
- //
827
- // var bounds = this.getPixelBounds(),
828
- // sw = this.unproject(bounds.getBottomLeft()),
829
- // ne = this.unproject(bounds.getTopRight());
830
- // return new LatLngBounds(sw, ne);
831
- //
832
-
833
- // LatLngBounds' constructor automatically
834
- // extends the bounds to fit the passed points
835
- var size = this.getSize();
836
- return new L.LatLngBounds([
837
- this.containerPointToLatLng([0, 0]), // topleft
838
- this.containerPointToLatLng([size.x, 0]), // topright
839
- this.containerPointToLatLng([size.x, size.y]), // bottomright
840
- this.containerPointToLatLng([0, size.y]), // bottomleft
841
- ]);
842
- },
843
-
844
- /**
845
- * Returns the bounds of the current map view in projected pixel
846
- * coordinates (sometimes useful in layer and overlay implementations).
847
- *
848
- * @TODO find out if map bounds calculated by `L.Map::getPixelBounds()`
849
- * function should match the `rotatePane` or `norotatePane` bounds
850
- *
851
- * @see https://github.com/fnicollet/Leaflet/issues/7
852
- *
853
- * @returns {L.Bounds}
854
- */
855
- // getPixelBounds(center, zoom) {
856
- // // const topLeftPoint = map.containerPointToLayerPoint(this._getTopLeftPoint());
857
- // const topLeftPoint = this._getTopLeftPoint(center, zoom);
858
- // return new L.Bounds(topLeftPoint, topLeftPoint.add(this.getSize()));
859
- // },
860
-
861
- /**
862
- * Change map rotation
863
- *
864
- * @param {number} theta map degrees
865
- *
866
- * @since leaflet-rotate (v0.1)
867
- */
868
- setBearing: function(theta) {
869
- if (!L.Browser.any3d || !this._rotate) { return; }
870
-
871
- var bearing = L.Util.wrapNum(theta, [0, 360]) * L.DomUtil.DEG_TO_RAD,
872
- center = this._getPixelCenter(),
873
- oldPos = this._getRotatePanePos().rotateFrom(-this._bearing, center),
874
- newPos = oldPos.rotateFrom(bearing, center);
875
-
876
- // CSS transform
877
- L.DomUtil.setPosition(this._rotatePane, oldPos, bearing, center);
878
-
879
- this._pivot = center;
880
- this._bearing = bearing;
881
- this._rotatePanePos = newPos;
882
-
883
- this.fire('rotate');
884
- },
885
-
886
- /**
887
- * Get current map rotation
888
- *
889
- * @returns {number} theta map degrees
890
- *
891
- * @since leaflet-rotate (v0.1)
892
- */
893
- getBearing: function() {
894
- return this._bearing * L.DomUtil.RAD_TO_DEG;
895
- },
896
-
897
- /**
898
- * Creates a new [map pane](#map-pane) with the given name if it doesn't
899
- * exist already, then returns it. The pane is created as a child of
900
- * `container`, or as a child of the main map pane if not set.
901
- *
902
- * @param {String} name leaflet pane
903
- * @param {HTMLElement} [container] parent element
904
- * @returns {HTMLElement} pane container
905
- */
906
- // createPane: function(name, container) {
907
- // if (!this._rotate || name == 'mapPane') {
908
- // return mapProto.createPane.apply(this, arguments);
909
- // }
910
- // // init "rotatePane"
911
- // if (!this._rotatePane) {
912
- // // this._pivot = this.getSize().divideBy(2);
913
- // this._rotatePane = mapProto.createPane.call(this, 'rotatePane', this._mapPane);
914
- // L.DomUtil.setPosition(this._rotatePane, new L.Point(0, 0), this._bearing, this._pivot);
915
- // }
916
- // return mapProto.createPane.call(this, name, container || this._rotatePane);
917
- // },
918
-
919
- /**
920
- * Panes are DOM elements used to control the ordering of layers on
921
- * the map. You can access panes with [`map.getPane`](#map-getpane)
922
- * or [`map.getPanes`](#map-getpanes) methods. New panes can be created
923
- * with the [`map.createPane`](#map-createpane) method.
924
- *
925
- * Every map has the following default panes that differ only in zIndex:
926
- *
927
- * - mapPane [HTMLElement = 'auto'] - Pane that contains all other map panes
928
- * - tilePane [HTMLElement = 2] - Pane for tile layers
929
- * - overlayPane [HTMLElement = 4] - Pane for overlays like polylines and polygons
930
- * - shadowPane [HTMLElement = 5] - Pane for overlay shadows (e.g. marker shadows)
931
- * - markerPane [HTMLElement = 6] - Pane for marker icons
932
- * - tooltipPane [HTMLElement = 650] - Pane for tooltips.
933
- * - popupPane [HTMLElement = 700] - Pane for popups.
934
- */
935
- _initPanes: function() {
936
- var panes = this._panes = {};
937
- this._paneRenderers = {};
938
-
939
- this._mapPane = this.createPane('mapPane', this._container);
940
- L.DomUtil.setPosition(this._mapPane, new L.Point(0, 0));
941
-
942
- if (this._rotate) {
943
- this._rotatePane = this.createPane('rotatePane', this._mapPane);
944
- this._norotatePane = this.createPane('norotatePane', this._mapPane);
945
- // rotatePane
946
- this.createPane('tilePane', this._rotatePane);
947
- this.createPane('overlayPane', this._rotatePane);
948
- // norotatePane
949
- this.createPane('shadowPane', this._norotatePane);
950
- this.createPane('markerPane', this._norotatePane);
951
- this.createPane('tooltipPane', this._norotatePane);
952
- this.createPane('popupPane', this._norotatePane);
953
- } else {
954
- this.createPane('tilePane');
955
- this.createPane('overlayPane');
956
- this.createPane('shadowPane');
957
- this.createPane('markerPane');
958
- this.createPane('tooltipPane');
959
- this.createPane('popupPane');
960
- }
961
-
962
- if (!this.options.markerZoomAnimation) {
963
- L.DomUtil.addClass(panes.markerPane, 'leaflet-zoom-hide');
964
- L.DomUtil.addClass(panes.shadowPane, 'leaflet-zoom-hide');
965
- }
966
- },
967
-
968
- /**
969
- * Pans the map the minimum amount to make the `latlng` visible. Use
970
- * padding options to fit the display to more restricted bounds.
971
- * If `latlng` is already within the (optionally padded) display bounds,
972
- * the map will not be panned.
973
- *
974
- * @see https://github.com/Raruto/leaflet-rotate/issues/18
975
- *
976
- * @param {L.LatLng} latlng coordinates
977
- * @param {Object} [options={}] padding options
978
- *
979
- * @returns {L.Map} current map instance
980
- */
981
- panInside(latlng, options) {
982
- options = options || {};
983
-
984
- const paddingTL = L.point(options.paddingTopLeft || options.padding || [0, 0]),
985
- paddingBR = L.point(options.paddingBottomRight || options.padding || [0, 0]),
986
- /** @TODO use mapProto.panInside */
987
- // pixelPoint = this.project(latlng),
988
- // pixelBounds = this.getPixelBounds(),
989
- // pixelCenter = this.project(this.getCenter()),
990
- rect = this._container.getBoundingClientRect(),
991
- pixelPoint = this.latLngToContainerPoint(latlng),
992
- pixelBounds = L.bounds([ L.point(rect), L.point(rect).add(this.getSize()) ]),
993
- pixelCenter = pixelBounds.getCenter(),
994
- //
995
- paddedBounds = L.bounds([pixelBounds.min.add(paddingTL), pixelBounds.max.subtract(paddingBR)]),
996
- paddedSize = paddedBounds.getSize();
997
-
998
- if (!paddedBounds.contains(pixelPoint)) {
999
- this._enforcingBounds = true;
1000
- const centerOffset = pixelPoint.subtract(paddedBounds.getCenter());
1001
- const offset = paddedBounds.extend(pixelPoint).getSize().subtract(paddedSize);
1002
- pixelCenter.x += centerOffset.x < 0 ? -offset.x : offset.x;
1003
- pixelCenter.y += centerOffset.y < 0 ? -offset.y : offset.y;
1004
- /** @TODO use mapProto.panInside */
1005
- // this.panTo(this.unproject(pixelCenter), options);
1006
- this.panTo(this.containerPointToLatLng(pixelCenter), options);
1007
- //
1008
- this._enforcingBounds = false;
1009
- }
1010
- return this;
1011
- },
1012
-
1013
- /**
1014
- * Pans the map to the closest view that would lie inside the given bounds
1015
- * (if it's not already), controlling the animation using the options specific,
1016
- * if any.
1017
- *
1018
- * @TODO check if map bounds calculated by `L.Map::panInsideBounds()`
1019
- * function should match the `rotatePane` or `norotatePane` bounds
1020
- *
1021
- * @see https://github.com/fnicollet/Leaflet/issues/7
1022
- *
1023
- * @param {L.LatLngBounds} bounds coordinates
1024
- * @param {Object} [options] pan options
1025
- * @returns {L.Map} current map instance
1026
- */
1027
- // panInsideBounds: function (bounds, options) {
1028
- // this._enforcingBounds = true;
1029
- // var center = this.getCenter(),
1030
- // newCenter = this._limitCenter(center, this._zoom, L.latLngBounds(bounds));
1031
- //
1032
- // if (!center.equals(newCenter)) {
1033
- // this.panTo(newCenter, options);
1034
- // }
1035
- //
1036
- // this._enforcingBounds = false;
1037
- // return this;
1038
- // },
1039
-
1040
- // adjust center for view to get inside bounds
1041
- // _limitCenter(center, zoom, bounds) {
1042
- //
1043
- // if (!bounds) { return center; }
1044
- //
1045
- // const centerPoint = this.project(center, zoom),
1046
- // viewHalf = this.getSize().divideBy(2),
1047
- // viewBounds = new Bounds(centerPoint.subtract(viewHalf), centerPoint.add(viewHalf)),
1048
- // offset = this._getBoundsOffset(viewBounds, bounds, zoom);
1049
- //
1050
- // // If offset is less than a pixel, ignore.
1051
- // // This prevents unstable projections from getting into
1052
- // // an infinite loop of tiny offsets.
1053
- // if (Math.abs(offset.x) <= 1 && Math.abs(offset.y) <= 1) {
1054
- // return center;
1055
- // }
1056
- //
1057
- // return this.unproject(centerPoint.add(offset), zoom);
1058
- // },
1059
-
1060
- // @method flyToBounds(bounds: LatLngBounds, options?: fitBounds options): this
1061
- // Sets the view of the map with a smooth animation like [`flyTo`](#map-flyto),
1062
- // but takes a bounds parameter like [`fitBounds`](#map-fitbounds).
1063
- // flyToBounds(bounds, options) {
1064
- // const target = this._getBoundsCenterZoom(bounds, options);
1065
- // return this.flyTo(target.center, target.zoom, options);
1066
- // },
1067
-
1068
- // _getBoundsCenterZoom(bounds, options) {
1069
- //
1070
- // options = options || {};
1071
- // bounds = bounds.getBounds ? bounds.getBounds() : toLatLngBounds(bounds);
1072
- //
1073
- // const paddingTL = L.point(options.paddingTopLeft || options.padding || [0, 0]),
1074
- // paddingBR = L.point(options.paddingBottomRight || options.padding || [0, 0]);
1075
- //
1076
- // let zoom = this.getBoundsZoom(bounds, false, paddingTL.add(paddingBR));
1077
- //
1078
- // zoom = (typeof options.maxZoom === 'number') ? Math.min(options.maxZoom, zoom) : zoom;
1079
- //
1080
- // if (zoom === Infinity) {
1081
- // return { center: bounds.getCenter(), zoom };
1082
- // }
1083
- //
1084
- // return { center, zoom };
1085
- //
1086
- // },
1087
-
1088
- /**
1089
- * Returns the maximum zoom level on which the given bounds fit to the map
1090
- * view in its entirety. If `inside` (optional) is set to `true`, the method
1091
- * instead returns the minimum zoom level on which the map view fits into
1092
- * the given bounds in its entirety.
1093
- *
1094
- * @param {L.LatLngBounds} bounds
1095
- * @param {Boolean} [inside=false]
1096
- * @param {L.Point} [padding=[0,0]]
1097
- *
1098
- * @returns {Number} zoom level
1099
- */
1100
- getBoundsZoom(bounds, inside, padding) {
1101
- if (!this._rotate || Math.abs(this._bearing).toFixed(1) < 0.1) {
1102
- return mapProto.getBoundsZoom.apply(this, arguments);
1103
- }
1104
-
1105
- bounds = L.latLngBounds(bounds);
1106
- padding = L.point(padding || [0, 0]);
1107
-
1108
- let zoom = this.getZoom() || 0;
1109
- const min = this.getMinZoom(),
1110
- max = this.getMaxZoom(),
1111
- /** @TODO use mapProto.getBoundsZoom */
1112
- // nw = bounds.getNorthWest(),
1113
- // se = bounds.getSouthEast(),
1114
- // size = this.getSize().subtract(padding),
1115
- // boundsSize = L.bounds(this.project(se, zoom), this.project(nw, zoom)).getSize(),
1116
- size = this.getSize().subtract(padding),
1117
- boundsSize = this.mapBoundsToContainerBounds(bounds).getSize(),
1118
- snap = this.options.zoomSnap,
1119
- scalex = size.x / boundsSize.x,
1120
- scaley = size.y / boundsSize.y,
1121
- scale = inside ? Math.max(scalex, scaley) : Math.min(scalex, scaley);
1122
-
1123
- zoom = this.getScaleZoom(scale, zoom);
1124
-
1125
- if (snap) {
1126
- zoom = Math.round(zoom / (snap / 100)) * (snap / 100); // don't jump if within 1% of a snap level
1127
- zoom = inside ? Math.ceil(zoom / snap) * snap : Math.floor(zoom / snap) * snap;
1128
- }
1129
-
1130
- return Math.max(min, Math.min(max, zoom));
1131
- },
1132
-
1133
- /**
1134
- * Layer point of the current center
1135
- *
1136
- * @returns {L.Point} layer center
1137
- */
1138
- // _getCenterLayerPoint: function () {
1139
- // return this.containerPointToLayerPoint(this.getSize()._divideBy(2));
1140
- // },
1141
-
1142
- /**
1143
- * Offset of the specified place to the current center in pixels
1144
- *
1145
- * @param {L.LatLng} latlng map coordinates
1146
- */
1147
- _getCenterOffset: function(latlng) {
1148
- var centerOffset = mapProto._getCenterOffset.apply(this, arguments);
1149
- if (this._rotate) {
1150
- centerOffset = centerOffset.rotate(this._bearing);
1151
- }
1152
- return centerOffset;
1153
- },
1154
-
1155
- /**
1156
- * @since leaflet-rotate (v0.1)
1157
- */
1158
- _getRotatePanePos: function() {
1159
- return this._rotatePanePos || new L.Point(0, 0);
1160
- // return L.DomUtil.getPosition(this._rotatePane) || new L.Point(0, 0);
1161
- },
1162
-
1163
- // _latLngToNewLayerPoint(latlng, zoom, center) {
1164
- // const topLeft = this._getNewPixelOrigin(center, zoom);
1165
- // return this.project(latlng, zoom)._subtract(topLeft);
1166
- //},
1167
-
1168
- _getNewPixelOrigin: function(center, zoom) {
1169
- if (!this._rotate) {
1170
- return mapProto._getNewPixelOrigin.apply(this, arguments);
1171
- }
1172
- var viewHalf = this.getSize()._divideBy(2);
1173
- return this.project(center, zoom)
1174
- .rotate(this._bearing)
1175
- ._subtract(viewHalf)
1176
- ._add(this._getMapPanePos())
1177
- ._add(this._getRotatePanePos())
1178
- .rotate(-this._bearing)
1179
- ._round();
1180
- },
1181
-
1182
- /**
1183
- * @since leaflet-rotate (v0.2)
1184
- *
1185
- * @see src\layer\tile\GridLayer::_getTiledPixelBounds()
1186
- */
1187
- _getNewPixelBounds: function(center, zoom) {
1188
- center = center || this.getCenter();
1189
- zoom = zoom || this.getZoom();
1190
- if (!this._rotate && mapProto._getNewPixelBounds) {
1191
- return mapProto._getNewPixelBounds.apply(this, arguments);
1192
- }
1193
- var mapZoom = this._animatingZoom ? Math.max(this._animateToZoom, this.getZoom()) : this.getZoom(),
1194
- scale = this.getZoomScale(mapZoom, zoom),
1195
- pixelCenter = this.project(center, zoom).floor(),
1196
- size = this.getSize(),
1197
- halfSize = new L.Bounds([
1198
- this.containerPointToLayerPoint([0, 0]).floor(),
1199
- this.containerPointToLayerPoint([size.x, 0]).floor(),
1200
- this.containerPointToLayerPoint([0, size.y]).floor(),
1201
- this.containerPointToLayerPoint([size.x, size.y]).floor()
1202
- ]).getSize().divideBy(scale * 2);
1203
-
1204
- return new L.Bounds(pixelCenter.subtract(halfSize), pixelCenter.add(halfSize));
1205
- },
1206
-
1207
- /**
1208
- * @since leaflet-rotate (v0.2)
1209
- *
1210
- * @return {L.Point} map pivot point (center)
1211
- */
1212
- _getPixelCenter: function() {
1213
- if (!this._rotate && mapProto._getPixelCenter) {
1214
- return mapProto._getPixelCenter.apply(this, arguments);
1215
- }
1216
- return this.getSize()._divideBy(2)._subtract(this._getMapPanePos());
1217
- },
1218
-
1219
- /**
1220
- * @since leaflet-rotate (v0.2)
1221
- *
1222
- * @see src\layer\vector\Renderer::_update()
1223
- */
1224
- _getPaddedPixelBounds: function(padding) {
1225
- if (!this._rotate && mapProto._getPaddedPixelBounds) {
1226
- return mapProto._getPaddedPixelBounds.apply(this, arguments);
1227
- }
1228
- var p = padding,
1229
- size = this.getSize(),
1230
- padMin = size.multiplyBy(-p),
1231
- padMax = size.multiplyBy(1 + p);
1232
- //min = this.containerPointToLayerPoint(size.multiplyBy(-p)).round();
1233
-
1234
- return new L.Bounds([
1235
- this.containerPointToLayerPoint([padMin.x, padMin.y]).floor(),
1236
- this.containerPointToLayerPoint([padMin.x, padMax.y]).floor(),
1237
- this.containerPointToLayerPoint([padMax.x, padMin.y]).floor(),
1238
- this.containerPointToLayerPoint([padMax.x, padMax.y]).floor()
1239
- ]);
1240
- },
1241
-
1242
- _handleGeolocationResponse: function(pos) {
1243
- if (!this._container._leaflet_id) { return; }
1244
-
1245
- var lat = pos.coords.latitude,
1246
- lng = pos.coords.longitude,
1247
- /** @TODO use mapProto._handleGeolocationResponse */
1248
- hdg = pos.coords.heading,
1249
- latlng = new L.LatLng(lat, lng),
1250
- bounds = latlng.toBounds(pos.coords.accuracy),
1251
- options = this._locateOptions;
1252
-
1253
- if (options.setView) {
1254
- var zoom = this.getBoundsZoom(bounds);
1255
- this.setView(latlng, options.maxZoom ? Math.min(zoom, options.maxZoom) : zoom);
1256
- }
1257
-
1258
- var data = {
1259
- latlng: latlng,
1260
- bounds: bounds,
1261
- timestamp: pos.timestamp,
1262
- /** @TODO use mapProto._handleGeolocationResponse */
1263
- heading: hdg
1264
- };
1265
-
1266
- for (var i in pos.coords) {
1267
- if (typeof pos.coords[i] === 'number') {
1268
- data[i] = pos.coords[i];
1269
- }
1270
- }
1271
-
1272
- // @event locationfound: LocationEvent
1273
- // Fired when geolocation (using the [`locate`](#map-locate) method)
1274
- // went successfully.
1275
- this.fire('locationfound', data);
1276
- },
1277
-
1278
- /**
1279
- * @see https://github.com/ronikar/Leaflet/blob/5c480ef959b947c3beed7065425a5a36c486262b/src/geo/LatLngBounds.js#L253-L264
1280
- *
1281
- * @param {L.Bounds} points
1282
- * @returns {L.Bounds}
1283
- */
1284
- // toCircumscribedBounds(points) {
1285
- // var minX = points.reduce(function (pv, v) { return Math.min(pv, v.x); }, points[0].x),
1286
- // maxX = points.reduce(function (pv, v) { return Math.max(pv, v.x); }, points[0].x),
1287
- // minY = points.reduce(function (pv, v) { return Math.min(pv, v.y); }, points[0].y),
1288
- // maxY = points.reduce(function (pv, v) { return Math.max(pv, v.y); }, points[0].y);
1289
- //
1290
- // return L.bounds(L.point(minX, minY), L.point(maxX, maxY));
1291
- // },
1292
-
1293
- });
1294
-
1295
- /**
1296
- * Rotates the map according to a smartphone's compass.
1297
- *
1298
- * @typedef L.Map.CompassBearing
1299
- */
1300
-
1301
- L.Map.CompassBearing = L.Handler.extend({
1302
-
1303
- initialize: function(map) {
1304
- this._map = map;
1305
- /** @see https://caniuse.com/?search=DeviceOrientation */
1306
- if ('ondeviceorientationabsolute' in window) {
1307
- this.__deviceOrientationEvent = 'deviceorientationabsolute';
1308
- } else if('ondeviceorientation' in window) {
1309
- this.__deviceOrientationEvent = 'deviceorientation';
1310
- }
1311
- this._throttled = L.Util.throttle(this._onDeviceOrientation, 100, this);
1312
- },
1313
-
1314
- addHooks: function() {
1315
- if (this._map._rotate && this.__deviceOrientationEvent) {
1316
- L.DomEvent.on(window, this.__deviceOrientationEvent, this._throttled, this);
1317
- } else {
1318
- // L.Map.CompassBearing handler will be automatically
1319
- // disabled if device orientation is not supported.
1320
- this.disable();
1321
- }
1322
- },
1323
-
1324
- removeHooks: function() {
1325
- if (this._map._rotate && this.__deviceOrientationEvent) {
1326
- L.DomEvent.off(window, this.__deviceOrientationEvent, this._throttled, this);
1327
- }
1328
- },
1329
-
1330
- /**
1331
- * `DeviceOrientationEvent.absolute` - Indicates whether the device is providing absolute
1332
- * orientation values (relatives to Magnetic North) or
1333
- * using some arbitrary frame determined by the device.
1334
- *
1335
- * `DeviceOrientationEvent.alpha` - Returns the rotation of the device around the Z axis;
1336
- * that is, the number of degrees by which the device is
1337
- * being twisted around the center of the screen.
1338
- *
1339
- * `window.orientation` - Returns the screen orientation in degrees (in 90-degree increments)
1340
- * of the viewport relative to the device's natural orientation.
1341
- * Its only possible values are -90, 0, 90, and 180. Positive
1342
- * values are counterclockwise; negative values are clockwise.
1343
- *
1344
- * @see https://developer.mozilla.org/en-US/docs/Web/API/DeviceOrientationEvent/absolute
1345
- * @see https://developer.mozilla.org/en-US/docs/Web/API/DeviceOrientationEvent/alpha
1346
- * @see https://developer.mozilla.org/en-US/docs/Web/API/Window/orientation
1347
- */
1348
- _onDeviceOrientation: function(e) {
1349
- var angle = e.webkitCompassHeading || e.alpha;
1350
- var deviceOrientation = 0;
1351
-
1352
- // Safari iOS
1353
- if (!e.absolute && e.webkitCompassHeading) {
1354
- angle = 360 - angle;
1355
- }
1356
-
1357
- // Older browsers
1358
- if (!e.absolute && 'undefined' !== typeof window.orientation) {
1359
- deviceOrientation = window.orientation;
1360
- }
1361
-
1362
- this._map.setBearing(angle - deviceOrientation);
1363
- },
1364
-
1365
- });
1366
-
1367
- /**
1368
- * Add Compass bearing handler to L.Map (disabled unless `window.DeviceOrientationEvent` is set).
1369
- *
1370
- * @property {L.Map.CompassBearing} compassBearing
1371
- */
1372
- L.Map.addInitHook('addHandler', 'compassBearing', L.Map.CompassBearing);
1373
-
1374
- /**
1375
- * Triggers `invalidateResize` when the map's DOM container mutates.
1376
- *
1377
- * @typedef L.Map.ContainerMutation
1378
- */
1379
-
1380
- /**
1381
- * @TODO check again this file after leaflet v1.9.3 (eg. L.Browser.mutation).
1382
- * Mutation Observer support will likely be added by default in next releases.
1383
- */
1384
-
1385
- L.Map.mergeOptions({
1386
-
1387
- /**
1388
- * Whether the map uses mutation observers to
1389
- * detect changes in its container and trigger
1390
- * `invalidateSize`. Disabled by default due to
1391
- * support not being available in all web browsers.
1392
- *
1393
- * @type {Boolean}
1394
- *
1395
- * @see https://developer.mozilla.org/docs/Web/API/MutationObserver
1396
- */
1397
- trackContainerMutation: false
1398
-
1399
- });
1400
-
1401
- L.Map.ContainerMutation = L.Handler.extend({
1402
-
1403
- addHooks: function() {
1404
- // if (!L.Browser.mutation) { return; }
1405
- if (!this._observer) {
1406
- this._observer = new MutationObserver(L.Util.bind(this._map.invalidateSize, this._map));
1407
- }
1408
- this._observer.observe(this._map.getContainer(), {
1409
- childList: false,
1410
- attributes: true,
1411
- characterData: false,
1412
- subtree: false,
1413
- attributeFilter: ['style']
1414
- });
1415
- },
1416
-
1417
- removeHooks: function() {
1418
- // if (!L.Browser.mutation) { return; }
1419
- this._observer.disconnect();
1420
- },
1421
-
1422
- });
1423
-
1424
- /**
1425
- * Add Container mutation handler to L.Map (disabled unless `trackContainerMutation` is set).
1426
- *
1427
- * @property {L.Map.ContainerMutation} trackContainerMutation
1428
- */
1429
- L.Map.addInitHook('addHandler', 'trackContainerMutation', L.Map.ContainerMutation);
1430
-
1431
- /**
1432
- * TouchGestures is both TouchZoom plus TouchRotate
1433
- *
1434
- * @see https://github.com/fnicollet/Leaflet/commit/a77af51a6b10f308d1b9a16552091d1d0aee8834
1435
- * @see https://github.com/Leaflet/Leaflet/blob/v1.9.3/src/map/handler/Map.TouchZoom.js
1436
- *
1437
- * @typedef L.Map.TouchGestures
1438
- */
1439
-
1440
- L.Map.mergeOptions({
1441
-
1442
- /**
1443
- * Set it to false if you don't want the map to
1444
- * zoom beyond min/max zoom and then bounce back
1445
- * when pinch-zooming.
1446
- *
1447
- * @type {Boolean}
1448
- */
1449
- bounceAtZoomLimits: true,
1450
-
1451
- });
1452
-
1453
- L.Map.TouchGestures = L.Handler.extend({
1454
-
1455
- initialize: function(map) {
1456
- this._map = map;
1457
- this.rotate = !!this._map.options.touchRotate;
1458
- this.zoom = !!this._map.options.touchZoom;
1459
- },
1460
-
1461
- addHooks: function() {
1462
- L.DomEvent.on(this._map._container, 'touchstart', this._onTouchStart, this);
1463
- },
1464
-
1465
- removeHooks: function() {
1466
- L.DomEvent.off(this._map._container, 'touchstart', this._onTouchStart, this);
1467
- },
1468
-
1469
- _onTouchStart: function(e) {
1470
- var map = this._map;
1471
-
1472
- if (!e.touches || e.touches.length !== 2 || map._animatingZoom || this._zooming || this._rotating) { return; }
1473
-
1474
- var p1 = map.mouseEventToContainerPoint(e.touches[0]),
1475
- p2 = map.mouseEventToContainerPoint(e.touches[1]),
1476
- vector = p1.subtract(p2);
1477
-
1478
- this._centerPoint = map.getSize()._divideBy(2);
1479
- this._startLatLng = map.containerPointToLatLng(this._centerPoint);
1480
-
1481
- if (this.zoom) {
1482
- if (map.options.touchZoom !== 'center') {
1483
- this._pinchStartLatLng = map.containerPointToLatLng(p1.add(p2)._divideBy(2));
1484
- }
1485
- this._startDist = p1.distanceTo(p2);
1486
- this._startZoom = map.getZoom();
1487
- this._zooming = true;
1488
- } else {
1489
- this._zooming = false;
1490
- }
1491
-
1492
- if (this.rotate) {
1493
- this._startTheta = Math.atan(vector.x / vector.y);
1494
- this._startBearing = map.getBearing();
1495
- if (vector.y < 0) { this._startBearing += 180; }
1496
- this._rotating = true;
1497
- } else {
1498
- this._rotating = false;
1499
- }
1500
-
1501
- this._moved = false;
1502
-
1503
- map._stop();
1504
-
1505
- L.DomEvent
1506
- .on(document, 'touchmove', this._onTouchMove, this)
1507
- .on(document, 'touchend touchcancel', this._onTouchEnd, this);
1508
-
1509
- L.DomEvent.preventDefault(e);
1510
- },
1511
-
1512
- _onTouchMove: function(e) {
1513
- if (!e.touches || e.touches.length !== 2 || !(this._zooming || this._rotating)) { return; }
1514
-
1515
- var map = this._map,
1516
- p1 = map.mouseEventToContainerPoint(e.touches[0]),
1517
- p2 = map.mouseEventToContainerPoint(e.touches[1]),
1518
- vector = p1.subtract(p2),
1519
- scale = p1.distanceTo(p2) / this._startDist,
1520
- delta;
1521
-
1522
- if (this._rotating) {
1523
- var theta = Math.atan(vector.x / vector.y);
1524
- var bearingDelta = (theta - this._startTheta) * L.DomUtil.RAD_TO_DEG;
1525
- if (vector.y < 0) { bearingDelta += 180; }
1526
- if (bearingDelta) {
1527
- /**
1528
- * @TODO the pivot should be the last touch point,
1529
- * but zoomAnimation manages to overwrite the rotate
1530
- * pane position. Maybe related to #3529.
1531
- *
1532
- * @see https://github.com/Leaflet/Leaflet/pull/3529
1533
- * @see https://github.com/fnicollet/Leaflet/commit/a77af51a6b10f308d1b9a16552091d1d0aee8834
1534
- */
1535
- map.setBearing(this._startBearing - bearingDelta);
1536
- }
1537
- }
1538
-
1539
- if (this._zooming) {
1540
- this._zoom = map.getScaleZoom(scale, this._startZoom);
1541
-
1542
- if (!map.options.bounceAtZoomLimits && (
1543
- (this._zoom < map.getMinZoom() && scale < 1) ||
1544
- (this._zoom > map.getMaxZoom() && scale > 1))) {
1545
- this._zoom = map._limitZoom(this._zoom);
1546
- }
1547
-
1548
- if (map.options.touchZoom === 'center') {
1549
- this._center = this._startLatLng;
1550
- if (scale === 1) { return; }
1551
- } else {
1552
- // Get delta from pinch to center, so centerLatLng is delta applied to initial pinchLatLng
1553
- delta = p1._add(p2)._divideBy(2)._subtract(this._centerPoint);
1554
- if (scale === 1 && delta.x === 0 && delta.y === 0) { return; }
1555
-
1556
- var alpha = -map.getBearing() * L.DomUtil.DEG_TO_RAD;
1557
-
1558
- this._center = map.unproject(map.project(this._pinchStartLatLng).subtract(delta.rotate(alpha)));
1559
- }
1560
-
1561
- }
1562
-
1563
- if (!this._moved) {
1564
- map._moveStart(true, false);
1565
- this._moved = true;
1566
- }
1567
-
1568
- L.Util.cancelAnimFrame(this._animRequest);
1569
-
1570
- var moveFn = map._move.bind(map, this._center, this._zoom, { pinch: true, round: false }, undefined);
1571
- this._animRequest = L.Util.requestAnimFrame(moveFn, this, true);
1572
-
1573
- L.DomEvent.preventDefault(e);
1574
- },
1575
-
1576
- _onTouchEnd: function() {
1577
- if (!this._moved || !(this._zooming || this._rotating)) {
1578
- this._zooming = false;
1579
- return;
1580
- }
1581
-
1582
- this._zooming = false;
1583
- this._rotating = false;
1584
- L.Util.cancelAnimFrame(this._animRequest);
1585
-
1586
- L.DomEvent
1587
- .off(document, 'touchmove', this._onTouchMove, this)
1588
- .off(document, 'touchend touchcancel', this._onTouchEnd, this);
1589
-
1590
- if (this.zoom) {
1591
- // Pinch updates GridLayers' levels only when zoomSnap is off, so zoomSnap becomes noUpdate.
1592
- if (this._map.options.zoomAnimation) {
1593
- this._map._animateZoom(this._center, this._map._limitZoom(this._zoom), true, this._map.options.zoomSnap);
1594
- } else {
1595
- this._map._resetView(this._center, this._map._limitZoom(this._zoom));
1596
- }
1597
- }
1598
- },
1599
-
1600
- });
1601
-
1602
- /**
1603
- * Add Touch Gestures handler (enabled unless `touchGestures` is unset).
1604
- *
1605
- * @property {L.Map.TouchGestures} touchGestures
1606
- */
1607
- L.Map.addInitHook('addHandler', 'touchGestures', L.Map.TouchGestures);
1608
-
1609
- /**
1610
- * Rotates the map on two-finger (touch devices).
1611
- *
1612
- * @typedef L.Map.TouchRotate
1613
- */
1614
-
1615
- L.Map.mergeOptions({
1616
-
1617
- /**
1618
- * Whether the map can be rotated with a two-finger rotation gesture
1619
- *
1620
- * @type {Boolean}
1621
- */
1622
- touchRotate: false,
1623
-
1624
- });
1625
-
1626
- L.Map.TouchRotate = L.Handler.extend({
1627
-
1628
- addHooks: function() {
1629
- this._map.touchGestures.enable();
1630
- this._map.touchGestures.rotate = true;
1631
- },
1632
-
1633
- removeHooks: function() {
1634
- this._map.touchGestures.rotate = false;
1635
- },
1636
-
1637
- });
1638
-
1639
- /**
1640
- * Add Touch Rotate handler (disabled unless `touchGestures` is set).
1641
- *
1642
- * @property {L.Map.TouchGestures} touchGestures
1643
- */
1644
- L.Map.addInitHook('addHandler', 'touchRotate', L.Map.TouchRotate);
1645
-
1646
- /**
1647
- * Rotates the map on shift key + mousewheel scrolling (desktop).
1648
- *
1649
- * @typedef L.Map.ShiftKeyRotate
1650
- */
1651
-
1652
- L.Map.mergeOptions({
1653
-
1654
- /**
1655
- * Whether the map can be rotated with shift + wheel scroll
1656
- * @type {Boolean}
1657
- */
1658
- shiftKeyRotate: true,
1659
-
1660
- });
1661
-
1662
- L.Map.ShiftKeyRotate = L.Handler.extend({
1663
-
1664
- addHooks: function() {
1665
- L.DomEvent.on(this._map._container, "wheel", this._handleShiftScroll, this);
1666
- // this._map.shiftKeyRotate.enable();
1667
- this._map.shiftKeyRotate.rotate = true;
1668
- },
1669
-
1670
- removeHooks: function() {
1671
- L.DomEvent.off(this._map._container, "wheel", this._handleShiftScroll, this);
1672
- this._map.shiftKeyRotate.rotate = false;
1673
- },
1674
-
1675
- _handleShiftScroll: function(e) {
1676
- if (e.shiftKey) {
1677
- e.preventDefault();
1678
- this._map.scrollWheelZoom.disable();
1679
- this._map.setBearing((this._map._bearing * L.DomUtil.RAD_TO_DEG) + Math.sign(e.deltaY) * 5);
1680
- } else {
1681
- this._map.scrollWheelZoom.enable();
1682
- }
1683
- },
1684
-
1685
- });
1686
-
1687
- /**
1688
- * Add ShiftKey handler to L.Map (enabled unless `shiftKeyRotate` is unset).
1689
- *
1690
- * @property {L.Map.ShiftKeyRotate} shiftKeyRotate
1691
- */
1692
- L.Map.addInitHook('addHandler', 'shiftKeyRotate', L.Map.ShiftKeyRotate);
1693
-
1694
- // decrease `scrollWheelZoom` handler priority over `shiftKeyRotate` handler
1695
- L.Map.addInitHook(function() {
1696
- if (this.scrollWheelZoom.enabled() && this.shiftKeyRotate.enabled()) {
1697
- this.scrollWheelZoom.disable();
1698
- this.scrollWheelZoom.enable();
1699
- }
1700
- });
1701
-
1702
- /**
1703
- * Adds pinch zoom rotation on mobile browsers
1704
- *
1705
- * @see https://github.com/Leaflet/Leaflet/blob/v1.9.3/src/map/handler/Map.TouchZoom.js
1706
- *
1707
- * @external L.Map.TouchZoom
1708
- */
1709
-
1710
- L.Map.mergeOptions({
1711
-
1712
- /**
1713
- * Whether the map can be zoomed by touch-dragging
1714
- * with two fingers. If passed `'center'`, it will
1715
- * zoom to the center of the view regardless of
1716
- * where the touch events (fingers) were. Enabled
1717
- * for touch-capable web browsers.
1718
- *
1719
- * @type {(Boolean|String)}
1720
- */
1721
- touchZoom: L.Browser.touch,
1722
-
1723
- /**
1724
- * @TODO check if this is a duplicate of `L.Map.TouchGestures::bounceAtZoomLimits`
1725
- *
1726
- * Set it to false if you don't want the map to
1727
- * zoom beyond min/max zoom and then bounce back
1728
- * when pinch-zooming.
1729
- *
1730
- * @type {Boolean}
1731
- */
1732
- bounceAtZoomLimits: false,
1733
-
1734
- });
1735
-
1736
- L.Map.TouchZoom = L.Handler.extend({
1737
-
1738
- addHooks: function() {
1739
- L.DomUtil.addClass(this._map._container, 'leaflet-touch-zoom');
1740
- this._map.touchGestures.enable();
1741
- this._map.touchGestures.zoom = true;
1742
- },
1743
-
1744
- removeHooks: function() {
1745
- L.DomUtil.removeClass(this._map._container, 'leaflet-touch-zoom');
1746
- this._map.touchGestures.zoom = false;
1747
- },
1748
-
1749
- });
1750
-
1751
- /**
1752
- * Add Touch Zoom handler (disabled unless `L.Browser.touch` is set).
1753
- *
1754
- * @property {L.Map.TouchGestures} touchGestures
1755
- */
1756
- L.Map.addInitHook('addHandler', 'touchZoom', L.Map.TouchZoom);
1757
-
1758
- /**
1759
- * A tri-state control for map rotation, states are:
1760
- *
1761
- * - Locked (default)
1762
- * - Unlocked (user can pinch-rotate)
1763
- * - Follow (rotation follows device orientation, if available)
1764
- *
1765
- * @typedef L.Control.Rotate
1766
- */
1767
-
1768
- L.Control.Rotate = L.Control.extend({
1769
-
1770
- options: {
1771
- position: 'topleft',
1772
- closeOnZeroBearing: true
1773
- },
1774
-
1775
- onAdd: function(map) {
1776
- var container = this._container = L.DomUtil.create('div', 'leaflet-control-rotate leaflet-bar');
1777
-
1778
- // this.button = L.Control.Zoom.prototype._createButton.call(this, 'R', 'leaflet-control-rotate', 'leaflet-control-rotate', container, this._toggleLock);
1779
-
1780
- var arrow = this._arrow = L.DomUtil.create('span', 'leaflet-control-rotate-arrow');
1781
-
1782
- arrow.style.backgroundImage = `url("data:image/svg+xml;charset=utf-8,%3Csvg width='29' height='29' viewBox='0 0 29 29' xmlns='http://www.w3.org/2000/svg' fill='%23333'%3E%3Cpath d='M10.5 14l4-8 4 8h-8z'/%3E%3Cpath d='M10.5 16l4 8 4-8h-8z' fill='%23ccc'/%3E%3C/svg%3E")`;
1783
- arrow.style.cursor = 'grab';
1784
- arrow.style.display = 'block';
1785
- arrow.style.width = '100%';
1786
- arrow.style.height = '100%';
1787
- arrow.style.backgroundRepeat = 'no-repeat';
1788
- arrow.style.backgroundPosition = '50%';
1789
-
1790
- // Copy-pasted from L.Control.Zoom
1791
- var link = this._link = L.DomUtil.create('a', 'leaflet-control-rotate-toggle', container);
1792
- link.appendChild(arrow);
1793
- link.href = '#';
1794
- link.title = 'Rotate map';
1795
-
1796
- L.DomEvent
1797
- .on(link, 'dblclick', L.DomEvent.stopPropagation)
1798
- .on(link, 'mousedown', this._handleMouseDown, this)
1799
- .on(link, 'click', L.DomEvent.stop)
1800
- .on(link, 'click', this._cycleState, this)
1801
- .on(link, 'click', this._refocusOnMap, this);
1802
-
1803
- if (!L.Browser.any3d) {
1804
- L.DomUtil.addClass(link, 'leaflet-disabled');
1805
- }
1806
-
1807
- this._restyle();
1808
-
1809
- map.on('rotate', this._restyle, this);
1810
-
1811
- // State flag
1812
- this._follow = false;
1813
- this._canFollow = false;
1814
-
1815
- if (this.options.closeOnZeroBearing && map.getBearing() === 0) {
1816
- container.style.display = 'none';
1817
- }
1818
-
1819
- return container;
1820
- },
1821
-
1822
- onRemove: function(map) {
1823
- map.off('rotate', this._restyle, this);
1824
- },
1825
-
1826
- _handleMouseDown: function(e) {
1827
- L.DomEvent.stop(e);
1828
- this.dragging = true;
1829
- this.dragstartX = e.pageX;
1830
- this.dragstartY = e.pageY;
1831
- L.DomEvent
1832
- .on(document, 'mousemove', this._handleMouseDrag, this)
1833
- .on(document, 'mouseup', this._handleMouseUp, this);
1834
- },
1835
-
1836
- _handleMouseUp: function(e) {
1837
- L.DomEvent.stop(e);
1838
- this.dragging = false;
1839
-
1840
- L.DomEvent
1841
- .off(document, 'mousemove', this._handleMouseDrag, this)
1842
- .off(document, 'mouseup', this._handleMouseUp, this);
1843
- },
1844
-
1845
- _handleMouseDrag: function(e) {
1846
- if (!this.dragging) { return; }
1847
- var deltaX = e.clientX - this.dragstartX;
1848
- this._map.setBearing(deltaX);
1849
- },
1850
-
1851
- _cycleState: function(ev) {
1852
- if (!this._map) {
1853
- return;
1854
- }
1855
-
1856
- var map = this._map;
1857
-
1858
- // Touch mode
1859
- if (!map.touchRotate.enabled() && !map.compassBearing.enabled()) {
1860
- map.touchRotate.enable();
1861
- }
1862
-
1863
- // Compass mode
1864
- else if (!map.compassBearing.enabled()) {
1865
- map.touchRotate.disable();
1866
- map.compassBearing.enable();
1867
- }
1868
-
1869
- // Locked mode
1870
- else {
1871
- map.compassBearing.disable();
1872
- map.setBearing(0);
1873
- if (this.options.closeOnZeroBearing) {
1874
- map.touchRotate.enable();
1875
- }
1876
- }
1877
- this._restyle();
1878
- },
1879
-
1880
- _restyle: function() {
1881
- if (!this._map.options.rotate) {
1882
- L.DomUtil.addClass(this._link, 'leaflet-disabled');
1883
- } else {
1884
- var map = this._map;
1885
- var bearing = map.getBearing();
1886
-
1887
- this._arrow.style.transform = 'rotate(' + bearing + 'deg)';
1888
-
1889
- if (bearing && this.options.closeOnZeroBearing) {
1890
- this._container.style.display = 'block';
1891
- }
1892
-
1893
- // Compass mode
1894
- if (map.compassBearing.enabled()) {
1895
- this._link.style.backgroundColor = 'orange';
1896
- }
1897
-
1898
- // Touch mode
1899
- else if (map.touchRotate.enabled()) {
1900
- this._link.style.backgroundColor = null;
1901
- }
1902
-
1903
- // Locked mode
1904
- else {
1905
- this._link.style.backgroundColor = 'grey';
1906
- if (0 === bearing && this.options.closeOnZeroBearing) {
1907
- this._container.style.display = 'none';
1908
- }
1909
- }
1910
- }
1911
- },
1912
-
1913
- });
1914
-
1915
- L.control.rotate = function(options) {
1916
- return new L.Control.Rotate(options);
1917
- };
1918
-
1919
- L.Map.mergeOptions({
1920
- rotateControl: true,
1921
- });
1922
-
1923
- L.Map.addInitHook(function() {
1924
- if (this.options.rotateControl) {
1925
- var options = typeof this.options.rotateControl === 'object' ? this.options.rotateControl : {};
1926
- this.rotateControl = L.control.rotate(options);
1927
- this.addControl(this.rotateControl);
1928
- }
1929
- });
1930
-
1931
- }));
1
+ !function(t){"function"==typeof define&&define.amd?define(t):t()}((function(){"use strict";const t=L.extend({},L.DomUtil);L.extend(L.DomUtil,{setTransform:function(o,e,i,n,a){var s=e||new L.Point(0,0);if(!n)return e=s._round(),t.setTransform.apply(this,arguments);s=s.rotateFrom(n,a),o.style[L.DomUtil.TRANSFORM]="translate3d("+s.x+"px,"+s.y+"px,0)"+(i?" scale("+i+")":"")+" rotate("+n+"rad)"},setPosition:function(o,e,i,n,a){if(!i)return t.setPosition.apply(this,arguments);o._leaflet_pos=e,L.Browser.any3d?L.DomUtil.setTransform(o,e,a,i,n):(o.style.left=e.x+"px",o.style.top=e.y+"px")},DEG_TO_RAD:Math.PI/180,RAD_TO_DEG:180/Math.PI}),L.Draggable.include({}),L.extend(L.Point.prototype,{rotate:function(t){return this.rotateFrom(t,new L.Point(0,0))},rotateFrom:function(t,o){if(!t)return this;var e=Math.sin(t),i=Math.cos(t),n=o.x,a=o.y,s=this.x-n,r=this.y-a;return new L.Point(s*i-r*e+n,s*e+r*i+a)}});const o=L.extend({},L.DivOverlay.prototype);L.DivOverlay.include({getEvents:function(){return L.extend(o.getEvents.apply(this,arguments),{rotate:this._updatePosition})},_updatePosition:function(){if(this._map&&(o._updatePosition.apply(this,arguments),this._map&&this._map._rotate&&this._zoomAnimated)){var t=this._getAnchor(),e=L.DomUtil.getPosition(this._container).subtract(t);L.DomUtil.setPosition(this._container,this._map.rotatedPointToMapPanePoint(e).add(t))}}});const e=L.extend({},L.Popup.prototype);L.Popup.include({_animateZoom:function(t){if(e._animateZoom.apply(this,arguments),this._map&&this._map._rotate){var o=this._getAnchor(),i=L.DomUtil.getPosition(this._container).subtract(o);L.DomUtil.setPosition(this._container,this._map.rotatedPointToMapPanePoint(i).add(o))}},_adjustPan:function(){if(!(!this.options.autoPan||this._map._panAnim&&this._map._panAnim._inProgress))if(this._autopanning)this._autopanning=!1;else{var t=this._map,o=parseInt(L.DomUtil.getStyle(this._container,"marginBottom"),10)||0,e=this._container.offsetHeight+o,i=this._containerWidth,n=new L.Point(this._containerLeft,-e-this._containerBottom);n._add(L.DomUtil.getPosition(this._container));var a=n._add(this._map._getMapPanePos()),s=L.point(this.options.autoPanPadding),r=L.point(this.options.autoPanPaddingTopLeft||s),h=L.point(this.options.autoPanPaddingBottomRight||s),_=t.getSize(),d=0,l=0;a.x+i+h.x>_.x&&(d=a.x+i-_.x+h.x),a.x-d-r.x<0&&(d=a.x-r.x),a.y+e+h.y>_.y&&(l=a.y+e-_.y+h.y),a.y-l-r.y<0&&(l=a.y-r.y),(d||l)&&(this.options.keepInView&&(this._autopanning=!0),t.fire("autopanstart").panBy([d,l]))}}});const i=L.extend({},L.Tooltip.prototype);L.Tooltip.include({_animateZoom:function(t){if(!this._map._rotate)return i._animateZoom.apply(this,arguments);var o=this._map._latLngToNewLayerPoint(this._latlng,t.zoom,t.center);o=this._map.rotatedPointToMapPanePoint(o),this._setPosition(o)},_updatePosition:function(){if(!this._map._rotate)return i._updatePosition.apply(this,arguments);var t=this._map.latLngToLayerPoint(this._latlng);t=this._map.rotatedPointToMapPanePoint(t),this._setPosition(t)}}),L.extend({},L.Icon.prototype),L.Icon.include({_setIconStyles:function(t,o){var e=this.options,i=e[o+"Size"];"number"==typeof i&&(i=[i,i]);var n=L.point(i),a=L.point("shadow"===o&&e.shadowAnchor||e.iconAnchor||n&&n.divideBy(2,!0));t.className="leaflet-marker-"+o+" "+(e.className||""),a&&(t.style.marginLeft=-a.x+"px",t.style.marginTop=-a.y+"px",t.style[L.DomUtil.TRANSFORM+"Origin"]=a.x+"px "+a.y+"px 0px"),n&&(t.style.width=n.x+"px",t.style.height=n.y+"px")}});const n=L.extend({},L.Marker.prototype);var a;L.Marker.mergeOptions({rotation:0,rotateWithView:!1,scale:void 0});var s={_onDrag:function(t){var o=this._marker,e=o.options.rotation||o.options.rotateWithView,i=o._shadow,n=L.DomUtil.getPosition(o._icon);!e&&i&&L.DomUtil.setPosition(i,n),o._map._rotate&&(n=o._map.mapPanePointToRotatedPoint(n));var a=o._map.layerPointToLatLng(n);o._latlng=a,t.latlng=a,t.oldLatLng=this._oldLatLng,e?o.setLatLng(a):o.fire("move",t),o.fire("drag",t)},_onDragEnd:function(t){this._marker._map._rotate&&this._marker.update(),a._onDragEnd.apply(this,arguments)}};L.Marker.include({getEvents:function(){return L.extend(n.getEvents.apply(this,arguments),{rotate:this.update})},_initInteraction:function(){var t=n._initInteraction.apply(this,arguments);return this.dragging&&this.dragging.enabled()&&this._map&&this._map._rotate&&(a=a||Object.getPrototypeOf(this.dragging),Object.assign(this.dragging,{_onDrag:s._onDrag.bind(this.dragging),_onDragEnd:s._onDragEnd.bind(this.dragging)}),this.dragging.disable(),this.dragging.enable()),t},_setPos:function(t){this._map._rotate&&(t=this._map.rotatedPointToMapPanePoint(t));var o=this.options.rotation||0;this.options.rotateWithView&&(o+=this._map._bearing),this._icon&&L.DomUtil.setPosition(this._icon,t,o,t,this.options.scale),this._shadow&&L.DomUtil.setPosition(this._shadow,t,o,t,this.options.scale),this._zIndex=t.y+this.options.zIndexOffset,this._resetZIndex()},setRotation:function(t){this.options.rotation=t,this.update()}});const r=L.extend({},L.GridLayer.prototype);L.GridLayer.include({getEvents:function(){var t=r.getEvents.apply(this,arguments);return this._map._rotate&&!this.options.updateWhenIdle&&(this._onRotate||(this._onRotate=L.Util.throttle(this._onMoveEnd,this.options.updateInterval,this)),t.rotate=this._onRotate),t},_getTiledPixelBounds:function(t){return this._map._rotate?this._map._getNewPixelBounds(t,this._tileZoom):r._getTiledPixelBounds.apply(this,arguments)}});const h=L.extend({},L.Renderer.prototype);L.Renderer.include({getEvents:function(){return L.extend(h.getEvents.apply(this,arguments),{rotate:this._update})},onAdd:function(){h.onAdd.apply(this,arguments),L.version<="1.9.3"&&this._container.classList.add("leaflet-zoom-animated")},_updateTransform:function(t,o){if(!this._map._rotate)return h._updateTransform.apply(this,arguments);var e=this._map.getZoomScale(o,this._zoom),i=this._map._latLngToNewLayerPoint(this._topLeft,o,t);L.DomUtil.setTransform(this._container,i,e)},_update:function(){if(!this._map._rotate)return h._update.apply(this,arguments);this._bounds=this._map._getPaddedPixelBounds(this.options.padding),this._topLeft=this._map.layerPointToLatLng(this._bounds.min),this._center=this._map.getCenter(),this._zoom=this._map.getZoom()}});const _=L.extend({},L.Map.prototype);L.Map.mergeOptions({rotate:!1,bearing:0}),L.Map.include({initialize:function(t,o){o.rotate&&(this._rotate=!0,this._bearing=0),_.initialize.apply(this,arguments),this.options.rotate&&this.setBearing(this.options.bearing)},containerPointToLayerPoint:function(t){return this._rotate?L.point(t).subtract(this._getMapPanePos()).rotateFrom(-this._bearing,this._getRotatePanePos()).subtract(this._getRotatePanePos()):_.containerPointToLayerPoint.apply(this,arguments)},layerPointToContainerPoint:function(t){return this._rotate?L.point(t).add(this._getRotatePanePos()).rotateFrom(this._bearing,this._getRotatePanePos()).add(this._getMapPanePos()):_.layerPointToContainerPoint.apply(this,arguments)},rotatedPointToMapPanePoint:function(t){return L.point(t).rotate(this._bearing)._add(this._getRotatePanePos())},mapPanePointToRotatedPoint:function(t){return L.point(t)._subtract(this._getRotatePanePos()).rotate(-this._bearing)},mapBoundsToContainerBounds:function(t){if(!this._rotate&&_.mapBoundsToContainerBounds)return _.mapBoundsToContainerBounds.apply(this,arguments);const o=this.getPixelOrigin(),e=this.layerPointToContainerPoint(this.project(t.getNorthWest())._subtract(o)),i=this.layerPointToContainerPoint(this.project(t.getNorthEast())._subtract(o)),n=this.layerPointToContainerPoint(this.project(t.getSouthWest())._subtract(o)),a=this.layerPointToContainerPoint(this.project(t.getSouthEast())._subtract(o));return L.bounds([L.point(Math.min(e.x,i.x,a.x,n.x),Math.min(e.y,i.y,a.y,n.y)),L.point(Math.max(e.x,i.x,a.x,n.x),Math.max(e.y,i.y,a.y,n.y))])},getBounds:function(){if(!this._rotate)return _.getBounds.apply(this,arguments);var t=this.getSize();return new L.LatLngBounds([this.containerPointToLatLng([0,0]),this.containerPointToLatLng([t.x,0]),this.containerPointToLatLng([t.x,t.y]),this.containerPointToLatLng([0,t.y])])},setBearing:function(t){if(L.Browser.any3d&&this._rotate){var o=L.Util.wrapNum(t,[0,360])*L.DomUtil.DEG_TO_RAD,e=this._getPixelCenter(),i=this._getRotatePanePos().rotateFrom(-this._bearing,e),n=i.rotateFrom(o,e);L.DomUtil.setPosition(this._rotatePane,i,o,e),this._pivot=e,this._bearing=o,this._rotatePanePos=n,this.fire("rotate")}},getBearing:function(){return this._bearing*L.DomUtil.RAD_TO_DEG},_initPanes:function(){var t=this._panes={};this._paneRenderers={},this._mapPane=this.createPane("mapPane",this._container),L.DomUtil.setPosition(this._mapPane,new L.Point(0,0)),this._rotate?(this._rotatePane=this.createPane("rotatePane",this._mapPane),this._norotatePane=this.createPane("norotatePane",this._mapPane),this.createPane("tilePane",this._rotatePane),this.createPane("overlayPane",this._rotatePane),this.createPane("shadowPane",this._norotatePane),this.createPane("markerPane",this._norotatePane),this.createPane("tooltipPane",this._norotatePane),this.createPane("popupPane",this._norotatePane)):(this.createPane("tilePane"),this.createPane("overlayPane"),this.createPane("shadowPane"),this.createPane("markerPane"),this.createPane("tooltipPane"),this.createPane("popupPane")),this.options.markerZoomAnimation||(L.DomUtil.addClass(t.markerPane,"leaflet-zoom-hide"),L.DomUtil.addClass(t.shadowPane,"leaflet-zoom-hide"))},panInside(t,o){o=o||{};const e=L.point(o.paddingTopLeft||o.padding||[0,0]),i=L.point(o.paddingBottomRight||o.padding||[0,0]),n=this._container.getBoundingClientRect(),a=this.latLngToContainerPoint(t),s=L.bounds([L.point(n),L.point(n).add(this.getSize())]),r=s.getCenter(),h=L.bounds([s.min.add(e),s.max.subtract(i)]),_=h.getSize();if(!h.contains(a)){this._enforcingBounds=!0;const t=a.subtract(h.getCenter()),e=h.extend(a).getSize().subtract(_);r.x+=t.x<0?-e.x:e.x,r.y+=t.y<0?-e.y:e.y,this.panTo(this.containerPointToLatLng(r),o),this._enforcingBounds=!1}return this},getBoundsZoom(t,o,e){if(!this._rotate||Math.abs(this._bearing).toFixed(1)<.1)return _.getBoundsZoom.apply(this,arguments);t=L.latLngBounds(t),e=L.point(e||[0,0]);let i=this.getZoom()||0;const n=this.getMinZoom(),a=this.getMaxZoom(),s=this.getSize().subtract(e),r=this.mapBoundsToContainerBounds(t).getSize(),h=this.options.zoomSnap,d=s.x/r.x,l=s.y/r.y,p=o?Math.max(d,l):Math.min(d,l);return i=this.getScaleZoom(p,i),h&&(i=Math.round(i/(h/100))*(h/100),i=o?Math.ceil(i/h)*h:Math.floor(i/h)*h),Math.max(n,Math.min(a,i))},_getCenterOffset:function(t){var o=_._getCenterOffset.apply(this,arguments);return this._rotate&&(o=o.rotate(this._bearing)),o},_getRotatePanePos:function(){return this._rotatePanePos||new L.Point(0,0)},_getNewPixelOrigin:function(t,o){if(!this._rotate)return _._getNewPixelOrigin.apply(this,arguments);var e=this.getSize()._divideBy(2);return this.project(t,o).rotate(this._bearing)._subtract(e)._add(this._getMapPanePos())._add(this._getRotatePanePos()).rotate(-this._bearing)._round()},_getNewPixelBounds:function(t,o){if(t=t||this.getCenter(),o=o||this.getZoom(),!this._rotate&&_._getNewPixelBounds)return _._getNewPixelBounds.apply(this,arguments);var e=this._animatingZoom?Math.max(this._animateToZoom,this.getZoom()):this.getZoom(),i=this.getZoomScale(e,o),n=this.project(t,o).floor(),a=this.getSize(),s=new L.Bounds([this.containerPointToLayerPoint([0,0]).floor(),this.containerPointToLayerPoint([a.x,0]).floor(),this.containerPointToLayerPoint([0,a.y]).floor(),this.containerPointToLayerPoint([a.x,a.y]).floor()]).getSize().divideBy(2*i);return new L.Bounds(n.subtract(s),n.add(s))},_getPixelCenter:function(){return!this._rotate&&_._getPixelCenter?_._getPixelCenter.apply(this,arguments):this.getSize()._divideBy(2)._subtract(this._getMapPanePos())},_getPaddedPixelBounds:function(t){if(!this._rotate&&_._getPaddedPixelBounds)return _._getPaddedPixelBounds.apply(this,arguments);var o=t,e=this.getSize(),i=e.multiplyBy(-o),n=e.multiplyBy(1+o);return new L.Bounds([this.containerPointToLayerPoint([i.x,i.y]).floor(),this.containerPointToLayerPoint([i.x,n.y]).floor(),this.containerPointToLayerPoint([n.x,i.y]).floor(),this.containerPointToLayerPoint([n.x,n.y]).floor()])},_handleGeolocationResponse:function(t){if(this._container._leaflet_id){var o=t.coords.latitude,e=t.coords.longitude,i=t.coords.heading,n=new L.LatLng(o,e),a=n.toBounds(t.coords.accuracy),s=this._locateOptions;if(s.setView){var r=this.getBoundsZoom(a);this.setView(n,s.maxZoom?Math.min(r,s.maxZoom):r)}var h={latlng:n,bounds:a,timestamp:t.timestamp,heading:i};for(var _ in t.coords)"number"==typeof t.coords[_]&&(h[_]=t.coords[_]);this.fire("locationfound",h)}}}),L.Map.CompassBearing=L.Handler.extend({initialize:function(t){this._map=t,"ondeviceorientationabsolute"in window?this.__deviceOrientationEvent="deviceorientationabsolute":"ondeviceorientation"in window&&(this.__deviceOrientationEvent="deviceorientation"),this._throttled=L.Util.throttle(this._onDeviceOrientation,100,this)},addHooks:function(){this._map._rotate&&this.__deviceOrientationEvent?L.DomEvent.on(window,this.__deviceOrientationEvent,this._throttled,this):this.disable()},removeHooks:function(){this._map._rotate&&this.__deviceOrientationEvent&&L.DomEvent.off(window,this.__deviceOrientationEvent,this._throttled,this)},_onDeviceOrientation:function(t){var o=t.webkitCompassHeading||t.alpha,e=0;!t.absolute&&t.webkitCompassHeading&&(o=360-o),t.absolute||void 0===window.orientation||(e=window.orientation),this._map.setBearing(o-e)}}),L.Map.addInitHook("addHandler","compassBearing",L.Map.CompassBearing),L.Map.mergeOptions({trackContainerMutation:!1}),L.Map.ContainerMutation=L.Handler.extend({addHooks:function(){this._observer||(this._observer=new MutationObserver(L.Util.bind(this._map.invalidateSize,this._map))),this._observer.observe(this._map.getContainer(),{childList:!1,attributes:!0,characterData:!1,subtree:!1,attributeFilter:["style"]})},removeHooks:function(){this._observer.disconnect()}}),L.Map.addInitHook("addHandler","trackContainerMutation",L.Map.ContainerMutation),L.Map.mergeOptions({bounceAtZoomLimits:!0}),L.Map.TouchGestures=L.Handler.extend({initialize:function(t){this._map=t,this.rotate=!!this._map.options.touchRotate,this.zoom=!!this._map.options.touchZoom},addHooks:function(){L.DomEvent.on(this._map._container,"touchstart",this._onTouchStart,this)},removeHooks:function(){L.DomEvent.off(this._map._container,"touchstart",this._onTouchStart,this)},_onTouchStart:function(t){var o=this._map;if(t.touches&&2===t.touches.length&&!o._animatingZoom&&!this._zooming&&!this._rotating){var e=o.mouseEventToContainerPoint(t.touches[0]),i=o.mouseEventToContainerPoint(t.touches[1]),n=e.subtract(i);this._centerPoint=o.getSize()._divideBy(2),this._startLatLng=o.containerPointToLatLng(this._centerPoint),this.zoom?("center"!==o.options.touchZoom&&(this._pinchStartLatLng=o.containerPointToLatLng(e.add(i)._divideBy(2))),this._startDist=e.distanceTo(i),this._startZoom=o.getZoom(),this._zooming=!0):this._zooming=!1,this.rotate?(this._startTheta=Math.atan(n.x/n.y),this._startBearing=o.getBearing(),n.y<0&&(this._startBearing+=180),this._rotating=!0):this._rotating=!1,this._moved=!1,o._stop(),L.DomEvent.on(document,"touchmove",this._onTouchMove,this).on(document,"touchend touchcancel",this._onTouchEnd,this),L.DomEvent.preventDefault(t)}},_onTouchMove:function(t){if(t.touches&&2===t.touches.length&&(this._zooming||this._rotating)){var o,e=this._map,i=e.mouseEventToContainerPoint(t.touches[0]),n=e.mouseEventToContainerPoint(t.touches[1]),a=i.subtract(n),s=i.distanceTo(n)/this._startDist;if(this._rotating){var r=(Math.atan(a.x/a.y)-this._startTheta)*L.DomUtil.RAD_TO_DEG;a.y<0&&(r+=180),r&&e.setBearing(this._startBearing-r)}if(this._zooming)if(this._zoom=e.getScaleZoom(s,this._startZoom),!e.options.bounceAtZoomLimits&&(this._zoom<e.getMinZoom()&&s<1||this._zoom>e.getMaxZoom()&&s>1)&&(this._zoom=e._limitZoom(this._zoom)),"center"===e.options.touchZoom){if(this._center=this._startLatLng,1===s)return}else{if(o=i._add(n)._divideBy(2)._subtract(this._centerPoint),1===s&&0===o.x&&0===o.y)return;var h=-e.getBearing()*L.DomUtil.DEG_TO_RAD;this._center=e.unproject(e.project(this._pinchStartLatLng).subtract(o.rotate(h)))}this._moved||(e._moveStart(!0,!1),this._moved=!0),L.Util.cancelAnimFrame(this._animRequest);var _=e._move.bind(e,this._center,this._zoom,{pinch:!0,round:!1},void 0);this._animRequest=L.Util.requestAnimFrame(_,this,!0),L.DomEvent.preventDefault(t)}},_onTouchEnd:function(){this._moved&&(this._zooming||this._rotating)?(this._zooming=!1,this._rotating=!1,L.Util.cancelAnimFrame(this._animRequest),L.DomEvent.off(document,"touchmove",this._onTouchMove,this).off(document,"touchend touchcancel",this._onTouchEnd,this),this.zoom&&(this._map.options.zoomAnimation?this._map._animateZoom(this._center,this._map._limitZoom(this._zoom),!0,this._map.options.zoomSnap):this._map._resetView(this._center,this._map._limitZoom(this._zoom)))):this._zooming=!1}}),L.Map.addInitHook("addHandler","touchGestures",L.Map.TouchGestures),L.Map.mergeOptions({touchRotate:!1}),L.Map.TouchRotate=L.Handler.extend({addHooks:function(){this._map.touchGestures.enable(),this._map.touchGestures.rotate=!0},removeHooks:function(){this._map.touchGestures.rotate=!1}}),L.Map.addInitHook("addHandler","touchRotate",L.Map.TouchRotate),L.Map.mergeOptions({shiftKeyRotate:!0}),L.Map.ShiftKeyRotate=L.Handler.extend({addHooks:function(){L.DomEvent.on(this._map._container,"wheel",this._handleShiftScroll,this),this._map.shiftKeyRotate.rotate=!0},removeHooks:function(){L.DomEvent.off(this._map._container,"wheel",this._handleShiftScroll,this),this._map.shiftKeyRotate.rotate=!1},_handleShiftScroll:function(t){t.shiftKey?(t.preventDefault(),this._map.scrollWheelZoom.disable(),this._map.setBearing(this._map._bearing*L.DomUtil.RAD_TO_DEG+5*Math.sign(t.deltaY))):this._map.scrollWheelZoom.enable()}}),L.Map.addInitHook("addHandler","shiftKeyRotate",L.Map.ShiftKeyRotate),L.Map.addInitHook((function(){this.scrollWheelZoom.enabled()&&this.shiftKeyRotate.enabled()&&(this.scrollWheelZoom.disable(),this.scrollWheelZoom.enable())})),L.Map.mergeOptions({touchZoom:L.Browser.touch,bounceAtZoomLimits:!1}),L.Map.TouchZoom=L.Handler.extend({addHooks:function(){L.DomUtil.addClass(this._map._container,"leaflet-touch-zoom"),this._map.touchGestures.enable(),this._map.touchGestures.zoom=!0},removeHooks:function(){L.DomUtil.removeClass(this._map._container,"leaflet-touch-zoom"),this._map.touchGestures.zoom=!1}}),L.Map.addInitHook("addHandler","touchZoom",L.Map.TouchZoom),L.Control.Rotate=L.Control.extend({options:{position:"topleft",closeOnZeroBearing:!0},onAdd:function(t){var o=this._container=L.DomUtil.create("div","leaflet-control-rotate leaflet-bar"),e=this._arrow=L.DomUtil.create("span","leaflet-control-rotate-arrow");e.style.backgroundImage="url(\"data:image/svg+xml;charset=utf-8,%3Csvg width='29' height='29' viewBox='0 0 29 29' xmlns='http://www.w3.org/2000/svg' fill='%23333'%3E%3Cpath d='M10.5 14l4-8 4 8h-8z'/%3E%3Cpath d='M10.5 16l4 8 4-8h-8z' fill='%23ccc'/%3E%3C/svg%3E\")",e.style.cursor="grab",e.style.display="block",e.style.width="100%",e.style.height="100%",e.style.backgroundRepeat="no-repeat",e.style.backgroundPosition="50%";var i=this._link=L.DomUtil.create("a","leaflet-control-rotate-toggle",o);return i.appendChild(e),i.href="#",i.title="Rotate map",L.DomEvent.on(i,"dblclick",L.DomEvent.stopPropagation).on(i,"mousedown",this._handleMouseDown,this).on(i,"click",L.DomEvent.stop).on(i,"click",this._cycleState,this).on(i,"click",this._refocusOnMap,this),L.Browser.any3d||L.DomUtil.addClass(i,"leaflet-disabled"),this._restyle(),t.on("rotate",this._restyle,this),this._follow=!1,this._canFollow=!1,this.options.closeOnZeroBearing&&0===t.getBearing()&&(o.style.display="none"),o},onRemove:function(t){t.off("rotate",this._restyle,this)},_handleMouseDown:function(t){L.DomEvent.stop(t),this.dragging=!0,this.dragstartX=t.pageX,this.dragstartY=t.pageY,L.DomEvent.on(document,"mousemove",this._handleMouseDrag,this).on(document,"mouseup",this._handleMouseUp,this)},_handleMouseUp:function(t){L.DomEvent.stop(t),this.dragging=!1,L.DomEvent.off(document,"mousemove",this._handleMouseDrag,this).off(document,"mouseup",this._handleMouseUp,this)},_handleMouseDrag:function(t){if(this.dragging){var o=t.clientX-this.dragstartX;this._map.setBearing(o)}},_cycleState:function(t){if(this._map){var o=this._map;o.touchRotate.enabled()||o.compassBearing.enabled()?o.compassBearing.enabled()?(o.compassBearing.disable(),o.setBearing(0),this.options.closeOnZeroBearing&&o.touchRotate.enable()):(o.touchRotate.disable(),o.compassBearing.enable()):o.touchRotate.enable(),this._restyle()}},_restyle:function(){if(this._map.options.rotate){var t=this._map,o=t.getBearing();this._arrow.style.transform="rotate("+o+"deg)",o&&this.options.closeOnZeroBearing&&(this._container.style.display="block"),t.compassBearing.enabled()?this._link.style.backgroundColor="orange":t.touchRotate.enabled()?this._link.style.backgroundColor=null:(this._link.style.backgroundColor="grey",0===o&&this.options.closeOnZeroBearing&&(this._container.style.display="none"))}else L.DomUtil.addClass(this._link,"leaflet-disabled")}}),L.control.rotate=function(t){return new L.Control.Rotate(t)},L.Map.mergeOptions({rotateControl:!0}),L.Map.addInitHook((function(){if(this.options.rotateControl){var t="object"==typeof this.options.rotateControl?this.options.rotateControl:{};this.rotateControl=L.control.rotate(t),this.addControl(this.rotateControl)}}))}));
1932
2
  //# sourceMappingURL=leaflet-rotate.js.map