leaflet-rotate 0.4.0 → 0.5.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.
- package/README.md +73 -4
- package/dist/leaflet-rotate-src.js +836 -103
- package/dist/leaflet-rotate-src.js.map +2 -2
- package/dist/leaflet-rotate.js +1 -1
- package/dist/leaflet-rotate.js.map +3 -3
- package/misc/leaflet-heat-rotate.js +7 -0
- package/package.json +1 -1
- package/src/control/Rotate.js +78 -5
- package/src/dom/DomUtil.js +23 -12
- package/src/dom/Draggable.js +5 -0
- package/src/geo/LatLngBounds.js +5 -0
- package/src/geometry/Bounds.js +5 -0
- package/src/geometry/Point.js +17 -3
- package/src/index.js +3 -1
- package/src/layer/DivOverlay.js +34 -5
- package/src/layer/Popup.js +14 -3
- package/src/layer/Tooltip.js +16 -0
- package/src/layer/marker/Icon.js +12 -0
- package/src/layer/marker/Marker.js +86 -7
- package/src/layer/tile/GridLayer.js +18 -2
- package/src/layer/vector/Renderer.js +57 -6
- package/src/map/Map.js +338 -56
- package/src/map/handler/CompassBearing.js +27 -1
- package/src/map/handler/ContainerMutation.js +18 -1
- package/src/map/handler/ShiftKeyRotate.js +153 -13
- package/src/map/handler/TouchGestures.js +63 -7
- package/src/map/handler/TouchRotate.js +18 -1
- package/src/map/handler/TouchZoom.js +21 -1
- package/test/features/rotation.feature +30 -0
- package/test/index.html +2 -1
- package/test/steps/bearing.steps.js +342 -0
- package/test/support/hooks.js +4 -16
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* For Leaflet.heat (https://github.com/Leaflet/Leaflet.heat) or the heatmap.js
|
|
3
|
+
* Leaflet plugin (https://github.com/pa7/heatmap.js/tree/master/plugins/leaflet-heatmap),
|
|
4
|
+
* load this file after the heatmap plugin. It adapts heat redraw coordinates to
|
|
5
|
+
* the rotated pane.
|
|
6
|
+
*/
|
|
7
|
+
|
|
1
8
|
if (!L.HeatLayer && !globalThis.HeatmapOverlay) {
|
|
2
9
|
throw new Error('Load Leaflet.heat or heatmap.js Leaflet plugin before this adapter.');
|
|
3
10
|
}
|
package/package.json
CHANGED
package/src/control/Rotate.js
CHANGED
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Leaflet control for changing map rotation and selecting a rotation mode.
|
|
3
|
+
* Its modes are:
|
|
3
4
|
*
|
|
4
|
-
* - Locked
|
|
5
|
-
* -
|
|
6
|
-
* -
|
|
5
|
+
* - Locked: rotation gestures are disabled.
|
|
6
|
+
* - Touch: two-finger rotation is enabled.
|
|
7
|
+
* - Compass: bearing follows device orientation when supported and permitted.
|
|
7
8
|
*
|
|
8
|
-
* @
|
|
9
|
+
* @class L.Control.Rotate
|
|
10
|
+
*
|
|
11
|
+
* @extends L.Control
|
|
12
|
+
*
|
|
13
|
+
* @property {string} [position='topleft'] Leaflet control position.
|
|
14
|
+
* @property {boolean} [closeOnZeroBearing=true] Hide the control when bearing is zero.
|
|
15
|
+
*
|
|
16
|
+
* @since leaflet-rotate (v0.1.0)
|
|
9
17
|
*/
|
|
10
18
|
|
|
11
19
|
L.Control.Rotate = L.Control.extend({
|
|
@@ -15,6 +23,15 @@ L.Control.Rotate = L.Control.extend({
|
|
|
15
23
|
closeOnZeroBearing: true
|
|
16
24
|
},
|
|
17
25
|
|
|
26
|
+
/**
|
|
27
|
+
* Create the control element and subscribe to map rotation.
|
|
28
|
+
*
|
|
29
|
+
* @param {L.Map} map
|
|
30
|
+
*
|
|
31
|
+
* @returns {HTMLElement} Control container.
|
|
32
|
+
*
|
|
33
|
+
* @since leaflet-rotate (v0.1.0)
|
|
34
|
+
*/
|
|
18
35
|
onAdd(map) {
|
|
19
36
|
const container = this._container = L.DomUtil.create('div', 'leaflet-control-rotate leaflet-bar');
|
|
20
37
|
|
|
@@ -58,10 +75,24 @@ L.Control.Rotate = L.Control.extend({
|
|
|
58
75
|
return container;
|
|
59
76
|
},
|
|
60
77
|
|
|
78
|
+
/**
|
|
79
|
+
* Remove the map event listener when the control is detached.
|
|
80
|
+
*
|
|
81
|
+
* @param {L.Map} map
|
|
82
|
+
*
|
|
83
|
+
* @since leaflet-rotate (v0.1.0)
|
|
84
|
+
*/
|
|
61
85
|
onRemove(map) {
|
|
62
86
|
map.off('rotate', this._restyle, this);
|
|
63
87
|
},
|
|
64
88
|
|
|
89
|
+
/**
|
|
90
|
+
* Begin dragging the control's bearing indicator.
|
|
91
|
+
*
|
|
92
|
+
* @param {MouseEvent} e Mouse-down event.
|
|
93
|
+
*
|
|
94
|
+
* @since leaflet-rotate (v0.1.0)
|
|
95
|
+
*/
|
|
65
96
|
_handleMouseDown(e) {
|
|
66
97
|
L.DomEvent.stop(e);
|
|
67
98
|
this.dragging = true;
|
|
@@ -72,6 +103,13 @@ L.Control.Rotate = L.Control.extend({
|
|
|
72
103
|
.on(document, 'mouseup', this._handleMouseUp, this);
|
|
73
104
|
},
|
|
74
105
|
|
|
106
|
+
/**
|
|
107
|
+
* End bearing-indicator dragging and remove document listeners.
|
|
108
|
+
*
|
|
109
|
+
* @param {MouseEvent} e Mouse-up event.
|
|
110
|
+
*
|
|
111
|
+
* @since leaflet-rotate (v0.1.0)
|
|
112
|
+
*/
|
|
75
113
|
_handleMouseUp(e) {
|
|
76
114
|
L.DomEvent.stop(e);
|
|
77
115
|
this.dragging = false;
|
|
@@ -81,12 +119,27 @@ L.Control.Rotate = L.Control.extend({
|
|
|
81
119
|
.off(document, 'mouseup', this._handleMouseUp, this);
|
|
82
120
|
},
|
|
83
121
|
|
|
122
|
+
/**
|
|
123
|
+
* Set bearing from the horizontal drag distance.
|
|
124
|
+
*
|
|
125
|
+
* @param {MouseEvent} e Mouse-move event.
|
|
126
|
+
*
|
|
127
|
+
* @since leaflet-rotate (v0.1.0)
|
|
128
|
+
*/
|
|
84
129
|
_handleMouseDrag(e) {
|
|
85
130
|
if (!this.dragging) { return; }
|
|
86
131
|
const deltaX = e.clientX - this.dragstartX;
|
|
87
132
|
this._map.setBearing(deltaX);
|
|
88
133
|
},
|
|
89
134
|
|
|
135
|
+
/**
|
|
136
|
+
* Cycle through touch, compass, and locked rotation modes.
|
|
137
|
+
* Compass mode may require permission from the browser.
|
|
138
|
+
*
|
|
139
|
+
* @param {Event} ev Control click event.
|
|
140
|
+
*
|
|
141
|
+
* @since leaflet-rotate (v0.1.0)
|
|
142
|
+
*/
|
|
90
143
|
_cycleState(ev) {
|
|
91
144
|
if (!this._map) {
|
|
92
145
|
return;
|
|
@@ -120,6 +173,13 @@ L.Control.Rotate = L.Control.extend({
|
|
|
120
173
|
this._restyle();
|
|
121
174
|
},
|
|
122
175
|
|
|
176
|
+
/**
|
|
177
|
+
* Update the control icon and visibility to match the current mode.
|
|
178
|
+
*
|
|
179
|
+
* @listens L.Map#rotate
|
|
180
|
+
*
|
|
181
|
+
* @since leaflet-rotate (v0.1.0)
|
|
182
|
+
*/
|
|
123
183
|
_restyle() {
|
|
124
184
|
if (!this._map.options.rotate) {
|
|
125
185
|
this._link.classList.add('leaflet-disabled');
|
|
@@ -160,9 +220,22 @@ if (L.control) {
|
|
|
160
220
|
}
|
|
161
221
|
|
|
162
222
|
L.Map.mergeOptions({
|
|
223
|
+
/**
|
|
224
|
+
* Add the rotation control automatically. Set to `false` to disable,
|
|
225
|
+
* or pass an options object to configure the control.
|
|
226
|
+
*
|
|
227
|
+
* @type {boolean|Object}
|
|
228
|
+
*
|
|
229
|
+
* @since leaflet-rotate (v0.1.0)
|
|
230
|
+
*/
|
|
163
231
|
rotateControl: true,
|
|
164
232
|
});
|
|
165
233
|
|
|
234
|
+
/**
|
|
235
|
+
* Add the configured rotation control to each newly initialized map.
|
|
236
|
+
*
|
|
237
|
+
* @since leaflet-rotate (v0.1.0)
|
|
238
|
+
*/
|
|
166
239
|
L.Map.addInitHook(function() {
|
|
167
240
|
if (this.options.rotateControl) {
|
|
168
241
|
const options = typeof this.options.rotateControl === 'object' ? this.options.rotateControl : {};
|
package/src/dom/DomUtil.js
CHANGED
|
@@ -11,11 +11,15 @@ Object.assign(L.DomUtil, {
|
|
|
11
11
|
* Resets the 3D CSS transform of `el` so it is translated by `offset` pixels,
|
|
12
12
|
* optionally scaled by `scale`, and rotated around `pivot` when `bearing` is set.
|
|
13
13
|
*
|
|
14
|
-
* @param {HTMLElement} el
|
|
15
|
-
* @param {L.Point} offset
|
|
16
|
-
* @param {
|
|
17
|
-
* @param {
|
|
18
|
-
* @param {L.Point} pivot
|
|
14
|
+
* @param {HTMLElement} el Element to transform.
|
|
15
|
+
* @param {L.Point} [offset] Translation in pixels; defaults to the origin.
|
|
16
|
+
* @param {number} [scale] Optional scale factor.
|
|
17
|
+
* @param {number} [bearing] Optional rotation in radians.
|
|
18
|
+
* @param {L.Point} [pivot] Point in pixels around which to rotate.
|
|
19
|
+
*
|
|
20
|
+
* @returns {void}
|
|
21
|
+
*
|
|
22
|
+
* @since leaflet-rotate (v0.1.0)
|
|
19
23
|
*/
|
|
20
24
|
setTransform(el, offset, scale, bearing, pivot) {
|
|
21
25
|
let pos = offset || new L.Point(0, 0);
|
|
@@ -35,11 +39,15 @@ Object.assign(L.DomUtil, {
|
|
|
35
39
|
* Sets the position of `el` to `point`, using CSS transforms or top/left positioning
|
|
36
40
|
* depending on browser support, and optionally rotating it around `pivot`.
|
|
37
41
|
*
|
|
38
|
-
* @param {HTMLElement} el
|
|
39
|
-
* @param {L.Point} point
|
|
40
|
-
* @param {
|
|
41
|
-
* @param {L.Point} pivot
|
|
42
|
-
* @param {
|
|
42
|
+
* @param {HTMLElement} el Element to position.
|
|
43
|
+
* @param {L.Point} point Position in pixels.
|
|
44
|
+
* @param {number} [bearing] Rotation in radians; zero or omitted uses Leaflet positioning.
|
|
45
|
+
* @param {L.Point} [pivot] Point in pixels around which to rotate.
|
|
46
|
+
* @param {number} [scale] Optional scale factor.
|
|
47
|
+
*
|
|
48
|
+
* @returns {void}
|
|
49
|
+
*
|
|
50
|
+
* @since leaflet-rotate (v0.1.0)
|
|
43
51
|
*/
|
|
44
52
|
setPosition(el, point, bearing, pivot, scale) {
|
|
45
53
|
if (!bearing) {
|
|
@@ -53,8 +61,11 @@ Object.assign(L.DomUtil, {
|
|
|
53
61
|
/**
|
|
54
62
|
* Returns the position assigned to `el`.
|
|
55
63
|
*
|
|
56
|
-
* @param {HTMLElement} el
|
|
57
|
-
*
|
|
64
|
+
* @param {HTMLElement} el Element whose Leaflet position is requested.
|
|
65
|
+
*
|
|
66
|
+
* @returns {L.Point} Stored Leaflet position, or the position measured by Leaflet.
|
|
67
|
+
*
|
|
68
|
+
* @since leaflet-rotate (v0.1.0)
|
|
58
69
|
*/
|
|
59
70
|
getPosition(el) {
|
|
60
71
|
return el._leaflet_pos || domUtilProto.getPosition(el);
|
package/src/dom/Draggable.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
+
* This plugin does not modify the `L.Draggable` API; it adapts marker drag
|
|
3
|
+
* coordinates in `L.Marker` when rotation or pitch is enabled.
|
|
4
|
+
*
|
|
2
5
|
* @external L.Draggable
|
|
3
6
|
*
|
|
4
7
|
* @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/dom/Draggable.js
|
|
@@ -8,6 +11,8 @@
|
|
|
8
11
|
* A class for making DOM elements draggable (including touch support).
|
|
9
12
|
* Used internally for map and marker dragging. Only works for elements
|
|
10
13
|
* that were positioned with [`L.DomUtil.setPosition`](#domutil-setposition).
|
|
14
|
+
*
|
|
15
|
+
* @since leaflet-rotate (v0.1.0)
|
|
11
16
|
*/
|
|
12
17
|
|
|
13
18
|
L.Draggable.include({
|
package/src/geo/LatLngBounds.js
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
+
* Leaflet's `L.LatLngBounds` is not overridden by this plugin. Map methods
|
|
3
|
+
* such as `getBounds()` return standard Leaflet bounds containing the viewport.
|
|
4
|
+
*
|
|
5
|
+
* @since leaflet-rotate (v0.1.0)
|
|
6
|
+
*
|
|
2
7
|
* @external L.LatLngBounds
|
|
3
8
|
*
|
|
4
9
|
* @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/geo/LatLngBounds.js
|
package/src/geometry/Bounds.js
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
+
* Leaflet's `L.Bounds` is not overridden by this plugin. Rotation-aware
|
|
3
|
+
* pixel bounds are calculated by the map and renderer extensions.
|
|
4
|
+
*
|
|
5
|
+
* @since leaflet-rotate (v0.1.0)
|
|
6
|
+
*
|
|
2
7
|
* @external L.Bounds
|
|
3
8
|
*
|
|
4
9
|
* @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/geometry/Bounds.js
|
package/src/geometry/Point.js
CHANGED
|
@@ -12,7 +12,10 @@ Object.assign(L.Point.prototype, {
|
|
|
12
12
|
* ⎡ x' ⎤ = ⎡ cos θ -sin θ ⎤ ⎡ x ⎤
|
|
13
13
|
* ⎣ y' ⎦ ⎣ sin θ cos θ ⎦ ⎣ y ⎦
|
|
14
14
|
*
|
|
15
|
-
* @param theta
|
|
15
|
+
* @param {number} theta Rotation angle in radians, counterclockwise.
|
|
16
|
+
* @returns {L.Point} Rotated point (or this point when theta is zero).
|
|
17
|
+
*
|
|
18
|
+
* @since leaflet-rotate (v0.1.0)
|
|
16
19
|
*/
|
|
17
20
|
rotate(theta) {
|
|
18
21
|
return this.rotateFrom(theta, new L.Point(0,0))
|
|
@@ -27,10 +30,12 @@ Object.assign(L.Point.prototype, {
|
|
|
27
30
|
*
|
|
28
31
|
* same as `this.subtract(pivot).rotate(theta).add(pivot)`
|
|
29
32
|
*
|
|
30
|
-
* @param {
|
|
31
|
-
* @param {L.Point} pivot
|
|
33
|
+
* @param {number} theta Rotation angle in radians, counterclockwise.
|
|
34
|
+
* @param {L.Point} pivot Point to rotate around.
|
|
32
35
|
*
|
|
33
36
|
* @returns {L.Point}
|
|
37
|
+
*
|
|
38
|
+
* @since leaflet-rotate (v0.1.0)
|
|
34
39
|
*/
|
|
35
40
|
rotateFrom(theta, pivot) {
|
|
36
41
|
if (!theta) { return this; }
|
|
@@ -49,6 +54,15 @@ Object.assign(L.Point.prototype, {
|
|
|
49
54
|
|
|
50
55
|
});
|
|
51
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Convert an array or point-like object to an `L.Point`.
|
|
59
|
+
*
|
|
60
|
+
* @param {L.Point|number[]|{x:number,y:number}|null} point Coordinate to convert.
|
|
61
|
+
*
|
|
62
|
+
* @returns {L.Point|null} Existing point, converted point, or `null` for a null input.
|
|
63
|
+
*
|
|
64
|
+
* @since leaflet-rotate (v0.1.0)
|
|
65
|
+
*/
|
|
52
66
|
export function toPoint(point) {
|
|
53
67
|
if (point == null || point instanceof L.Point) {
|
|
54
68
|
return point;
|
package/src/index.js
CHANGED
package/src/layer/DivOverlay.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
+
* Keeps popup and tooltip screen positions aligned with rotated and pitched maps.
|
|
3
|
+
*
|
|
2
4
|
* @external L.DivOverlay
|
|
3
5
|
*
|
|
4
6
|
* @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/layer/DivOverlay.js
|
|
7
|
+
*
|
|
8
|
+
* @since leaflet-rotate (v0.1.0)
|
|
5
9
|
*/
|
|
6
10
|
|
|
7
11
|
import { toPoint } from '../geometry/Point';
|
|
@@ -11,18 +15,43 @@ const divOverlayProto = Object.defineProperties({}, Object.getOwnPropertyDescrip
|
|
|
11
15
|
L.DivOverlay.include({
|
|
12
16
|
|
|
13
17
|
/**
|
|
14
|
-
*
|
|
15
|
-
* the map is moved by calling `map.setBearing(theta)`
|
|
18
|
+
* Extend overlay event subscriptions to refresh position after map rotation and pitch.
|
|
16
19
|
*
|
|
17
20
|
* @listens L.Map~rotate
|
|
21
|
+
* @listens L.Map~pitch
|
|
22
|
+
*
|
|
23
|
+
* @returns {Object} Leaflet event map for the overlay.
|
|
24
|
+
*
|
|
25
|
+
* @since leaflet-rotate (v0.1.0)
|
|
18
26
|
*/
|
|
19
27
|
getEvents() {
|
|
20
|
-
|
|
28
|
+
const events = Object.assign(divOverlayProto.getEvents.apply(this, arguments), {
|
|
29
|
+
rotate: this._updatePosition,
|
|
30
|
+
pitch: this._updatePitchEvents,
|
|
31
|
+
});
|
|
32
|
+
if (this._map && this._map._pitch) {
|
|
33
|
+
events.move = this._updatePosition;
|
|
34
|
+
}
|
|
35
|
+
return events;
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Listen to map movement only while pitch is non-zero.
|
|
40
|
+
*
|
|
41
|
+
* @since leaflet-rotate (0.5.0)
|
|
42
|
+
*/
|
|
43
|
+
_updatePitchEvents() {
|
|
44
|
+
if (this._map._pitch) {
|
|
45
|
+
this._map.on('move', this._updatePosition, this);
|
|
46
|
+
} else {
|
|
47
|
+
this._map.off('move', this._updatePosition, this);
|
|
48
|
+
}
|
|
21
49
|
},
|
|
22
50
|
|
|
23
51
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
52
|
+
* Reposition the overlay after map movement, applying rotation/pitch-aware coordinates.
|
|
53
|
+
*
|
|
54
|
+
* @since leaflet-rotate (v0.1.0)
|
|
26
55
|
*/
|
|
27
56
|
_updatePosition() {
|
|
28
57
|
if (!this._map) { return; }
|
package/src/layer/Popup.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
+
* Preserves popup positioning and auto-pan behavior on rotated maps.
|
|
3
|
+
*
|
|
2
4
|
* @external L.Popup
|
|
3
5
|
*
|
|
4
6
|
* @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/layer/Popup.js
|
|
7
|
+
*
|
|
8
|
+
* @since leaflet-rotate (v0.1.0)
|
|
5
9
|
*/
|
|
6
10
|
|
|
7
11
|
import { toPoint } from '../geometry/Point';
|
|
@@ -11,8 +15,11 @@ const popupProto = Object.defineProperties({}, Object.getOwnPropertyDescriptors(
|
|
|
11
15
|
L.Popup.include({
|
|
12
16
|
|
|
13
17
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
18
|
+
* Update the popup position during zoom animation and transform it into map-pane coordinates.
|
|
19
|
+
*
|
|
20
|
+
* @param {Object} e Zoom animation event.
|
|
21
|
+
*
|
|
22
|
+
* @since leaflet-rotate (v0.1.0)
|
|
16
23
|
*/
|
|
17
24
|
_animateZoom(e) {
|
|
18
25
|
popupProto._animateZoom.apply(this, arguments);
|
|
@@ -24,9 +31,13 @@ L.Popup.include({
|
|
|
24
31
|
},
|
|
25
32
|
|
|
26
33
|
/**
|
|
27
|
-
*
|
|
34
|
+
* Pan the map when a popup with auto-pan enabled would extend beyond the viewport.
|
|
28
35
|
*
|
|
29
36
|
* @see https://github.com/fnicollet/Leaflet/pull/21
|
|
37
|
+
*
|
|
38
|
+
* @fires L.Map#autopanstart
|
|
39
|
+
*
|
|
40
|
+
* @since leaflet-rotate (v0.1.0)
|
|
30
41
|
*/
|
|
31
42
|
_adjustPan() {
|
|
32
43
|
if (!this.options.autoPan || (this._map._panAnim && this._map._panAnim._inProgress)) { return; }
|
package/src/layer/Tooltip.js
CHANGED
|
@@ -1,13 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
|
+
* Keeps tooltips positioned correctly when the map is rotated or pitched.
|
|
3
|
+
*
|
|
2
4
|
* @external L.Tooltip
|
|
3
5
|
*
|
|
4
6
|
* @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/layer/Tooltip.js
|
|
7
|
+
*
|
|
8
|
+
* @since leaflet-rotate (v0.1.0)
|
|
5
9
|
*/
|
|
6
10
|
|
|
7
11
|
const tooltipProto = Object.defineProperties({}, Object.getOwnPropertyDescriptors(L.Tooltip.prototype));
|
|
8
12
|
|
|
9
13
|
L.Tooltip.include({
|
|
10
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Reposition the tooltip during zoom animation using transformed map coordinates.
|
|
17
|
+
*
|
|
18
|
+
* @param {Object} e Zoom animation event.
|
|
19
|
+
*
|
|
20
|
+
* @since leaflet-rotate (v0.1.0)
|
|
21
|
+
*/
|
|
11
22
|
_animateZoom(e) {
|
|
12
23
|
if (!this._map._rotate) {
|
|
13
24
|
return tooltipProto._animateZoom.apply(this, arguments);
|
|
@@ -18,6 +29,11 @@ L.Tooltip.include({
|
|
|
18
29
|
this._setPosition(pos);
|
|
19
30
|
},
|
|
20
31
|
|
|
32
|
+
/**
|
|
33
|
+
* Recompute tooltip screen position after map movement.
|
|
34
|
+
*
|
|
35
|
+
* @since leaflet-rotate (v0.1.0)
|
|
36
|
+
*/
|
|
21
37
|
_updatePosition() {
|
|
22
38
|
if (!this._map._rotate) {
|
|
23
39
|
return tooltipProto._updatePosition.apply(this, arguments);
|
package/src/layer/marker/Icon.js
CHANGED
|
@@ -1,13 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
+
* Applies icon-anchor transform origins so marker rotation pivots around its anchor.
|
|
3
|
+
*
|
|
2
4
|
* @external L.Icon
|
|
3
5
|
*
|
|
4
6
|
* @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/layer/marker/Icon.js
|
|
7
|
+
*
|
|
8
|
+
* @since leaflet-rotate (v0.1.0)
|
|
5
9
|
*/
|
|
6
10
|
|
|
7
11
|
const iconProto = Object.defineProperties({}, Object.getOwnPropertyDescriptors(L.Icon.prototype));
|
|
8
12
|
|
|
9
13
|
L.Icon.include({
|
|
10
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Set marker icon dimensions and anchor styles, including the rotation origin.
|
|
17
|
+
*
|
|
18
|
+
* @param {HTMLImageElement} img Icon or shadow element.
|
|
19
|
+
* @param {string} name Icon style key (`icon` or `shadow`).
|
|
20
|
+
*
|
|
21
|
+
* @since leaflet-rotate (v0.1.0)
|
|
22
|
+
*/
|
|
11
23
|
_setIconStyles(img, name) {
|
|
12
24
|
const options = this.options;
|
|
13
25
|
let sizeOption = options[name + 'Size'];
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
+
* Adds rotation and pitch-aware positioning to Leaflet markers.
|
|
3
|
+
*
|
|
2
4
|
* @external L.Marker
|
|
3
5
|
* @external L.Handler.MarkerDrag
|
|
4
6
|
*
|
|
7
|
+
* @property {number} [rotation=0] Marker icon rotation in radians.
|
|
8
|
+
* @property {boolean} [rotateWithView=false] Rotate the icon with the map bearing.
|
|
9
|
+
* @property {boolean} [keepUpright=false] Flip a map-aligned icon to keep it upright.
|
|
10
|
+
* @property {number} [scale] Optional scale applied to the icon and shadow.
|
|
11
|
+
*
|
|
12
|
+
* @since leaflet-rotate (v0.1.0)
|
|
13
|
+
*
|
|
5
14
|
* @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/layer/marker/Marker.js
|
|
6
15
|
* @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/layer/marker/Marker.Drag.js
|
|
7
16
|
* @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/dom/Draggable.js
|
|
@@ -12,30 +21,41 @@ const markerProto = Object.defineProperties({}, Object.getOwnPropertyDescriptors
|
|
|
12
21
|
L.Marker.mergeOptions({
|
|
13
22
|
|
|
14
23
|
/**
|
|
15
|
-
* Rotation of
|
|
24
|
+
* Rotation of the marker icon in radians.
|
|
16
25
|
*
|
|
17
26
|
* @type {Number}
|
|
27
|
+
*
|
|
28
|
+
* @since leaflet-rotate (v0.1.0)
|
|
18
29
|
*/
|
|
19
30
|
rotation: 0,
|
|
20
31
|
|
|
21
32
|
/**
|
|
22
|
-
* Rotate
|
|
33
|
+
* Rotate the marker icon when the map bearing changes.
|
|
34
|
+
*
|
|
35
|
+
* Combine with `keepUpright: true` to keep the marker readable while
|
|
36
|
+
* preserving its line alignment.
|
|
23
37
|
*
|
|
24
38
|
* @type {Boolean}
|
|
39
|
+
*
|
|
40
|
+
* @since leaflet-rotate (v0.1.0)
|
|
25
41
|
*/
|
|
26
42
|
rotateWithView: false,
|
|
27
43
|
|
|
28
44
|
/**
|
|
29
|
-
* Flip
|
|
45
|
+
* Flip the icon when needed to keep it upright while map-aligned.
|
|
30
46
|
*
|
|
31
47
|
* @type {Boolean}
|
|
48
|
+
*
|
|
49
|
+
* @since leaflet-rotate (v0.1.0)
|
|
32
50
|
*/
|
|
33
51
|
keepUpright: false,
|
|
34
52
|
|
|
35
53
|
/**
|
|
36
|
-
*
|
|
54
|
+
* Optional scale of the marker icon and shadow.
|
|
37
55
|
*
|
|
38
56
|
* @type {Number}
|
|
57
|
+
*
|
|
58
|
+
* @since leaflet-rotate (v0.1.0)
|
|
39
59
|
*/
|
|
40
60
|
scale: undefined,
|
|
41
61
|
|
|
@@ -52,6 +72,13 @@ const MarkerDrag = {
|
|
|
52
72
|
// this._draggable.updateMapBearing(this._marker._map._bearing);
|
|
53
73
|
// },
|
|
54
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Update a dragged marker's geographic position from its transformed icon position.
|
|
77
|
+
*
|
|
78
|
+
* @param {Object} e Marker drag event with `latlng` and `oldLatLng` fields.
|
|
79
|
+
*
|
|
80
|
+
* @since leaflet-rotate (v0.1.0)
|
|
81
|
+
*/
|
|
55
82
|
_onDrag(e) {
|
|
56
83
|
const marker = this._marker,
|
|
57
84
|
/** @TODO use markerDragProto._onDrag */
|
|
@@ -86,6 +113,13 @@ const MarkerDrag = {
|
|
|
86
113
|
.fire('drag', e);
|
|
87
114
|
},
|
|
88
115
|
|
|
116
|
+
/**
|
|
117
|
+
* Reposition the marker after a drag ends, then run Leaflet's drag-end logic.
|
|
118
|
+
*
|
|
119
|
+
* @param {Object} e Marker drag-end event.
|
|
120
|
+
*
|
|
121
|
+
* @since leaflet-rotate (v0.1.0)
|
|
122
|
+
*/
|
|
89
123
|
_onDragEnd(e) {
|
|
90
124
|
if (this._marker._map._rotate) {
|
|
91
125
|
this._marker.update();
|
|
@@ -98,15 +132,44 @@ const MarkerDrag = {
|
|
|
98
132
|
L.Marker.include({
|
|
99
133
|
|
|
100
134
|
/**
|
|
101
|
-
*
|
|
102
|
-
* is moved by calling `map.setBearing(theta)`
|
|
135
|
+
* Extend marker event subscriptions to reposition its icon after bearing or pitch changes.
|
|
103
136
|
*
|
|
104
137
|
* @listens L.Map~rotate
|
|
138
|
+
* @listens L.Map~pitch
|
|
139
|
+
*
|
|
140
|
+
* @returns {Object} Leaflet event map for the marker.
|
|
141
|
+
*
|
|
142
|
+
* @since leaflet-rotate (v0.1.0)
|
|
105
143
|
*/
|
|
106
144
|
getEvents() {
|
|
107
|
-
|
|
145
|
+
const events = Object.assign(markerProto.getEvents.apply(this, arguments), {
|
|
146
|
+
rotate: this.update,
|
|
147
|
+
pitch: this._updatePitchEvents,
|
|
148
|
+
});
|
|
149
|
+
if (this._map && this._map._pitch) {
|
|
150
|
+
events.move = this.update;
|
|
151
|
+
}
|
|
152
|
+
return events;
|
|
108
153
|
},
|
|
109
154
|
|
|
155
|
+
/**
|
|
156
|
+
* Subscribe to map movement while pitch is active to keep the icon aligned.
|
|
157
|
+
*
|
|
158
|
+
* @since leaflet-rotate (0.5.0)
|
|
159
|
+
*/
|
|
160
|
+
_updatePitchEvents() {
|
|
161
|
+
if (this._map._pitch) {
|
|
162
|
+
this._map.on('move', this.update, this);
|
|
163
|
+
} else {
|
|
164
|
+
this._map.off('move', this.update, this);
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Install rotation-aware drag callbacks when marker dragging is enabled.
|
|
170
|
+
*
|
|
171
|
+
* @since leaflet-rotate (v0.1.0)
|
|
172
|
+
*/
|
|
110
173
|
_initInteraction() {
|
|
111
174
|
const ret = markerProto._initInteraction.apply(this, arguments);
|
|
112
175
|
if (this.dragging && this.dragging.enabled() && this._map && this._map._rotate) {
|
|
@@ -123,6 +186,13 @@ L.Marker.include({
|
|
|
123
186
|
return ret;
|
|
124
187
|
},
|
|
125
188
|
|
|
189
|
+
/**
|
|
190
|
+
* Position and rotate the marker icon and shadow in map-pane coordinates.
|
|
191
|
+
*
|
|
192
|
+
* @param {L.Point} pos Marker anchor in layer-point coordinates.
|
|
193
|
+
*
|
|
194
|
+
* @since leaflet-rotate (v0.1.0)
|
|
195
|
+
*/
|
|
126
196
|
_setPos(pos) {
|
|
127
197
|
|
|
128
198
|
/** @TODO use markerProto._setPos */
|
|
@@ -165,6 +235,15 @@ L.Marker.include({
|
|
|
165
235
|
// this._icon.style.zIndex = Math.round(this._zIndex + offset);
|
|
166
236
|
// },
|
|
167
237
|
|
|
238
|
+
/**
|
|
239
|
+
* Set the marker icon's rotation and redraw it.
|
|
240
|
+
*
|
|
241
|
+
* @param {number} rotation Angle in radians.
|
|
242
|
+
*
|
|
243
|
+
* @returns {void}
|
|
244
|
+
*
|
|
245
|
+
* @since leaflet-rotate (v0.1.0)
|
|
246
|
+
*/
|
|
168
247
|
setRotation(rotation) {
|
|
169
248
|
this.options.rotation = rotation;
|
|
170
249
|
this.update();
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
+
* Updates tile coverage for rotated map bounds.
|
|
3
|
+
*
|
|
2
4
|
* @external L.GridLayer
|
|
3
5
|
*
|
|
4
6
|
* @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/layer/tile/GridLayer.js
|
|
7
|
+
*
|
|
8
|
+
* @since leaflet-rotate (v0.1.0)
|
|
5
9
|
*/
|
|
6
10
|
|
|
7
11
|
const gridLayerProto = Object.defineProperties({}, Object.getOwnPropertyDescriptors(L.GridLayer.prototype));
|
|
@@ -9,10 +13,13 @@ const gridLayerProto = Object.defineProperties({}, Object.getOwnPropertyDescript
|
|
|
9
13
|
L.GridLayer.include({
|
|
10
14
|
|
|
11
15
|
/**
|
|
12
|
-
*
|
|
13
|
-
* moved by just calling `map.setBearing(theta)`
|
|
16
|
+
* Add a throttled tile refresh after map bearing changes.
|
|
14
17
|
*
|
|
15
18
|
* @listens L.Map~rotate
|
|
19
|
+
*
|
|
20
|
+
* @returns {Object} Leaflet event map for the grid layer.
|
|
21
|
+
*
|
|
22
|
+
* @since leaflet-rotate (v0.1.0)
|
|
16
23
|
*/
|
|
17
24
|
getEvents() {
|
|
18
25
|
const events = gridLayerProto.getEvents.apply(this, arguments);
|
|
@@ -25,6 +32,15 @@ L.GridLayer.include({
|
|
|
25
32
|
return events;
|
|
26
33
|
},
|
|
27
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Return tile pixel bounds that cover the rotated viewport.
|
|
37
|
+
*
|
|
38
|
+
* @param {L.LatLng} center View center used to calculate bounds.
|
|
39
|
+
*
|
|
40
|
+
* @returns {L.Bounds} Pixel bounds covered by the layer's tiles.
|
|
41
|
+
*
|
|
42
|
+
* @since leaflet-rotate (v0.1.0)
|
|
43
|
+
*/
|
|
28
44
|
_getTiledPixelBounds(center) {
|
|
29
45
|
if (!this._map._rotate) {
|
|
30
46
|
return gridLayerProto._getTiledPixelBounds.apply(this, arguments);
|