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
package/package.json CHANGED
@@ -1,17 +1,15 @@
1
1
  {
2
2
  "name": "leaflet-rotate",
3
- "version": "0.2.8",
3
+ "version": "0.4.0",
4
4
  "description": "A Leaflet plugin that allows to add rotation functionality to map tiles",
5
5
  "type": "module",
6
6
  "main": "dist/leaflet-rotate.js",
7
7
  "browser": "dist/leaflet-rotate.js",
8
8
  "module": "src/index.js",
9
9
  "scripts": {
10
- "test": "uvu . \"(examples|src)[\\\\/].*\\.spec\\.js$\"",
11
- "build": "rollup -c build/rollup.config.js",
12
- "watch": "rollup -c build/rollup.config.js --watch",
13
- "dev": "npm-run-all --print-label --parallel serve watch",
14
- "serve": "http-server",
10
+ "dev": "node build/dev.js",
11
+ "build": "node build/build.js",
12
+ "test": "node build/test.js",
15
13
  "version": "npm run build && git add -A dist"
16
14
  },
17
15
  "repository": {
@@ -48,17 +46,12 @@
48
46
  "url": "https://github.com/Raruto/leaflet-rotate/issues"
49
47
  },
50
48
  "homepage": "https://github.com/Raruto/leaflet-rotate#readme",
51
- "devDependencies": {
52
- "rollup": "^3.20.6",
53
- "@rollup/plugin-commonjs": "^24.1.0",
54
- "@rollup/plugin-node-resolve": "^15.0.2",
55
- "@rollup/plugin-terser": "^0.4.1",
56
- "http-server": "^14.1.1",
57
- "npm-run-all": "^4.1.5",
58
- "playwright": "^1.32.3",
59
- "uvu": "^0.5.6"
60
- },
61
49
  "peerDependencies": {
62
- "leaflet": "^1.9.3"
50
+ "leaflet": "^1.9.3 || ^2.0.0-alpha.1"
51
+ },
52
+ "devDependencies": {
53
+ "@cucumber/cucumber": "^10.3.1",
54
+ "esbuild": "^0.28.2",
55
+ "playwright": "^1.64.1"
63
56
  }
64
57
  }
@@ -15,12 +15,12 @@ L.Control.Rotate = L.Control.extend({
15
15
  closeOnZeroBearing: true
16
16
  },
17
17
 
18
- onAdd: function(map) {
19
- var container = this._container = L.DomUtil.create('div', 'leaflet-control-rotate leaflet-bar');
18
+ onAdd(map) {
19
+ const container = this._container = L.DomUtil.create('div', 'leaflet-control-rotate leaflet-bar');
20
20
 
21
21
  // this.button = L.Control.Zoom.prototype._createButton.call(this, 'R', 'leaflet-control-rotate', 'leaflet-control-rotate', container, this._toggleLock);
22
22
 
23
- var arrow = this._arrow = L.DomUtil.create('span', 'leaflet-control-rotate-arrow');
23
+ const arrow = this._arrow = L.DomUtil.create('span', 'leaflet-control-rotate-arrow');
24
24
 
25
25
  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")`;
26
26
  arrow.style.cursor = 'grab';
@@ -31,7 +31,7 @@ L.Control.Rotate = L.Control.extend({
31
31
  arrow.style.backgroundPosition = '50%';
32
32
 
33
33
  // Copy-pasted from L.Control.Zoom
34
- var link = this._link = L.DomUtil.create('a', 'leaflet-control-rotate-toggle', container);
34
+ const link = this._link = L.DomUtil.create('a', 'leaflet-control-rotate-toggle', container);
35
35
  link.appendChild(arrow);
36
36
  link.href = '#';
37
37
  link.title = 'Rotate map';
@@ -43,10 +43,6 @@ L.Control.Rotate = L.Control.extend({
43
43
  .on(link, 'click', this._cycleState, this)
44
44
  .on(link, 'click', this._refocusOnMap, this);
45
45
 
46
- if (!L.Browser.any3d) {
47
- L.DomUtil.addClass(link, 'leaflet-disabled');
48
- }
49
-
50
46
  this._restyle();
51
47
 
52
48
  map.on('rotate', this._restyle, this);
@@ -62,11 +58,11 @@ L.Control.Rotate = L.Control.extend({
62
58
  return container;
63
59
  },
64
60
 
65
- onRemove: function(map) {
61
+ onRemove(map) {
66
62
  map.off('rotate', this._restyle, this);
67
63
  },
68
64
 
69
- _handleMouseDown: function(e) {
65
+ _handleMouseDown(e) {
70
66
  L.DomEvent.stop(e);
71
67
  this.dragging = true;
72
68
  this.dragstartX = e.pageX;
@@ -76,7 +72,7 @@ L.Control.Rotate = L.Control.extend({
76
72
  .on(document, 'mouseup', this._handleMouseUp, this);
77
73
  },
78
74
 
79
- _handleMouseUp: function(e) {
75
+ _handleMouseUp(e) {
80
76
  L.DomEvent.stop(e);
81
77
  this.dragging = false;
82
78
 
@@ -85,18 +81,18 @@ L.Control.Rotate = L.Control.extend({
85
81
  .off(document, 'mouseup', this._handleMouseUp, this);
86
82
  },
87
83
 
88
- _handleMouseDrag: function(e) {
84
+ _handleMouseDrag(e) {
89
85
  if (!this.dragging) { return; }
90
- var deltaX = e.clientX - this.dragstartX;
86
+ const deltaX = e.clientX - this.dragstartX;
91
87
  this._map.setBearing(deltaX);
92
88
  },
93
89
 
94
- _cycleState: function(ev) {
90
+ _cycleState(ev) {
95
91
  if (!this._map) {
96
92
  return;
97
93
  }
98
94
 
99
- var map = this._map;
95
+ const map = this._map;
100
96
 
101
97
  // Touch mode
102
98
  if (!map.touchRotate.enabled() && !map.compassBearing.enabled()) {
@@ -106,7 +102,11 @@ L.Control.Rotate = L.Control.extend({
106
102
  // Compass mode
107
103
  else if (!map.compassBearing.enabled()) {
108
104
  map.touchRotate.disable();
109
- map.compassBearing.enable();
105
+ (
106
+ DeviceOrientationEvent && DeviceOrientationEvent.requestPermission
107
+ ? DeviceOrientationEvent.requestPermission() // iOS compass
108
+ : Promise.resolve('granted') // others
109
+ ).then(state => "granted" === state && map.compassBearing.enable())
110
110
  }
111
111
 
112
112
  // Locked mode
@@ -120,12 +120,12 @@ L.Control.Rotate = L.Control.extend({
120
120
  this._restyle();
121
121
  },
122
122
 
123
- _restyle: function() {
123
+ _restyle() {
124
124
  if (!this._map.options.rotate) {
125
- L.DomUtil.addClass(this._link, 'leaflet-disabled');
125
+ this._link.classList.add('leaflet-disabled');
126
126
  } else {
127
- var map = this._map;
128
- var bearing = map.getBearing();
127
+ const map = this._map;
128
+ const bearing = map.getBearing();
129
129
 
130
130
  this._arrow.style.transform = 'rotate(' + bearing + 'deg)';
131
131
 
@@ -155,9 +155,9 @@ L.Control.Rotate = L.Control.extend({
155
155
 
156
156
  });
157
157
 
158
- L.control.rotate = function(options) {
159
- return new L.Control.Rotate(options);
160
- };
158
+ if (L.control) {
159
+ L.control.rotate = options => new L.Control.Rotate(options);
160
+ }
161
161
 
162
162
  L.Map.mergeOptions({
163
163
  rotateControl: true,
@@ -165,8 +165,8 @@ L.Map.mergeOptions({
165
165
 
166
166
  L.Map.addInitHook(function() {
167
167
  if (this.options.rotateControl) {
168
- var options = typeof this.options.rotateControl === 'object' ? this.options.rotateControl : {};
169
- this.rotateControl = L.control.rotate(options);
168
+ const options = typeof this.options.rotateControl === 'object' ? this.options.rotateControl : {};
169
+ this.rotateControl = new L.Control.Rotate(options);
170
170
  this.addControl(this.rotateControl);
171
171
  }
172
172
  });
@@ -4,75 +4,59 @@
4
4
  * @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/dom/DomUtil.js
5
5
  */
6
6
 
7
- const domUtilProto = L.extend({}, L.DomUtil);
8
-
9
- L.extend(L.DomUtil, {
7
+ const domUtilProto = Object.assign({}, L.DomUtil);
10
8
 
9
+ Object.assign(L.DomUtil, {
11
10
  /**
12
- * Resets the 3D CSS transform of `el` so it is
13
- * translated by `offset` pixels and optionally
14
- * scaled by `scale`. Does not have an effect if
15
- * the browser doesn't support 3D CSS transforms.
16
- *
17
- * @param {HTMLElement} el
18
- * @param {L.Point} offset
11
+ * Resets the 3D CSS transform of `el` so it is translated by `offset` pixels,
12
+ * optionally scaled by `scale`, and rotated around `pivot` when `bearing` is set.
13
+ *
14
+ * @param {HTMLElement} el
15
+ * @param {L.Point} offset
19
16
  * @param {Number} scale
20
- * @param {Number} bearing
21
- * @param {L.Point} pivot
17
+ * @param {Number} bearing
18
+ * @param {L.Point} pivot
22
19
  */
23
- setTransform: function(el, offset, scale, bearing, pivot) {
24
- var pos = offset || new L.Point(0, 0);
20
+ setTransform(el, offset, scale, bearing, pivot) {
21
+ let pos = offset || new L.Point(0, 0);
25
22
 
26
23
  if (!bearing) {
27
- offset = pos._round();
28
- return domUtilProto.setTransform.apply(this, arguments);
24
+ return domUtilProto.setTransform(el, pos._round(), scale);
29
25
  }
30
26
 
31
27
  pos = pos.rotateFrom(bearing, pivot);
32
-
33
- el.style[L.DomUtil.TRANSFORM] =
34
- 'translate3d(' + pos.x + 'px,' + pos.y + 'px' + ',0)' +
28
+ el.style.transform =
29
+ 'translate3d(' + pos.x + 'px,' + pos.y + 'px,0)' +
35
30
  (scale ? ' scale(' + scale + ')' : '') +
36
31
  ' rotate(' + bearing + 'rad)';
37
32
  },
38
33
 
39
34
  /**
40
- * Sets the position of `el` to coordinates specified by
41
- * `position`, using CSS translate or top/left positioning
42
- * depending on the browser (used by Leaflet internally
43
- * to position its layers).
44
- *
45
- * @param {HTMLElement} el
46
- * @param {L.Point} point
35
+ * Sets the position of `el` to `point`, using CSS transforms or top/left positioning
36
+ * depending on browser support, and optionally rotating it around `pivot`.
37
+ *
38
+ * @param {HTMLElement} el
39
+ * @param {L.Point} point
47
40
  * @param {Number} bearing
48
- * @param {L.Point} pivot
49
- * @param {Number} scale
41
+ * @param {L.Point} pivot
42
+ * @param {Number} scale
50
43
  */
51
- setPosition: function(el, point, bearing, pivot, scale) {
44
+ setPosition(el, point, bearing, pivot, scale) {
52
45
  if (!bearing) {
53
- return domUtilProto.setPosition.apply(this, arguments);
46
+ return domUtilProto.setPosition(el, point);
54
47
  }
55
48
 
56
- /*eslint-disable */
57
49
  el._leaflet_pos = point;
58
- /*eslint-enable */
59
-
60
- if (L.Browser.any3d) {
61
- L.DomUtil.setTransform(el, point, scale, bearing, pivot);
62
- } else {
63
- el.style.left = point.x + 'px';
64
- el.style.top = point.y + 'px';
65
- }
50
+ L.DomUtil.setTransform(el, point, scale, bearing, pivot);
66
51
  },
67
52
 
68
53
  /**
69
- * @constant radians = degrees × π/180°
54
+ * Returns the position assigned to `el`.
55
+ *
56
+ * @param {HTMLElement} el
57
+ * @returns {L.Point}
70
58
  */
71
- DEG_TO_RAD: Math.PI / 180,
72
-
73
- /**
74
- * @constant degrees = radians × 180°/π
75
- */
76
- RAD_TO_DEG: 180 / Math.PI,
77
-
59
+ getPosition(el) {
60
+ return el._leaflet_pos || domUtilProto.getPosition(el);
61
+ }
78
62
  });
@@ -13,7 +13,7 @@
13
13
  L.Draggable.include({
14
14
 
15
15
  /** @TODO */
16
- // updateMapBearing: function(mapBearing) {
16
+ // updateMapBearing(mapBearing) {
17
17
  // this._mapBearing = mapBearing;
18
18
  // },
19
19
 
@@ -4,7 +4,7 @@
4
4
  * @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/geometry/Point.js
5
5
  */
6
6
 
7
- L.extend(L.Point.prototype, {
7
+ Object.assign(L.Point.prototype, {
8
8
 
9
9
  /**
10
10
  * Rotate around (0,0) by applying the 2D rotation matrix:
@@ -14,7 +14,7 @@ L.extend(L.Point.prototype, {
14
14
  *
15
15
  * @param theta must be given in radians.
16
16
  */
17
- rotate: function(theta) {
17
+ rotate(theta) {
18
18
  return this.rotateFrom(theta, new L.Point(0,0))
19
19
  },
20
20
 
@@ -32,13 +32,13 @@ L.extend(L.Point.prototype, {
32
32
  *
33
33
  * @returns {L.Point}
34
34
  */
35
- rotateFrom: function(theta, pivot) {
35
+ rotateFrom(theta, pivot) {
36
36
  if (!theta) { return this; }
37
- var sinTheta = Math.sin(theta);
38
- var cosTheta = Math.cos(theta);
39
- var cx = pivot.x,
37
+ const sinTheta = Math.sin(theta);
38
+ const cosTheta = Math.cos(theta);
39
+ const cx = pivot.x,
40
40
  cy = pivot.y;
41
- var x = this.x - cx,
41
+ const x = this.x - cx,
42
42
  y = this.y - cy;
43
43
 
44
44
  return new L.Point(
@@ -48,3 +48,12 @@ L.extend(L.Point.prototype, {
48
48
  },
49
49
 
50
50
  });
51
+
52
+ export function toPoint(point) {
53
+ if (point == null || point instanceof L.Point) {
54
+ return point;
55
+ }
56
+ return Array.isArray(point)
57
+ ? new L.Point(point[0], point[1])
58
+ : new L.Point(point.x, point.y);
59
+ }
@@ -4,7 +4,9 @@
4
4
  * @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/layer/DivOverlay.js
5
5
  */
6
6
 
7
- const divOverlayProto = L.extend({}, L.DivOverlay.prototype);
7
+ import { toPoint } from '../geometry/Point';
8
+
9
+ const divOverlayProto = Object.defineProperties({}, Object.getOwnPropertyDescriptors(L.DivOverlay.prototype));
8
10
 
9
11
  L.DivOverlay.include({
10
12
 
@@ -14,21 +16,33 @@ L.DivOverlay.include({
14
16
  *
15
17
  * @listens L.Map~rotate
16
18
  */
17
- getEvents: function() {
18
- return L.extend(divOverlayProto.getEvents.apply(this, arguments), { rotate: this._updatePosition });
19
+ getEvents() {
20
+ return Object.assign(divOverlayProto.getEvents.apply(this, arguments), { rotate: this._updatePosition });
19
21
  },
20
22
 
21
23
  /**
22
24
  * 0. update element anchor point (divOverlayProto v1.9.3)
23
25
  * 1. rotate around anchor point (subtract anchor -> rotate point -> add anchor)
24
26
  */
25
- _updatePosition: function() {
27
+ _updatePosition() {
26
28
  if (!this._map) { return; }
27
29
  divOverlayProto._updatePosition.apply(this, arguments);
28
- if (this._map && this._map._rotate && this._zoomAnimated) {
29
- var anchor = this._getAnchor();
30
- var pos = L.DomUtil.getPosition(this._container).subtract(anchor);
30
+ if (this._map._rotate && this._zoomAnimated) {
31
+ const anchor = this._getAnchor();
32
+ const pos = L.DomUtil.getPosition(this._container).subtract(anchor);
31
33
  L.DomUtil.setPosition(this._container, this._map.rotatedPointToMapPanePoint(pos).add(anchor));
34
+ } else if (this._map._rotate) {
35
+ const mapPanePoint = this._map.rotatedPointToMapPanePoint(this._map.latLngToLayerPoint(this._latlng)),
36
+ offset = toPoint(this.options.offset || [0, 0]),
37
+ anchor = this._getAnchor();
38
+
39
+ this._containerLeft = -Math.round(this._containerWidth / 2) + mapPanePoint.x + offset.x + anchor.x;
40
+ this._containerBottom = -(mapPanePoint.y + offset.y + anchor.y);
41
+ this._container.style.left = this._containerLeft + 'px';
42
+ this._container.style.bottom = this._containerBottom + 'px';
43
+ this._container.style.top = '';
44
+ L.DomUtil.setPosition(this._container, new L.Point(0, 0));
45
+ this._container.style.transform = '';
32
46
  }
33
47
 
34
48
  },
@@ -4,7 +4,9 @@
4
4
  * @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/layer/Popup.js
5
5
  */
6
6
 
7
- const popupProto = L.extend({}, L.Popup.prototype);
7
+ import { toPoint } from '../geometry/Point';
8
+
9
+ const popupProto = Object.defineProperties({}, Object.getOwnPropertyDescriptors(L.Popup.prototype));
8
10
 
9
11
  L.Popup.include({
10
12
 
@@ -12,11 +14,11 @@ L.Popup.include({
12
14
  * 0. update element anchor point (popupProto v1.9.3)
13
15
  * 1. rotate around anchor point (subtract anchor -> rotate point -> add anchor)
14
16
  */
15
- _animateZoom: function(e) {
17
+ _animateZoom(e) {
16
18
  popupProto._animateZoom.apply(this, arguments);
17
19
  if (this._map && this._map._rotate) {
18
- var anchor = this._getAnchor();
19
- var pos = L.DomUtil.getPosition(this._container).subtract(anchor);
20
+ const anchor = this._getAnchor();
21
+ const pos = L.DomUtil.getPosition(this._container).subtract(anchor);
20
22
  L.DomUtil.setPosition(this._container, this._map.rotatedPointToMapPanePoint(pos).add(anchor));
21
23
  }
22
24
  },
@@ -26,7 +28,7 @@ L.Popup.include({
26
28
  *
27
29
  * @see https://github.com/fnicollet/Leaflet/pull/21
28
30
  */
29
- _adjustPan: function() {
31
+ _adjustPan() {
30
32
  if (!this.options.autoPan || (this._map._panAnim && this._map._panAnim._inProgress)) { return; }
31
33
 
32
34
  // We can endlessly recurse if keepInView is set and the view resets.
@@ -36,8 +38,8 @@ L.Popup.include({
36
38
  return;
37
39
  }
38
40
 
39
- var map = this._map,
40
- marginBottom = parseInt(L.DomUtil.getStyle(this._container, 'marginBottom'), 10) || 0,
41
+ const map = this._map,
42
+ marginBottom = parseInt(getComputedStyle(this._container).marginBottom, 10) || 0,
41
43
  containerHeight = this._container.offsetHeight + marginBottom,
42
44
  containerWidth = this._containerWidth,
43
45
  layerPos = new L.Point(this._containerLeft, -containerHeight - this._containerBottom);
@@ -46,12 +48,12 @@ L.Popup.include({
46
48
 
47
49
  /** @TODO use popupProto._adjustPan */
48
50
  // var containerPos = map.layerPointToContainerPoint(layerPos);
49
- var containerPos = layerPos._add(this._map._getMapPanePos()),
50
- padding = L.point(this.options.autoPanPadding),
51
- paddingTL = L.point(this.options.autoPanPaddingTopLeft || padding),
52
- paddingBR = L.point(this.options.autoPanPaddingBottomRight || padding),
53
- size = map.getSize(),
54
- dx = 0,
51
+ const containerPos = layerPos._add(this._map._getMapPanePos()),
52
+ padding = toPoint(this.options.autoPanPadding || [0, 0]),
53
+ paddingTL = toPoint(this.options.autoPanPaddingTopLeft || padding),
54
+ paddingBR = toPoint(this.options.autoPanPaddingBottomRight || padding),
55
+ size = map.getSize();
56
+ let dx = 0,
55
57
  dy = 0;
56
58
 
57
59
  if (containerPos.x + containerWidth + paddingBR.x > size.x) { // right
@@ -4,25 +4,25 @@
4
4
  * @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/layer/Tooltip.js
5
5
  */
6
6
 
7
- const tooltipProto = L.extend({}, L.Tooltip.prototype);
7
+ const tooltipProto = Object.defineProperties({}, Object.getOwnPropertyDescriptors(L.Tooltip.prototype));
8
8
 
9
9
  L.Tooltip.include({
10
10
 
11
- _animateZoom: function(e) {
11
+ _animateZoom(e) {
12
12
  if (!this._map._rotate) {
13
13
  return tooltipProto._animateZoom.apply(this, arguments);
14
14
  }
15
- var pos = this._map._latLngToNewLayerPoint(this._latlng, e.zoom, e.center);
15
+ let pos = this._map._latLngToNewLayerPoint(this._latlng, e.zoom, e.center);
16
16
 
17
17
  pos = this._map.rotatedPointToMapPanePoint(pos);
18
18
  this._setPosition(pos);
19
19
  },
20
20
 
21
- _updatePosition: function() {
21
+ _updatePosition() {
22
22
  if (!this._map._rotate) {
23
23
  return tooltipProto._updatePosition.apply(this, arguments);
24
24
  }
25
- var pos = this._map.latLngToLayerPoint(this._latlng);
25
+ let pos = this._map.latLngToLayerPoint(this._latlng);
26
26
 
27
27
  pos = this._map.rotatedPointToMapPanePoint(pos);
28
28
  this._setPosition(pos);
@@ -4,21 +4,21 @@
4
4
  * @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/layer/marker/Icon.js
5
5
  */
6
6
 
7
- const iconProto = L.extend({}, L.Icon.prototype);
7
+ const iconProto = Object.defineProperties({}, Object.getOwnPropertyDescriptors(L.Icon.prototype));
8
8
 
9
9
  L.Icon.include({
10
10
 
11
- _setIconStyles: function(img, name) {
12
- var options = this.options;
13
- var sizeOption = options[name + 'Size'];
11
+ _setIconStyles(img, name) {
12
+ const options = this.options;
13
+ let sizeOption = options[name + 'Size'];
14
14
 
15
15
  if (typeof sizeOption === 'number') {
16
16
  sizeOption = [sizeOption, sizeOption];
17
17
  }
18
18
 
19
- var size = L.point(sizeOption),
20
- anchor = L.point(name === 'shadow' && options.shadowAnchor || options.iconAnchor ||
21
- size && size.divideBy(2, true));
19
+ const size = sizeOption ? new L.Point(...(Array.isArray(sizeOption) ? sizeOption : [sizeOption.x, sizeOption.y])) : null,
20
+ anchorOption = name === 'shadow' && options.shadowAnchor || options.iconAnchor || size && size.divideBy(2, true),
21
+ anchor = anchorOption ? new L.Point(...(Array.isArray(anchorOption) ? anchorOption : [anchorOption.x, anchorOption.y])) : null;
22
22
 
23
23
  img.className = 'leaflet-marker-' + name + ' ' + (options.className || '');
24
24
 
@@ -26,7 +26,7 @@ L.Icon.include({
26
26
  img.style.marginLeft = (-anchor.x) + 'px';
27
27
  img.style.marginTop = (-anchor.y) + 'px';
28
28
  /** @TODO use iconProto._setIconStyles */
29
- img.style[L.DomUtil.TRANSFORM + "Origin"] = anchor.x + "px " + anchor.y + "px 0px";
29
+ img.style.transformOrigin = anchor.x + "px " + anchor.y + "px 0px";
30
30
  }
31
31
 
32
32
  if (size) {
@@ -7,7 +7,7 @@
7
7
  * @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/dom/Draggable.js
8
8
  */
9
9
 
10
- const markerProto = L.extend({}, L.Marker.prototype);
10
+ const markerProto = Object.defineProperties({}, Object.getOwnPropertyDescriptors(L.Marker.prototype));
11
11
 
12
12
  L.Marker.mergeOptions({
13
13
 
@@ -25,6 +25,13 @@ L.Marker.mergeOptions({
25
25
  */
26
26
  rotateWithView: false,
27
27
 
28
+ /**
29
+ * Flip a rotated marker when needed to keep it upright
30
+ *
31
+ * @type {Boolean}
32
+ */
33
+ keepUpright: false,
34
+
28
35
  /**
29
36
  * Scale of the marker icon
30
37
  *
@@ -34,23 +41,23 @@ L.Marker.mergeOptions({
34
41
 
35
42
  });
36
43
 
37
- var markerDragProto; // retrived at runtime (see below: L.Marker::_initInteraction())
44
+ let markerDragProto; // retrived at runtime (see below: L.Marker::_initInteraction())
38
45
 
39
- var MarkerDrag = {
46
+ const MarkerDrag = {
40
47
 
41
- // _onDragStart: function() {
48
+ // _onDragStart() {
42
49
  // if (!this._marker._map._rotate) {
43
50
  // return markerDragProto._onDragStart.apply(this, arguments);
44
51
  // }
45
52
  // this._draggable.updateMapBearing(this._marker._map._bearing);
46
53
  // },
47
54
 
48
- _onDrag: function(e) {
49
- var marker = this._marker,
55
+ _onDrag(e) {
56
+ const marker = this._marker,
50
57
  /** @TODO use markerDragProto._onDrag */
51
58
  rotated_marker = marker.options.rotation || marker.options.rotateWithView,
52
- shadow = marker._shadow,
53
- iconPos = L.DomUtil.getPosition(marker._icon);
59
+ shadow = marker._shadow;
60
+ let iconPos = L.DomUtil.getPosition(marker._icon);
54
61
 
55
62
  /** @TODO use markerDragProto._onDrag */
56
63
  // update shadow position
@@ -63,7 +70,7 @@ var MarkerDrag = {
63
70
  // Reverse calculation from mapPane coordinates to rotatePane coordinates
64
71
  iconPos = marker._map.mapPanePointToRotatedPoint(iconPos);
65
72
  }
66
- var latlng = marker._map.layerPointToLatLng(iconPos);
73
+ const latlng = marker._map.layerPointToLatLng(iconPos);
67
74
 
68
75
  marker._latlng = latlng;
69
76
  e.latlng = latlng;
@@ -79,7 +86,7 @@ var MarkerDrag = {
79
86
  .fire('drag', e);
80
87
  },
81
88
 
82
- _onDragEnd: function(e) {
89
+ _onDragEnd(e) {
83
90
  if (this._marker._map._rotate) {
84
91
  this._marker.update();
85
92
  }
@@ -96,12 +103,12 @@ L.Marker.include({
96
103
  *
97
104
  * @listens L.Map~rotate
98
105
  */
99
- getEvents: function() {
100
- return L.extend(markerProto.getEvents.apply(this, arguments), { rotate: this.update });
106
+ getEvents() {
107
+ return Object.assign(markerProto.getEvents.apply(this, arguments), { rotate: this.update });
101
108
  },
102
109
 
103
- _initInteraction: function() {
104
- var ret = markerProto._initInteraction.apply(this, arguments);
110
+ _initInteraction() {
111
+ const ret = markerProto._initInteraction.apply(this, arguments);
105
112
  if (this.dragging && this.dragging.enabled() && this._map && this._map._rotate) {
106
113
  // L.Handler.MarkerDrag is used internally by L.Marker to make the markers draggable
107
114
  markerDragProto = markerDragProto || Object.getPrototypeOf(this.dragging);
@@ -116,7 +123,7 @@ L.Marker.include({
116
123
  return ret;
117
124
  },
118
125
 
119
- _setPos: function(pos) {
126
+ _setPos(pos) {
120
127
 
121
128
  /** @TODO use markerProto._setPos */
122
129
  if (this._map._rotate) {
@@ -124,10 +131,17 @@ L.Marker.include({
124
131
  }
125
132
 
126
133
  /** @TODO use markerProto._setPos */
127
- var bearing = this.options.rotation || 0;
134
+ let bearing = this.options.rotation || 0;
128
135
  if (this.options.rotateWithView) {
129
136
  bearing += this._map._bearing;
130
137
  }
138
+ if (this.options.keepUpright) {
139
+ bearing = ((bearing % (2 * Math.PI)) + 2 * Math.PI) % (2 * Math.PI);
140
+ if (bearing > Math.PI / 2 && bearing < 3 * Math.PI / 2) {
141
+ bearing += Math.PI;
142
+ }
143
+ bearing %= 2 * Math.PI;
144
+ }
131
145
 
132
146
  /** @TODO use markerProto._setPos */
133
147
  if (this._icon) {
@@ -144,14 +158,14 @@ L.Marker.include({
144
158
  this._resetZIndex();
145
159
  },
146
160
 
147
- // _updateZIndex: function(offset) {
161
+ // _updateZIndex(offset) {
148
162
  // if (!this._map._rotate) {
149
163
  // return markerProto._updateZIndex.apply(this, arguments);
150
164
  // }
151
165
  // this._icon.style.zIndex = Math.round(this._zIndex + offset);
152
166
  // },
153
167
 
154
- setRotation: function(rotation) {
168
+ setRotation(rotation) {
155
169
  this.options.rotation = rotation;
156
170
  this.update();
157
171
  },