leaflet-rotate 0.2.8 → 0.4.0

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.
Files changed (48) hide show
  1. package/.github/workflows/ci.yml +21 -0
  2. package/README.md +6 -2
  3. package/build/build.js +69 -0
  4. package/build/dev.js +24 -0
  5. package/build/server.js +104 -0
  6. package/build/test.js +18 -0
  7. package/cucumber.mjs +5 -0
  8. package/dist/leaflet-rotate-src.js +1425 -1853
  9. package/dist/leaflet-rotate-src.js.map +7 -1
  10. package/dist/leaflet-rotate.js +1 -1
  11. package/dist/leaflet-rotate.js.map +7 -1
  12. package/lib/debug.js +98 -69
  13. package/lib/debug.min.js +1 -1
  14. package/misc/leaflet-heat-rotate.js +96 -0
  15. package/misc/loremIpsum.js +1 -1
  16. package/misc/places.js +1 -1
  17. package/misc/route.js +1 -1
  18. package/package.json +10 -17
  19. package/src/control/Rotate.js +25 -25
  20. package/src/dom/DomUtil.js +31 -47
  21. package/src/dom/Draggable.js +1 -1
  22. package/src/geometry/Point.js +16 -7
  23. package/src/layer/DivOverlay.js +21 -7
  24. package/src/layer/Popup.js +15 -13
  25. package/src/layer/Tooltip.js +5 -5
  26. package/src/layer/marker/Icon.js +8 -8
  27. package/src/layer/marker/Marker.js +32 -18
  28. package/src/layer/tile/GridLayer.js +4 -4
  29. package/src/layer/vector/Renderer.js +51 -7
  30. package/src/map/Map.js +121 -57
  31. package/src/map/handler/CompassBearing.js +10 -8
  32. package/src/map/handler/ContainerMutation.js +2 -2
  33. package/src/map/handler/ShiftKeyRotate.js +4 -4
  34. package/src/map/handler/TouchGestures.js +36 -22
  35. package/src/map/handler/TouchRotate.js +2 -2
  36. package/src/map/handler/TouchZoom.js +4 -4
  37. package/test/features/example.feature +92 -0
  38. package/test/features/gestures.feature +33 -0
  39. package/test/features/overlays.feature +58 -0
  40. package/test/features/rotation.feature +36 -0
  41. package/test/index.html +59 -22
  42. package/test/steps/bearing.steps.js +235 -0
  43. package/test/steps/example.steps.js +424 -0
  44. package/test/steps/gestures.steps.js +145 -0
  45. package/test/steps/overlays.steps.js +427 -0
  46. package/test/support/hooks.js +92 -0
  47. package/build/rollup.config.js +0 -34
  48. package/test/setup/http_server.js +0 -104
@@ -4,7 +4,7 @@
4
4
  * @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/layer/tile/GridLayer.js
5
5
  */
6
6
 
7
- const gridLayerProto = L.extend({}, L.GridLayer.prototype);
7
+ const gridLayerProto = Object.defineProperties({}, Object.getOwnPropertyDescriptors(L.GridLayer.prototype));
8
8
 
9
9
  L.GridLayer.include({
10
10
 
@@ -14,8 +14,8 @@ L.GridLayer.include({
14
14
  *
15
15
  * @listens L.Map~rotate
16
16
  */
17
- getEvents: function() {
18
- var events = gridLayerProto.getEvents.apply(this, arguments);
17
+ getEvents() {
18
+ const events = gridLayerProto.getEvents.apply(this, arguments);
19
19
  if (this._map._rotate && !this.options.updateWhenIdle) {
20
20
  if (!this._onRotate) {
21
21
  this._onRotate = L.Util.throttle(this._onMoveEnd, this.options.updateInterval, this);
@@ -25,7 +25,7 @@ L.GridLayer.include({
25
25
  return events;
26
26
  },
27
27
 
28
- _getTiledPixelBounds: function(center) {
28
+ _getTiledPixelBounds(center) {
29
29
  if (!this._map._rotate) {
30
30
  return gridLayerProto._getTiledPixelBounds.apply(this, arguments);
31
31
  }
@@ -4,7 +4,9 @@
4
4
  * @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/layer/vector/Renderer.js
5
5
  */
6
6
 
7
- const rendererProto = L.extend({}, L.Renderer.prototype);
7
+ const rendererProto = Object.defineProperties({}, Object.getOwnPropertyDescriptors(L.Renderer.prototype));
8
+ const rendererBase = Object.getPrototypeOf(L.Renderer.prototype);
9
+ const rendererGetEvents = rendererProto.getEvents || rendererBase.getEvents;
8
10
 
9
11
  L.Renderer.include({
10
12
 
@@ -14,8 +16,9 @@ L.Renderer.include({
14
16
  *
15
17
  * @listens L.Map~rotate
16
18
  */
17
- getEvents: function() {
18
- return L.extend(rendererProto.getEvents.apply(this, arguments), { rotate: this._update });
19
+ getEvents() {
20
+ const events = rendererGetEvents.apply(this, arguments);
21
+ return L.version.startsWith('2.') ? events : Object.assign(events, { rotate: this._update });
19
22
  },
20
23
 
21
24
  /**
@@ -23,7 +26,7 @@ L.Renderer.include({
23
26
  *
24
27
  * @see https://github.com/Leaflet/Leaflet/pull/8794
25
28
  */
26
- onAdd: function() {
29
+ onAdd() {
27
30
  rendererProto.onAdd.apply(this, arguments);
28
31
  if (L.version <= "1.9.3") {
29
32
  // always keep transform-origin as 0 0
@@ -50,20 +53,61 @@ L.Renderer.include({
50
53
  *
51
54
  * @see https://github.com/Leaflet/Leaflet/compare/v1.7.0...v1.9.3
52
55
  */
53
- _updateTransform: function(center, zoom) {
56
+ _updateTransform(center, zoom) {
57
+ if (L.version.startsWith('2.')) {
58
+ if (this._map._rotate) {
59
+ const scale = this._map.getZoomScale(zoom, this._zoom),
60
+ offset = this._topLeftPoint.multiplyBy(scale)
61
+ .subtract(this._map._getNewPixelOrigin(center, zoom));
62
+
63
+ L.DomUtil.setTransform(this._container, offset, scale);
64
+ return;
65
+ }
66
+ return rendererBase._updateTransform.apply(this, arguments);
67
+ }
54
68
  if (!this._map._rotate) {
55
69
  return rendererProto._updateTransform.apply(this, arguments);
56
70
  }
71
+ if (zoom === this._zoom) {
72
+ // _reset() has already repositioned the renderer at the current zoom.
73
+ return;
74
+ }
57
75
  /**
58
76
  * @FIXME see path._renderer._reset();
59
77
  */
60
- var scale = this._map.getZoomScale(zoom, this._zoom),
78
+ const scale = this._map.getZoomScale(zoom, this._zoom),
61
79
  offset = this._map._latLngToNewLayerPoint(this._topLeft, zoom, center);
62
80
 
63
81
  L.DomUtil.setTransform(this._container, offset, scale);
64
82
 
65
83
  },
66
84
 
85
+ _onMoveEnd(ev) {
86
+ if (!L.version.startsWith('2.') || !this._map._rotate) {
87
+ return rendererBase._onMoveEnd.apply(this, arguments);
88
+ }
89
+
90
+ this._bounds = this._map._getPaddedPixelBounds(this.options.padding);
91
+ this._topLeft = this._map.layerPointToLatLng(this._bounds.min);
92
+ this._center = this._map.getCenter();
93
+ this._zoom = this._map.getZoom();
94
+ this._topLeftPoint = this._map._getNewPixelOrigin(this._center, this._zoom).add(this._bounds.min);
95
+ this._updateTransform(this._center, this._zoom);
96
+ this._resizeContainer();
97
+ this._onSettled(ev);
98
+ },
99
+
100
+ _resizeContainer() {
101
+ if (!L.version.startsWith('2.') || !this._map._rotate || !this._bounds) {
102
+ return rendererBase._resizeContainer.apply(this, arguments);
103
+ }
104
+
105
+ const size = this._bounds.getSize();
106
+ this._container.style.width = size.x + 'px';
107
+ this._container.style.height = size.y + 'px';
108
+ return size;
109
+ },
110
+
67
111
  // getEvents() {
68
112
  // const events = {
69
113
  // viewreset: this._reset,
@@ -106,7 +150,7 @@ L.Renderer.include({
106
150
  // }
107
151
  // },
108
152
 
109
- _update: function() {
153
+ _update() {
110
154
  if (!this._map._rotate) {
111
155
  return rendererProto._update.apply(this, arguments);
112
156
  }
package/src/map/Map.js CHANGED
@@ -4,17 +4,29 @@
4
4
  * @see https://github.com/Leaflet/Leaflet/blob/v1.9.3/src/map/Map.js
5
5
  */
6
6
 
7
- const mapProto = L.extend({}, L.Map.prototype);
7
+ import { toPoint } from '../geometry/Point';
8
+
9
+ const mapProto = Object.defineProperties({}, Object.getOwnPropertyDescriptors(L.Map.prototype));
8
10
 
9
11
  L.Map.mergeOptions({ rotate: false, bearing: 0, });
10
12
 
11
13
  L.Map.include({
12
14
 
15
+ _animateZoomNoDelay(center, zoom) {
16
+ if (!this._mapPane) { return; }
17
+
18
+ this._animatingZoom = true;
19
+ this._animateToCenter = center;
20
+ this._animateToZoom = zoom;
21
+ this._move(center, zoom, undefined, true);
22
+ this._onZoomTransitionEnd();
23
+ },
24
+
13
25
  /**
14
26
  * @param {(HTMLElement|String)} id html selector
15
27
  * @param {Object} [options={}] leaflet map options
16
28
  */
17
- initialize: function(id, options) {
29
+ initialize(id, options) {
18
30
  if (options.rotate) {
19
31
  this._rotate = true;
20
32
  this._bearing = 0;
@@ -33,11 +45,11 @@ L.Map.include({
33
45
  * @param {L.Point} point pixel screen coordinates
34
46
  * @returns {L.Point} transformed pixel point
35
47
  */
36
- containerPointToLayerPoint: function(point) {
48
+ containerPointToLayerPoint(point) {
37
49
  if (!this._rotate) {
38
50
  return mapProto.containerPointToLayerPoint.apply(this, arguments);
39
51
  }
40
- return L.point(point)
52
+ return toPoint(point)
41
53
  .subtract(this._getMapPanePos())
42
54
  .rotateFrom(-this._bearing, this._getRotatePanePos())
43
55
  .subtract(this._getRotatePanePos());
@@ -50,11 +62,11 @@ L.Map.include({
50
62
  * @param {L.Point} point pixel screen coordinates
51
63
  * @returns {L.Point} transformed pixel point
52
64
  */
53
- layerPointToContainerPoint: function(point) {
65
+ layerPointToContainerPoint(point) {
54
66
  if (!this._rotate) {
55
67
  return mapProto.layerPointToContainerPoint.apply(this, arguments);
56
68
  }
57
- return L.point(point)
69
+ return toPoint(point)
58
70
  .add(this._getRotatePanePos())
59
71
  .rotateFrom(this._bearing, this._getRotatePanePos())
60
72
  .add(this._getMapPanePos());
@@ -72,8 +84,8 @@ L.Map.include({
72
84
  *
73
85
  * @since leaflet-rotate (v0.1)
74
86
  */
75
- rotatedPointToMapPanePoint: function(point) {
76
- return L.point(point)
87
+ rotatedPointToMapPanePoint(point) {
88
+ return toPoint(point)
77
89
  .rotate(this._bearing)
78
90
  ._add(this._getRotatePanePos());
79
91
  },
@@ -89,18 +101,18 @@ L.Map.include({
89
101
  *
90
102
  * @since leaflet-rotate (v0.1)
91
103
  */
92
- mapPanePointToRotatedPoint: function(point) {
93
- return L.point(point)
104
+ mapPanePointToRotatedPoint(point) {
105
+ return toPoint(point)
94
106
  ._subtract(this._getRotatePanePos())
95
107
  .rotate(-this._bearing);
96
108
  },
97
109
 
98
- // latLngToLayerPoint: function (latlng) {
99
- // var projectedPoint = this.project(L.latLng(latlng))._round();
110
+ // latLngToLayerPoint(latlng) {
111
+ // const projectedPoint = this.project(L.latLng(latlng))._round();
100
112
  // return projectedPoint._subtract(this.getPixelOrigin());
101
113
  // },
102
114
 
103
- // latLngToContainerPoint: function (latlng) {
115
+ // latLngToContainerPoint(latlng) {
104
116
  // return this.layerPointToContainerPoint(this.latLngToLayerPoint(toLatLng(latlng)));
105
117
  // },
106
118
 
@@ -115,7 +127,7 @@ L.Map.include({
115
127
  *
116
128
  * @since leaflet-rotate (v0.2)
117
129
  */
118
- mapBoundsToContainerBounds: function (bounds) {
130
+ mapBoundsToContainerBounds(bounds) {
119
131
  if (!this._rotate && mapProto.mapBoundsToContainerBounds) {
120
132
  return mapProto.mapBoundsToContainerBounds.apply(this, arguments);
121
133
  }
@@ -132,9 +144,9 @@ L.Map.include({
132
144
  sw = this.layerPointToContainerPoint(this.project(bounds.getSouthWest())._subtract(origin)),
133
145
  se = this.layerPointToContainerPoint(this.project(bounds.getSouthEast())._subtract(origin));
134
146
 
135
- return L.bounds([
136
- L.point(Math.min(nw.x, ne.x, se.x, sw.x), Math.min(nw.y, ne.y, se.y, sw.y)), // [ minX, minY ]
137
- L.point(Math.max(nw.x, ne.x, se.x, sw.x), Math.max(nw.y, ne.y, se.y, sw.y)) // [ maxX, maxY ]
147
+ return new L.Bounds([
148
+ new L.Point(Math.min(nw.x, ne.x, se.x, sw.x), Math.min(nw.y, ne.y, se.y, sw.y)), // [ minX, minY ]
149
+ new L.Point(Math.max(nw.x, ne.x, se.x, sw.x), Math.max(nw.y, ne.y, se.y, sw.y)) // [ maxX, maxY ]
138
150
  ]);
139
151
  },
140
152
 
@@ -148,14 +160,14 @@ L.Map.include({
148
160
  *
149
161
  * @returns {L.LatLngBounds}
150
162
  */
151
- getBounds: function() {
163
+ getBounds() {
152
164
  if (!this._rotate) {
153
165
  return mapProto.getBounds.apply(this, arguments);
154
166
  }
155
167
 
156
168
  // SEE: https://github.com/fnicollet/Leaflet/pull/22
157
169
  //
158
- // var bounds = this.getPixelBounds(),
170
+ // const bounds = this.getPixelBounds(),
159
171
  // sw = this.unproject(bounds.getBottomLeft()),
160
172
  // ne = this.unproject(bounds.getTopRight());
161
173
  // return new LatLngBounds(sw, ne);
@@ -163,7 +175,7 @@ L.Map.include({
163
175
 
164
176
  // LatLngBounds' constructor automatically
165
177
  // extends the bounds to fit the passed points
166
- var size = this.getSize();
178
+ const size = this.getSize();
167
179
  return new L.LatLngBounds([
168
180
  this.containerPointToLatLng([0, 0]), // topleft
169
181
  this.containerPointToLatLng([size.x, 0]), // topright
@@ -193,13 +205,63 @@ L.Map.include({
193
205
  * Change map rotation
194
206
  *
195
207
  * @param {number} theta map degrees
208
+ * @param {Object} [options] animation options
209
+ * @param {boolean} [options.animate=false]
210
+ * @param {number} [options.duration=0.25] animation duration in seconds
211
+ * @param {number} [options.easeLinearity=0.5]
196
212
  *
197
213
  * @since leaflet-rotate (v0.1)
198
214
  */
199
- setBearing: function(theta) {
200
- if (!L.Browser.any3d || !this._rotate) { return; }
215
+ setBearing(theta, options) {
216
+ if (!this._rotate) { return; }
217
+
218
+ if (options && options.animate) {
219
+ this._bearingAnimationId = (this._bearingAnimationId || 0) + 1;
220
+ const animationId = this._bearingAnimationId;
221
+ if (this._bearingAnimationFrame) {
222
+ cancelAnimationFrame(this._bearingAnimationFrame);
223
+ }
224
+
225
+ const startBearing = this.getBearing(),
226
+ endBearing = L.Util.wrapNum(theta, [0, 360]),
227
+ delta = ((endBearing - startBearing + 540) % 360) - 180,
228
+ duration = Math.max(0, options.duration == null ? 0.25 : options.duration) * 1000,
229
+ easeLinearity = Math.max(options.easeLinearity || 0.5, 0.2),
230
+ startTime = performance.now();
231
+
232
+ const animate = function() {
233
+ if (!this._mapPane) {
234
+ delete this._bearingAnimationFrame;
235
+ return;
236
+ }
237
+
238
+ const progress = duration ? Math.min((performance.now() - startTime) / duration, 1) : 1,
239
+ eased = 1 - Math.pow(1 - progress, 1 / easeLinearity);
240
+
241
+ this._setBearing(progress === 1 ? endBearing : startBearing + delta * eased);
242
+ if (this._bearingAnimationId !== animationId) { return; }
243
+ if (progress < 1) {
244
+ this._bearingAnimationFrame = requestAnimationFrame(animate.bind(this));
245
+ } else {
246
+ delete this._bearingAnimationFrame;
247
+ }
248
+ };
249
+
250
+ this._bearingAnimationFrame = requestAnimationFrame(animate.bind(this));
251
+ return;
252
+ }
253
+
254
+ this._bearingAnimationId = (this._bearingAnimationId || 0) + 1;
255
+ if (this._bearingAnimationFrame) {
256
+ cancelAnimationFrame(this._bearingAnimationFrame);
257
+ delete this._bearingAnimationFrame;
258
+ }
201
259
 
202
- var bearing = L.Util.wrapNum(theta, [0, 360]) * L.DomUtil.DEG_TO_RAD,
260
+ this._setBearing(theta);
261
+ },
262
+
263
+ _setBearing(theta) {
264
+ const bearing = L.Util.wrapNum(theta, [0, 360]) * (Math.PI / 180),
203
265
  center = this._getPixelCenter(),
204
266
  oldPos = this._getRotatePanePos().rotateFrom(-this._bearing, center),
205
267
  newPos = oldPos.rotateFrom(bearing, center);
@@ -221,8 +283,8 @@ L.Map.include({
221
283
  *
222
284
  * @since leaflet-rotate (v0.1)
223
285
  */
224
- getBearing: function() {
225
- return this._bearing * L.DomUtil.RAD_TO_DEG;
286
+ getBearing() {
287
+ return this._bearing * (180 / Math.PI);
226
288
  },
227
289
 
228
290
  /**
@@ -234,7 +296,7 @@ L.Map.include({
234
296
  * @param {HTMLElement} [container] parent element
235
297
  * @returns {HTMLElement} pane container
236
298
  */
237
- // createPane: function(name, container) {
299
+ // createPane(name, container) {
238
300
  // if (!this._rotate || name == 'mapPane') {
239
301
  // return mapProto.createPane.apply(this, arguments);
240
302
  // }
@@ -263,8 +325,8 @@ L.Map.include({
263
325
  * - tooltipPane [HTMLElement = 650] - Pane for tooltips.
264
326
  * - popupPane [HTMLElement = 700] - Pane for popups.
265
327
  */
266
- _initPanes: function() {
267
- var panes = this._panes = {};
328
+ _initPanes() {
329
+ const panes = this._panes = {};
268
330
  this._paneRenderers = {};
269
331
 
270
332
  this._mapPane = this.createPane('mapPane', this._container);
@@ -273,6 +335,9 @@ L.Map.include({
273
335
  if (this._rotate) {
274
336
  this._rotatePane = this.createPane('rotatePane', this._mapPane);
275
337
  this._norotatePane = this.createPane('norotatePane', this._mapPane);
338
+ if (L.version.startsWith('2.')) {
339
+ this._rotatePane.style.transformOrigin = '0 0';
340
+ }
276
341
  // rotatePane
277
342
  this.createPane('tilePane', this._rotatePane);
278
343
  this.createPane('overlayPane', this._rotatePane);
@@ -291,8 +356,8 @@ L.Map.include({
291
356
  }
292
357
 
293
358
  if (!this.options.markerZoomAnimation) {
294
- L.DomUtil.addClass(panes.markerPane, 'leaflet-zoom-hide');
295
- L.DomUtil.addClass(panes.shadowPane, 'leaflet-zoom-hide');
359
+ panes.markerPane.classList.add('leaflet-zoom-hide');
360
+ panes.shadowPane.classList.add('leaflet-zoom-hide');
296
361
  }
297
362
  },
298
363
 
@@ -316,18 +381,17 @@ L.Map.include({
316
381
 
317
382
  options = options || {};
318
383
 
319
- const paddingTL = L.point(options.paddingTopLeft || options.padding || [0, 0]),
320
- paddingBR = L.point(options.paddingBottomRight || options.padding || [0, 0]),
384
+ const paddingTL = toPoint(options.paddingTopLeft || options.padding || [0, 0]),
385
+ paddingBR = toPoint(options.paddingBottomRight || options.padding || [0, 0]),
321
386
  /** @TODO use mapProto.panInside */
322
387
  // pixelPoint = this.project(latlng),
323
388
  // pixelBounds = this.getPixelBounds(),
324
389
  // pixelCenter = this.project(this.getCenter()),
325
- rect = this._container.getBoundingClientRect(),
326
390
  pixelPoint = this.latLngToContainerPoint(latlng),
327
- pixelBounds = L.bounds([ L.point(rect), L.point(rect).add(this.getSize()) ]),
391
+ pixelBounds = new L.Bounds([new L.Point(0, 0), this.getSize()]),
328
392
  pixelCenter = pixelBounds.getCenter(),
329
393
  //
330
- paddedBounds = L.bounds([pixelBounds.min.add(paddingTL), pixelBounds.max.subtract(paddingBR)]),
394
+ paddedBounds = new L.Bounds([pixelBounds.min.add(paddingTL), pixelBounds.max.subtract(paddingBR)]),
331
395
  paddedSize = paddedBounds.getSize();
332
396
 
333
397
  if (!paddedBounds.contains(pixelPoint)) {
@@ -359,9 +423,9 @@ L.Map.include({
359
423
  * @param {Object} [options] pan options
360
424
  * @returns {L.Map} current map instance
361
425
  */
362
- // panInsideBounds: function (bounds, options) {
426
+ // panInsideBounds(bounds, options) {
363
427
  // this._enforcingBounds = true;
364
- // var center = this.getCenter(),
428
+ // const center = this.getCenter(),
365
429
  // newCenter = this._limitCenter(center, this._zoom, L.latLngBounds(bounds));
366
430
  //
367
431
  // if (!center.equals(newCenter)) {
@@ -437,8 +501,8 @@ L.Map.include({
437
501
  return mapProto.getBoundsZoom.apply(this, arguments);
438
502
  }
439
503
 
440
- bounds = L.latLngBounds(bounds);
441
- padding = L.point(padding || [0, 0]);
504
+ bounds = bounds instanceof L.LatLngBounds ? bounds : new L.LatLngBounds(bounds);
505
+ padding = toPoint(padding || [0, 0]);
442
506
 
443
507
  let zoom = this.getZoom() || 0;
444
508
  const min = this.getMinZoom(),
@@ -470,7 +534,7 @@ L.Map.include({
470
534
  *
471
535
  * @returns {L.Point} layer center
472
536
  */
473
- // _getCenterLayerPoint: function () {
537
+ // _getCenterLayerPoint() {
474
538
  // return this.containerPointToLayerPoint(this.getSize()._divideBy(2));
475
539
  // },
476
540
 
@@ -479,8 +543,8 @@ L.Map.include({
479
543
  *
480
544
  * @param {L.LatLng} latlng map coordinates
481
545
  */
482
- _getCenterOffset: function(latlng) {
483
- var centerOffset = mapProto._getCenterOffset.apply(this, arguments);
546
+ _getCenterOffset(latlng) {
547
+ let centerOffset = mapProto._getCenterOffset.apply(this, arguments);
484
548
  if (this._rotate) {
485
549
  centerOffset = centerOffset.rotate(this._bearing);
486
550
  }
@@ -490,7 +554,7 @@ L.Map.include({
490
554
  /**
491
555
  * @since leaflet-rotate (v0.1)
492
556
  */
493
- _getRotatePanePos: function() {
557
+ _getRotatePanePos() {
494
558
  return this._rotatePanePos || new L.Point(0, 0);
495
559
  // return L.DomUtil.getPosition(this._rotatePane) || new L.Point(0, 0);
496
560
  },
@@ -500,11 +564,11 @@ L.Map.include({
500
564
  // return this.project(latlng, zoom)._subtract(topLeft);
501
565
  //},
502
566
 
503
- _getNewPixelOrigin: function(center, zoom) {
504
- if (!this._rotate) {
567
+ _getNewPixelOrigin(center, zoom) {
568
+ if (!this._rotate || L.version.startsWith('2.')) {
505
569
  return mapProto._getNewPixelOrigin.apply(this, arguments);
506
570
  }
507
- var viewHalf = this.getSize()._divideBy(2);
571
+ const viewHalf = this.getSize()._divideBy(2);
508
572
  return this.project(center, zoom)
509
573
  .rotate(this._bearing)
510
574
  ._subtract(viewHalf)
@@ -519,13 +583,13 @@ L.Map.include({
519
583
  *
520
584
  * @see src\layer\tile\GridLayer::_getTiledPixelBounds()
521
585
  */
522
- _getNewPixelBounds: function(center, zoom) {
586
+ _getNewPixelBounds(center, zoom) {
523
587
  center = center || this.getCenter();
524
588
  zoom = zoom || this.getZoom();
525
589
  if (!this._rotate && mapProto._getNewPixelBounds) {
526
590
  return mapProto._getNewPixelBounds.apply(this, arguments);
527
591
  }
528
- var mapZoom = this._animatingZoom ? Math.max(this._animateToZoom, this.getZoom()) : this.getZoom(),
592
+ const mapZoom = this._animatingZoom ? Math.max(this._animateToZoom, this.getZoom()) : this.getZoom(),
529
593
  scale = this.getZoomScale(mapZoom, zoom),
530
594
  pixelCenter = this.project(center, zoom).floor(),
531
595
  size = this.getSize(),
@@ -544,7 +608,7 @@ L.Map.include({
544
608
  *
545
609
  * @return {L.Point} map pivot point (center)
546
610
  */
547
- _getPixelCenter: function() {
611
+ _getPixelCenter() {
548
612
  if (!this._rotate && mapProto._getPixelCenter) {
549
613
  return mapProto._getPixelCenter.apply(this, arguments);
550
614
  }
@@ -556,11 +620,11 @@ L.Map.include({
556
620
  *
557
621
  * @see src\layer\vector\Renderer::_update()
558
622
  */
559
- _getPaddedPixelBounds: function(padding) {
623
+ _getPaddedPixelBounds(padding) {
560
624
  if (!this._rotate && mapProto._getPaddedPixelBounds) {
561
625
  return mapProto._getPaddedPixelBounds.apply(this, arguments);
562
626
  }
563
- var p = padding,
627
+ const p = padding,
564
628
  size = this.getSize(),
565
629
  padMin = size.multiplyBy(-p),
566
630
  padMax = size.multiplyBy(1 + p);
@@ -574,10 +638,10 @@ L.Map.include({
574
638
  ]);
575
639
  },
576
640
 
577
- _handleGeolocationResponse: function(pos) {
641
+ _handleGeolocationResponse(pos) {
578
642
  if (!this._container._leaflet_id) { return; }
579
643
 
580
- var lat = pos.coords.latitude,
644
+ const lat = pos.coords.latitude,
581
645
  lng = pos.coords.longitude,
582
646
  /** @TODO use mapProto._handleGeolocationResponse */
583
647
  hdg = pos.coords.heading,
@@ -586,11 +650,11 @@ L.Map.include({
586
650
  options = this._locateOptions;
587
651
 
588
652
  if (options.setView) {
589
- var zoom = this.getBoundsZoom(bounds);
653
+ const zoom = this.getBoundsZoom(bounds);
590
654
  this.setView(latlng, options.maxZoom ? Math.min(zoom, options.maxZoom) : zoom);
591
655
  }
592
656
 
593
- var data = {
657
+ const data = {
594
658
  latlng: latlng,
595
659
  bounds: bounds,
596
660
  timestamp: pos.timestamp,
@@ -598,7 +662,7 @@ L.Map.include({
598
662
  heading: hdg
599
663
  };
600
664
 
601
- for (var i in pos.coords) {
665
+ for (const i in pos.coords) {
602
666
  if (typeof pos.coords[i] === 'number') {
603
667
  data[i] = pos.coords[i];
604
668
  }
@@ -617,7 +681,7 @@ L.Map.include({
617
681
  * @returns {L.Bounds}
618
682
  */
619
683
  // toCircumscribedBounds(points) {
620
- // var minX = points.reduce(function (pv, v) { return Math.min(pv, v.x); }, points[0].x),
684
+ // const minX = points.reduce(function (pv, v) { return Math.min(pv, v.x); }, points[0].x),
621
685
  // maxX = points.reduce(function (pv, v) { return Math.max(pv, v.x); }, points[0].x),
622
686
  // minY = points.reduce(function (pv, v) { return Math.min(pv, v.y); }, points[0].y),
623
687
  // maxY = points.reduce(function (pv, v) { return Math.max(pv, v.y); }, points[0].y);
@@ -6,7 +6,7 @@
6
6
 
7
7
  L.Map.CompassBearing = L.Handler.extend({
8
8
 
9
- initialize: function(map) {
9
+ initialize(map) {
10
10
  this._map = map;
11
11
  /** @see https://caniuse.com/?search=DeviceOrientation */
12
12
  if ('ondeviceorientationabsolute' in window) {
@@ -17,7 +17,7 @@ L.Map.CompassBearing = L.Handler.extend({
17
17
  this._throttled = L.Util.throttle(this._onDeviceOrientation, 100, this);
18
18
  },
19
19
 
20
- addHooks: function() {
20
+ addHooks() {
21
21
  if (this._map._rotate && this.__deviceOrientationEvent) {
22
22
  L.DomEvent.on(window, this.__deviceOrientationEvent, this._throttled, this);
23
23
  } else {
@@ -27,7 +27,7 @@ L.Map.CompassBearing = L.Handler.extend({
27
27
  }
28
28
  },
29
29
 
30
- removeHooks: function() {
30
+ removeHooks() {
31
31
  if (this._map._rotate && this.__deviceOrientationEvent) {
32
32
  L.DomEvent.off(window, this.__deviceOrientationEvent, this._throttled, this);
33
33
  }
@@ -51,12 +51,14 @@ L.Map.CompassBearing = L.Handler.extend({
51
51
  * @see https://developer.mozilla.org/en-US/docs/Web/API/DeviceOrientationEvent/alpha
52
52
  * @see https://developer.mozilla.org/en-US/docs/Web/API/Window/orientation
53
53
  */
54
- _onDeviceOrientation: function(e) {
55
- var angle = e.webkitCompassHeading || e.alpha;
56
- var deviceOrientation = 0;
54
+ _onDeviceOrientation(e) {
55
+ let angle = e.webkitCompassHeading != null ? e.webkitCompassHeading : e.alpha;
56
+ let deviceOrientation = 0;
57
57
 
58
- // Safari iOS
59
- if (!e.absolute && e.webkitCompassHeading) {
58
+ if (!Number.isFinite(angle)) { return; }
59
+
60
+ // Safari iOS
61
+ if (!e.absolute && e.webkitCompassHeading) {
60
62
  angle = 360 - angle;
61
63
  }
62
64
 
@@ -27,7 +27,7 @@ L.Map.mergeOptions({
27
27
 
28
28
  L.Map.ContainerMutation = L.Handler.extend({
29
29
 
30
- addHooks: function() {
30
+ addHooks() {
31
31
  // if (!L.Browser.mutation) { return; }
32
32
  if (!this._observer) {
33
33
  this._observer = new MutationObserver(L.Util.bind(this._map.invalidateSize, this._map));
@@ -41,7 +41,7 @@ L.Map.ContainerMutation = L.Handler.extend({
41
41
  });
42
42
  },
43
43
 
44
- removeHooks: function() {
44
+ removeHooks() {
45
45
  // if (!L.Browser.mutation) { return; }
46
46
  this._observer.disconnect();
47
47
  },
@@ -17,22 +17,22 @@ L.Map.mergeOptions({
17
17
 
18
18
  L.Map.ShiftKeyRotate = L.Handler.extend({
19
19
 
20
- addHooks: function() {
20
+ addHooks() {
21
21
  L.DomEvent.on(this._map._container, "wheel", this._handleShiftScroll, this);
22
22
  // this._map.shiftKeyRotate.enable();
23
23
  this._map.shiftKeyRotate.rotate = true;
24
24
  },
25
25
 
26
- removeHooks: function() {
26
+ removeHooks() {
27
27
  L.DomEvent.off(this._map._container, "wheel", this._handleShiftScroll, this);
28
28
  this._map.shiftKeyRotate.rotate = false;
29
29
  },
30
30
 
31
- _handleShiftScroll: function(e) {
31
+ _handleShiftScroll(e) {
32
32
  if (e.shiftKey) {
33
33
  e.preventDefault();
34
34
  this._map.scrollWheelZoom.disable();
35
- this._map.setBearing((this._map._bearing * L.DomUtil.RAD_TO_DEG) + Math.sign(e.deltaY) * 5);
35
+ this._map.setBearing((this._map._bearing * (180 / Math.PI)) + Math.sign(e.deltaY) * 5);
36
36
  } else {
37
37
  this._map.scrollWheelZoom.enable();
38
38
  }