leaflet-rotate 0.1.4 → 0.2.1
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 +2 -2
- package/build/rollup.config.js +4 -4
- package/dist/leaflet-rotate-src.js +744 -329
- package/dist/leaflet-rotate-src.js.map +1 -1
- package/dist/leaflet-rotate.js +1760 -1
- package/dist/leaflet-rotate.js.map +1 -1
- package/lib/debug.js +253 -21
- package/lib/debug.min.js +1 -9
- package/package.json +10 -7
- package/src/control/Rotate.js +10 -7
- package/src/dom/DomUtil.js +8 -5
- package/src/dom/Draggable.js +8 -5
- package/src/geometry/Point.js +22 -18
- package/src/index.js +5 -3
- package/src/layer/DivOverlay.js +14 -22
- package/src/layer/Popup.js +30 -10
- package/src/layer/Tooltip.js +10 -7
- package/src/layer/marker/Icon.js +5 -2
- package/src/layer/marker/Marker.js +52 -43
- package/src/layer/tile/GridLayer.js +7 -16
- package/src/layer/vector/Canvas.js +18 -15
- package/src/layer/vector/Renderer.js +23 -32
- package/src/layer/vector/SVG.js +10 -7
- package/src/map/Map.js +462 -96
- package/src/map/handler/CompassBearing.js +7 -11
- package/src/map/handler/ContainerMutation.js +12 -8
- package/src/map/handler/ShiftKeyRotate.js +5 -2
- package/src/map/handler/TouchGestures.js +16 -11
- package/src/map/handler/TouchRotate.js +4 -2
- package/src/map/handler/TouchZoom.js +16 -4
- package/test/index.html +30 -6
- package/build/rollup.config.min.js +0 -2
- package/src/map/handler/ShiftKeyRotate.min.js +0 -1
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
(function (factory) {
|
|
2
2
|
typeof define === 'function' && define.amd ? define(factory) :
|
|
3
3
|
factory();
|
|
4
|
-
}((function () { 'use strict';
|
|
4
|
+
})((function () { 'use strict';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* L.DomUtil
|
|
7
|
+
* @external L.DomUtil
|
|
8
|
+
*
|
|
9
|
+
* @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/dom/DomUtil.js
|
|
8
10
|
*/
|
|
11
|
+
|
|
9
12
|
const domUtilProto = L.extend({}, L.DomUtil);
|
|
10
13
|
|
|
11
14
|
L.extend(L.DomUtil, {
|
|
@@ -15,7 +18,7 @@
|
|
|
15
18
|
|
|
16
19
|
if (!bearing) {
|
|
17
20
|
offset = pos._round();
|
|
18
|
-
return domUtilProto.setTransform.
|
|
21
|
+
return domUtilProto.setTransform.apply(this, arguments);
|
|
19
22
|
}
|
|
20
23
|
|
|
21
24
|
pos = pos.rotateFrom(bearing, pivot);
|
|
@@ -26,9 +29,9 @@
|
|
|
26
29
|
' rotate(' + bearing + 'rad)';
|
|
27
30
|
},
|
|
28
31
|
|
|
29
|
-
setPosition: function(el, point, bearing, pivot) { // (HTMLElement, Point[, Boolean])
|
|
32
|
+
setPosition: function(el, point, bearing, pivot, scale) { // (HTMLElement, Point[, Boolean])
|
|
30
33
|
if (!bearing) {
|
|
31
|
-
return domUtilProto.setPosition.
|
|
34
|
+
return domUtilProto.setPosition.apply(this, arguments);
|
|
32
35
|
}
|
|
33
36
|
|
|
34
37
|
/*eslint-disable */
|
|
@@ -36,7 +39,7 @@
|
|
|
36
39
|
/*eslint-enable */
|
|
37
40
|
|
|
38
41
|
if (L.Browser.any3d) {
|
|
39
|
-
L.DomUtil.setTransform(el, point,
|
|
42
|
+
L.DomUtil.setTransform(el, point, scale, bearing, pivot);
|
|
40
43
|
} else {
|
|
41
44
|
el.style.left = point.x + 'px';
|
|
42
45
|
el.style.top = point.y + 'px';
|
|
@@ -50,41 +53,48 @@
|
|
|
50
53
|
});
|
|
51
54
|
|
|
52
55
|
/**
|
|
53
|
-
* L.Draggable
|
|
56
|
+
* @external L.Draggable
|
|
57
|
+
*
|
|
58
|
+
* @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/dom/Draggable.js
|
|
54
59
|
*/
|
|
60
|
+
|
|
55
61
|
L.Draggable.include({
|
|
56
62
|
|
|
57
|
-
updateMapBearing: function(mapBearing) {
|
|
58
|
-
|
|
59
|
-
},
|
|
63
|
+
// updateMapBearing: function(mapBearing) {
|
|
64
|
+
// this._mapBearing = mapBearing;
|
|
65
|
+
// },
|
|
60
66
|
|
|
61
67
|
});
|
|
62
68
|
|
|
63
69
|
/**
|
|
64
|
-
* L.Point
|
|
70
|
+
* @external L.Point
|
|
71
|
+
*
|
|
72
|
+
* @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/geometry/Point.js
|
|
65
73
|
*/
|
|
74
|
+
|
|
66
75
|
L.extend(L.Point.prototype, {
|
|
67
76
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
77
|
+
/**
|
|
78
|
+
* Rotate around (0,0) by applying the 2D rotation matrix:
|
|
79
|
+
*
|
|
80
|
+
* ⎡ x' ⎤ = ⎡ cos θ -sin θ ⎤ ⎡ x ⎤
|
|
81
|
+
* ⎣ y' ⎦ ⎣ sin θ cos θ ⎦ ⎣ y ⎦
|
|
82
|
+
*
|
|
83
|
+
* @param theta must be given in radians.
|
|
84
|
+
*/
|
|
72
85
|
rotate: function(theta) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
// 2. rotate around (0, 0)
|
|
86
|
-
// 3. add (pivot.x, pivot.y) back
|
|
87
|
-
// same as `this.subtract(pivot).rotate(theta).add(pivot)`
|
|
86
|
+
return this.rotateFrom(theta, new L.Point(0,0))
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Rotate around (pivot.x, pivot.y) by:
|
|
91
|
+
*
|
|
92
|
+
* 1. subtract (pivot.x, pivot.y)
|
|
93
|
+
* 2. rotate around (0, 0)
|
|
94
|
+
* 3. add (pivot.x, pivot.y) back
|
|
95
|
+
*
|
|
96
|
+
* same as `this.subtract(pivot).rotate(theta).add(pivot)`
|
|
97
|
+
*/
|
|
88
98
|
rotateFrom: function(theta, pivot) {
|
|
89
99
|
if (!theta) { return this; }
|
|
90
100
|
var sinTheta = Math.sin(theta);
|
|
@@ -103,65 +113,73 @@
|
|
|
103
113
|
});
|
|
104
114
|
|
|
105
115
|
/**
|
|
106
|
-
* L.DivOverlay
|
|
116
|
+
* @external L.DivOverlay
|
|
117
|
+
*
|
|
118
|
+
* @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/layer/DivOverlay.js
|
|
107
119
|
*/
|
|
120
|
+
|
|
108
121
|
const divOverlayProto = L.extend({}, L.DivOverlay.prototype);
|
|
109
122
|
|
|
110
123
|
L.DivOverlay.include({
|
|
111
124
|
|
|
112
125
|
getEvents: function() {
|
|
113
|
-
return L.extend(divOverlayProto.getEvents.
|
|
126
|
+
return L.extend(divOverlayProto.getEvents.apply(this, arguments), { rotate: this._updatePosition });
|
|
114
127
|
},
|
|
115
128
|
|
|
116
129
|
_updatePosition: function() {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
pos = this._map.rotatedPointToMapPanePoint(pos);
|
|
127
|
-
}
|
|
128
|
-
L.DomUtil.setPosition(this._container, pos.add(anchor));
|
|
129
|
-
} else {
|
|
130
|
-
offset = offset.add(pos).add(anchor);
|
|
130
|
+
// 0. update anchor (leaflet v1.9.3)
|
|
131
|
+
divOverlayProto._updatePosition.apply(this, arguments);
|
|
132
|
+
// 1. subtract anchor
|
|
133
|
+
// 2. rotate element
|
|
134
|
+
// 3. restore anchor
|
|
135
|
+
if (this._map && this._map._rotate && this._zoomAnimated) {
|
|
136
|
+
var anchor = this._getAnchor();
|
|
137
|
+
var pos = L.DomUtil.getPosition(this._container).subtract(anchor);
|
|
138
|
+
L.DomUtil.setPosition(this._container, this._map.rotatedPointToMapPanePoint(pos).add(anchor));
|
|
131
139
|
}
|
|
132
140
|
|
|
133
|
-
var bottom = this._containerBottom = -offset.y,
|
|
134
|
-
left = this._containerLeft = -Math.round(this._containerWidth / 2) + offset.x;
|
|
135
|
-
|
|
136
|
-
// bottom position the popup in case the height of the popup changes (images loading etc)
|
|
137
|
-
this._container.style.bottom = bottom + 'px';
|
|
138
|
-
this._container.style.left = left + 'px';
|
|
139
141
|
},
|
|
140
142
|
|
|
141
143
|
});
|
|
142
144
|
|
|
143
145
|
/**
|
|
144
|
-
* L.Popup
|
|
146
|
+
* @external L.Popup
|
|
147
|
+
*
|
|
148
|
+
* @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/layer/Popup.js
|
|
145
149
|
*/
|
|
150
|
+
|
|
146
151
|
const popupProto = L.extend({}, L.Popup.prototype);
|
|
147
152
|
|
|
148
153
|
L.Popup.include({
|
|
149
154
|
|
|
150
155
|
_animateZoom: function(e) {
|
|
151
|
-
|
|
152
|
-
|
|
156
|
+
// 0. update anchor (leaflet v1.9.3)
|
|
157
|
+
popupProto._animateZoom.apply(this, arguments);
|
|
158
|
+
// 1. subtract anchor
|
|
159
|
+
// 2. rotate element
|
|
160
|
+
// 3. restore anchor
|
|
161
|
+
if (this._map && this._map._rotate) {
|
|
162
|
+
var anchor = this._getAnchor();
|
|
163
|
+
var pos = L.DomUtil.getPosition(this._container).subtract(anchor);
|
|
164
|
+
L.DomUtil.setPosition(this._container, this._map.rotatedPointToMapPanePoint(pos).add(anchor));
|
|
153
165
|
}
|
|
154
|
-
var pos = this._map._latLngToNewLayerPoint(this._latlng, e.zoom, e.center),
|
|
155
|
-
anchor = this._getAnchor();
|
|
156
|
-
|
|
157
|
-
pos = this._map.rotatedPointToMapPanePoint(pos);
|
|
158
|
-
|
|
159
|
-
L.DomUtil.setPosition(this._container, pos.add(anchor));
|
|
160
166
|
},
|
|
161
167
|
|
|
168
|
+
/**
|
|
169
|
+
* Hot fix for L.Popup.mergeOptions({ keepInView: true, });
|
|
170
|
+
*
|
|
171
|
+
* @see https://github.com/fnicollet/Leaflet/pull/21
|
|
172
|
+
*/
|
|
162
173
|
_adjustPan: function() {
|
|
163
174
|
if (!this.options.autoPan || (this._map._panAnim && this._map._panAnim._inProgress)) { return; }
|
|
164
175
|
|
|
176
|
+
// We can endlessly recurse if keepInView is set and the view resets.
|
|
177
|
+
// Let's guard against that by exiting early if we're responding to our own autopan.
|
|
178
|
+
if (this._autopanning) {
|
|
179
|
+
this._autopanning = false;
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
|
|
165
183
|
var map = this._map,
|
|
166
184
|
marginBottom = parseInt(L.DomUtil.getStyle(this._container, 'marginBottom'), 10) || 0,
|
|
167
185
|
containerHeight = this._container.offsetHeight + marginBottom,
|
|
@@ -171,7 +189,7 @@
|
|
|
171
189
|
layerPos._add(L.DomUtil.getPosition(this._container));
|
|
172
190
|
|
|
173
191
|
// var containerPos = map.layerPointToContainerPoint(layerPos);
|
|
174
|
-
|
|
192
|
+
/** @TODO use popupProto._adjustPan */
|
|
175
193
|
var containerPos = layerPos._add(this._map._getMapPanePos()),
|
|
176
194
|
padding = L.point(this.options.autoPanPadding),
|
|
177
195
|
paddingTL = L.point(this.options.autoPanPaddingTopLeft || padding),
|
|
@@ -198,6 +216,10 @@
|
|
|
198
216
|
// @event autopanstart: Event
|
|
199
217
|
// Fired when the map starts autopanning when opening a popup.
|
|
200
218
|
if (dx || dy) {
|
|
219
|
+
// Track that we're autopanning, as this function will be re-ran on moveend
|
|
220
|
+
if (this.options.keepInView) {
|
|
221
|
+
this._autopanning = true;
|
|
222
|
+
}
|
|
201
223
|
map
|
|
202
224
|
.fire('autopanstart')
|
|
203
225
|
.panBy([dx, dy]);
|
|
@@ -207,27 +229,30 @@
|
|
|
207
229
|
});
|
|
208
230
|
|
|
209
231
|
/**
|
|
210
|
-
* L.Tooltip
|
|
232
|
+
* @external L.Tooltip
|
|
233
|
+
*
|
|
234
|
+
* @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/layer/Tooltip.js
|
|
211
235
|
*/
|
|
236
|
+
|
|
212
237
|
const tooltipProto = L.extend({}, L.Tooltip.prototype);
|
|
213
238
|
|
|
214
239
|
L.Tooltip.include({
|
|
215
240
|
|
|
216
|
-
|
|
241
|
+
_animateZoom: function(e) {
|
|
217
242
|
if (!this._map._rotate) {
|
|
218
|
-
return tooltipProto.
|
|
243
|
+
return tooltipProto._animateZoom.apply(this, arguments);
|
|
219
244
|
}
|
|
220
|
-
var pos = this._map.
|
|
245
|
+
var pos = this._map._latLngToNewLayerPoint(this._latlng, e.zoom, e.center);
|
|
221
246
|
|
|
222
247
|
pos = this._map.rotatedPointToMapPanePoint(pos);
|
|
223
248
|
this._setPosition(pos);
|
|
224
249
|
},
|
|
225
250
|
|
|
226
|
-
|
|
251
|
+
_updatePosition: function() {
|
|
227
252
|
if (!this._map._rotate) {
|
|
228
|
-
return tooltipProto.
|
|
253
|
+
return tooltipProto._updatePosition.apply(this, arguments);
|
|
229
254
|
}
|
|
230
|
-
var pos = this._map.
|
|
255
|
+
var pos = this._map.latLngToLayerPoint(this._latlng);
|
|
231
256
|
|
|
232
257
|
pos = this._map.rotatedPointToMapPanePoint(pos);
|
|
233
258
|
this._setPosition(pos);
|
|
@@ -236,9 +261,12 @@
|
|
|
236
261
|
});
|
|
237
262
|
|
|
238
263
|
/**
|
|
239
|
-
* L.Icon
|
|
264
|
+
* @external L.Icon
|
|
265
|
+
*
|
|
266
|
+
* @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/layer/marker/Icon.js
|
|
240
267
|
*/
|
|
241
|
-
|
|
268
|
+
|
|
269
|
+
L.extend({}, L.Icon.prototype);
|
|
242
270
|
|
|
243
271
|
L.Icon.include({
|
|
244
272
|
|
|
@@ -259,7 +287,7 @@
|
|
|
259
287
|
if (anchor) {
|
|
260
288
|
img.style.marginLeft = (-anchor.x) + 'px';
|
|
261
289
|
img.style.marginTop = (-anchor.y) + 'px';
|
|
262
|
-
|
|
290
|
+
/** @TODO use iconProto._setIconStyles */
|
|
263
291
|
img.style[L.DomUtil.TRANSFORM + "Origin"] = anchor.x + "px " + anchor.y + "px 0px";
|
|
264
292
|
}
|
|
265
293
|
|
|
@@ -272,33 +300,55 @@
|
|
|
272
300
|
});
|
|
273
301
|
|
|
274
302
|
/**
|
|
275
|
-
* L.
|
|
303
|
+
* @external L.Marker
|
|
304
|
+
* @external L.Handler.MarkerDrag
|
|
305
|
+
*
|
|
306
|
+
* @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/layer/marker/Marker.js
|
|
276
307
|
*/
|
|
277
|
-
|
|
308
|
+
|
|
309
|
+
const markerProto = L.extend({}, L.Marker.prototype);
|
|
310
|
+
|
|
311
|
+
L.Marker.mergeOptions({
|
|
312
|
+
|
|
313
|
+
// @option rotation: Number = 0
|
|
314
|
+
// Rotation of this marker in rad
|
|
315
|
+
rotation: 0,
|
|
316
|
+
|
|
317
|
+
// @option rotateWithView: Boolean = false
|
|
318
|
+
// Rotate this marker when map rotates
|
|
319
|
+
rotateWithView: false,
|
|
320
|
+
|
|
321
|
+
// @option scale: Number = undefined
|
|
322
|
+
// Scale of the marker icon
|
|
323
|
+
scale: undefined,
|
|
324
|
+
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
var markerDragProto; // retrived at runtime (see below: L.Marker::_initInteraction())
|
|
278
328
|
|
|
279
329
|
var MarkerDrag = {
|
|
280
330
|
|
|
281
|
-
_onDragStart: function() {
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
},
|
|
331
|
+
// _onDragStart: function() {
|
|
332
|
+
// if (!this._marker._map._rotate) {
|
|
333
|
+
// return markerDragProto._onDragStart.apply(this, arguments);
|
|
334
|
+
// }
|
|
335
|
+
// this._draggable.updateMapBearing(this._marker._map._bearing);
|
|
336
|
+
// },
|
|
287
337
|
|
|
288
338
|
_onDrag: function(e) {
|
|
289
339
|
var marker = this._marker,
|
|
290
|
-
|
|
340
|
+
/** @TODO use markerDragProto._onDrag */
|
|
291
341
|
rotated_marker = marker.options.rotation || marker.options.rotateWithView,
|
|
292
342
|
shadow = marker._shadow,
|
|
293
343
|
iconPos = L.DomUtil.getPosition(marker._icon);
|
|
294
344
|
|
|
295
|
-
|
|
345
|
+
/** @TODO use markerDragProto._onDrag */
|
|
296
346
|
// update shadow position
|
|
297
347
|
if (!rotated_marker && shadow) {
|
|
298
348
|
L.DomUtil.setPosition(shadow, iconPos);
|
|
299
349
|
}
|
|
300
350
|
|
|
301
|
-
|
|
351
|
+
/** @TODO use markerDragProto._onDrag */
|
|
302
352
|
if (marker._map._rotate) {
|
|
303
353
|
// Reverse calculation from mapPane coordinates to rotatePane coordinates
|
|
304
354
|
iconPos = marker._map.mapPanePointToRotatedPoint(iconPos);
|
|
@@ -309,7 +359,7 @@
|
|
|
309
359
|
e.latlng = latlng;
|
|
310
360
|
e.oldLatLng = this._oldLatLng;
|
|
311
361
|
|
|
312
|
-
|
|
362
|
+
/** @TODO use markerDragProto._onDrag */
|
|
313
363
|
if (rotated_marker) marker.setLatLng(latlng); // use `setLatLng` to presisit rotation. low efficiency
|
|
314
364
|
else marker.fire('move', e); // `setLatLng` will trig 'move' event. we imitate here.
|
|
315
365
|
|
|
@@ -323,47 +373,32 @@
|
|
|
323
373
|
if (this._marker._map._rotate) {
|
|
324
374
|
this._marker.update();
|
|
325
375
|
}
|
|
326
|
-
markerDragProto._onDragEnd.
|
|
376
|
+
markerDragProto._onDragEnd.apply(this, arguments);
|
|
327
377
|
},
|
|
328
378
|
|
|
329
379
|
};
|
|
330
380
|
|
|
331
|
-
/**
|
|
332
|
-
* L.Marker
|
|
333
|
-
*/
|
|
334
|
-
const markerProto = L.extend({}, L.Marker.prototype);
|
|
335
|
-
|
|
336
|
-
L.Marker.mergeOptions({
|
|
337
|
-
|
|
338
|
-
// @option rotation: Number = 0
|
|
339
|
-
// Rotation of this marker in rad
|
|
340
|
-
rotation: 0,
|
|
341
|
-
|
|
342
|
-
// @option rotateWithView: Boolean = false
|
|
343
|
-
// Rotate this marker when map rotates
|
|
344
|
-
rotateWithView: false,
|
|
345
|
-
|
|
346
|
-
});
|
|
347
|
-
|
|
348
381
|
L.Marker.include({
|
|
349
382
|
|
|
350
383
|
getEvents: function() {
|
|
351
|
-
return L.extend(markerProto.getEvents.
|
|
384
|
+
return L.extend(markerProto.getEvents.apply(this, arguments), { rotate: this.update });
|
|
352
385
|
},
|
|
353
386
|
|
|
354
387
|
onAdd: function(map) {
|
|
355
|
-
markerProto.onAdd.
|
|
388
|
+
markerProto.onAdd.apply(this, arguments);
|
|
356
389
|
map.on('rotate', this.update, this);
|
|
357
390
|
},
|
|
358
391
|
|
|
359
392
|
_initInteraction: function() {
|
|
360
|
-
var ret = markerProto._initInteraction.
|
|
393
|
+
var ret = markerProto._initInteraction.apply(this, arguments);
|
|
361
394
|
if (this.dragging && this.dragging.enabled() && this._map && this._map._rotate) {
|
|
362
395
|
// L.Handler.MarkerDrag is used internally by L.Marker to make the markers draggable
|
|
363
396
|
markerDragProto = markerDragProto || Object.getPrototypeOf(this.dragging);
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
397
|
+
Object.assign(this.dragging, {
|
|
398
|
+
// _onDragStart: MarkerDrag._onDragStart.bind(this.dragging),
|
|
399
|
+
_onDrag: MarkerDrag._onDrag.bind(this.dragging),
|
|
400
|
+
_onDragEnd: MarkerDrag._onDragEnd.bind(this.dragging),
|
|
401
|
+
});
|
|
367
402
|
this.dragging.disable();
|
|
368
403
|
this.dragging.enable();
|
|
369
404
|
}
|
|
@@ -372,23 +407,25 @@
|
|
|
372
407
|
|
|
373
408
|
_setPos: function(pos) {
|
|
374
409
|
|
|
375
|
-
|
|
410
|
+
/** @TODO use markerProto._setPos */
|
|
376
411
|
if (this._map._rotate) {
|
|
377
412
|
pos = this._map.rotatedPointToMapPanePoint(pos);
|
|
378
413
|
}
|
|
379
414
|
|
|
380
|
-
|
|
415
|
+
/** @TODO use markerProto._setPos */
|
|
381
416
|
var bearing = this.options.rotation || 0;
|
|
382
417
|
if (this.options.rotateWithView) {
|
|
383
418
|
bearing += this._map._bearing;
|
|
384
419
|
}
|
|
385
420
|
|
|
386
|
-
|
|
387
|
-
|
|
421
|
+
/** @TODO use markerProto._setPos */
|
|
422
|
+
if (this._icon) {
|
|
423
|
+
L.DomUtil.setPosition(this._icon, pos, bearing, pos, this.options.scale);
|
|
424
|
+
}
|
|
388
425
|
|
|
389
|
-
|
|
426
|
+
/** @TODO use markerProto._setPos */
|
|
390
427
|
if (this._shadow) {
|
|
391
|
-
L.DomUtil.setPosition(this._shadow, pos, bearing, pos);
|
|
428
|
+
L.DomUtil.setPosition(this._shadow, pos, bearing, pos, this.options.scale);
|
|
392
429
|
}
|
|
393
430
|
|
|
394
431
|
this._zIndex = pos.y + this.options.zIndexOffset;
|
|
@@ -398,7 +435,7 @@
|
|
|
398
435
|
|
|
399
436
|
_updateZIndex: function(offset) {
|
|
400
437
|
if (!this._map._rotate) {
|
|
401
|
-
return markerProto._updateZIndex.
|
|
438
|
+
return markerProto._updateZIndex.apply(this, arguments);
|
|
402
439
|
}
|
|
403
440
|
this._icon.style.zIndex = Math.round(this._zIndex + offset);
|
|
404
441
|
},
|
|
@@ -411,14 +448,17 @@
|
|
|
411
448
|
});
|
|
412
449
|
|
|
413
450
|
/**
|
|
414
|
-
* L.GridLayer
|
|
451
|
+
* @external L.GridLayer
|
|
452
|
+
*
|
|
453
|
+
* @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/layer/tile/GridLayer.js
|
|
415
454
|
*/
|
|
455
|
+
|
|
416
456
|
const gridLayerProto = L.extend({}, L.GridLayer.prototype);
|
|
417
457
|
|
|
418
458
|
L.GridLayer.include({
|
|
419
459
|
|
|
420
460
|
getEvents: function() {
|
|
421
|
-
var events = gridLayerProto.getEvents.
|
|
461
|
+
var events = gridLayerProto.getEvents.apply(this, arguments);
|
|
422
462
|
if (this._map._rotate && !this.options.updateWhenIdle) {
|
|
423
463
|
if (!this._onRotate) {
|
|
424
464
|
this._onRotate = L.Util.throttle(this._onMoveEnd, this.options.updateInterval, this);
|
|
@@ -430,72 +470,71 @@
|
|
|
430
470
|
|
|
431
471
|
_getTiledPixelBounds: function(center) {
|
|
432
472
|
if (!this._map._rotate) {
|
|
433
|
-
return gridLayerProto._getTiledPixelBounds.
|
|
473
|
+
return gridLayerProto._getTiledPixelBounds.apply(this, arguments);
|
|
434
474
|
}
|
|
435
475
|
|
|
436
|
-
|
|
437
|
-
mapZoom = map._animatingZoom ? Math.max(map._animateToZoom, map.getZoom()) : map.getZoom(),
|
|
438
|
-
scale = map.getZoomScale(mapZoom, this._tileZoom),
|
|
439
|
-
pixelCenter = map.project(center, this._tileZoom).floor(),
|
|
440
|
-
size = map.getSize(),
|
|
441
|
-
halfSize = new L.Bounds([
|
|
442
|
-
map.containerPointToLayerPoint([0, 0]).floor(),
|
|
443
|
-
map.containerPointToLayerPoint([size.x, 0]).floor(),
|
|
444
|
-
map.containerPointToLayerPoint([0, size.y]).floor(),
|
|
445
|
-
map.containerPointToLayerPoint([size.x, size.y]).floor()
|
|
446
|
-
]).getSize().divideBy(scale * 2);
|
|
447
|
-
|
|
448
|
-
return new L.Bounds(pixelCenter.subtract(halfSize), pixelCenter.add(halfSize));
|
|
476
|
+
return this._map._getNewPixelBounds(center, this._tileZoom);
|
|
449
477
|
},
|
|
450
478
|
|
|
451
479
|
});
|
|
452
480
|
|
|
453
481
|
/**
|
|
454
|
-
* L.Canvas
|
|
482
|
+
* @external L.Canvas
|
|
483
|
+
*
|
|
484
|
+
* @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/layer/vector/Canvas.js
|
|
455
485
|
*/
|
|
456
|
-
|
|
486
|
+
|
|
487
|
+
L.extend({}, L.Canvas.prototype);
|
|
457
488
|
|
|
458
489
|
L.Canvas.include({
|
|
459
490
|
|
|
460
|
-
onAdd: function() {
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
},
|
|
491
|
+
// onAdd: function() {
|
|
492
|
+
// canvasProto.onAdd.apply(this, arguments);
|
|
493
|
+
// // When rotating the canvas itself, it is cleared by some weird reason, so redraw.
|
|
494
|
+
// this._map.on('rotate', this._redraw, this);
|
|
495
|
+
// },
|
|
465
496
|
|
|
466
|
-
onRemove: function() {
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
},
|
|
497
|
+
// onRemove: function() {
|
|
498
|
+
// canvasProto.onRemove.apply(this, arguments);
|
|
499
|
+
// this._map.off('rotate', this._redraw, this);
|
|
500
|
+
// },
|
|
470
501
|
|
|
471
|
-
_update: function() {
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
},
|
|
502
|
+
// _update: function() {
|
|
503
|
+
// canvasProto._update.apply(this, arguments);
|
|
504
|
+
// // Tell paths to redraw themselves
|
|
505
|
+
// this.fire('update')
|
|
506
|
+
// },
|
|
476
507
|
|
|
477
508
|
});
|
|
478
509
|
|
|
479
510
|
/**
|
|
480
|
-
* L.Renderer
|
|
511
|
+
* @external L.Renderer
|
|
512
|
+
*
|
|
513
|
+
* @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/layer/vector/Renderer.js
|
|
481
514
|
*/
|
|
515
|
+
|
|
482
516
|
const rendererProto = L.extend({}, L.Renderer.prototype);
|
|
483
517
|
|
|
484
518
|
L.Renderer.include({
|
|
485
519
|
|
|
486
|
-
onAdd: function() {
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
},
|
|
520
|
+
// onAdd: function() {
|
|
521
|
+
// rendererProto.onAdd.apply(this, arguments);
|
|
522
|
+
// // this._map.on('rotate', this._update, this);
|
|
523
|
+
// },
|
|
490
524
|
|
|
491
|
-
onRemove: function() {
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
},
|
|
525
|
+
// onRemove: function() {
|
|
526
|
+
// rendererProto.onRemove.apply(this, arguments);
|
|
527
|
+
// // this._map.off('rotate', this._update, this);
|
|
528
|
+
// },
|
|
495
529
|
|
|
530
|
+
/**
|
|
531
|
+
* @TODO rechek this changes from leaflet@v1.9.3
|
|
532
|
+
*
|
|
533
|
+
* @see https://github.com/Leaflet/Leaflet/compare/v1.7.0...v1.9.3
|
|
534
|
+
*/
|
|
496
535
|
_updateTransform: function(center, zoom) {
|
|
497
536
|
if (!this._map._rotate) {
|
|
498
|
-
return rendererProto._updateTransform.
|
|
537
|
+
return rendererProto._updateTransform.apply(this, arguments);
|
|
499
538
|
}
|
|
500
539
|
var scale = this._map.getZoomScale(zoom, this._zoom),
|
|
501
540
|
offset = this._map._latLngToNewLayerPoint(this._topLeft, zoom, center);
|
|
@@ -508,29 +547,12 @@
|
|
|
508
547
|
|
|
509
548
|
_update: function() {
|
|
510
549
|
if (!this._map._rotate) {
|
|
511
|
-
return rendererProto._update.
|
|
550
|
+
return rendererProto._update.apply(this, arguments);
|
|
512
551
|
}
|
|
513
552
|
// Update pixel bounds of renderer container (for positioning/sizing/clipping later)
|
|
514
553
|
// Subclasses are responsible of firing the 'update' event.
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
size = this._map.getSize(),
|
|
518
|
-
padMin = size.multiplyBy(-p),
|
|
519
|
-
padMax = size.multiplyBy(1 + p),
|
|
520
|
-
//// TODO: Somehow refactor this out into map.something() - the code is
|
|
521
|
-
//// pretty much the same as in GridLayer.
|
|
522
|
-
clip = new L.Bounds([
|
|
523
|
-
map.containerPointToLayerPoint([padMin.x, padMin.y]).floor(),
|
|
524
|
-
map.containerPointToLayerPoint([padMin.x, padMax.y]).floor(),
|
|
525
|
-
map.containerPointToLayerPoint([padMax.x, padMin.y]).floor(),
|
|
526
|
-
map.containerPointToLayerPoint([padMax.x, padMax.y]).floor()
|
|
527
|
-
]);
|
|
528
|
-
//min = this._map.containerPointToLayerPoint(size.multiplyBy(-p)).round();
|
|
529
|
-
|
|
530
|
-
this._bounds = clip;
|
|
531
|
-
// this._topLeft = clip.min;
|
|
532
|
-
this._topLeft = this._map.layerPointToLatLng(clip.min);
|
|
533
|
-
|
|
554
|
+
this._bounds = this._map._getPaddedPixelBounds(this.options.padding);
|
|
555
|
+
this._topLeft = this._map.layerPointToLatLng(this._bounds.min);
|
|
534
556
|
this._center = this._map.getCenter();
|
|
535
557
|
this._zoom = this._map.getZoom();
|
|
536
558
|
},
|
|
@@ -538,57 +560,62 @@
|
|
|
538
560
|
});
|
|
539
561
|
|
|
540
562
|
/**
|
|
541
|
-
* L.SVG
|
|
563
|
+
* @external L.SVG
|
|
564
|
+
*
|
|
565
|
+
* @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/layer/vector/SVG.js
|
|
542
566
|
*/
|
|
543
|
-
|
|
567
|
+
|
|
568
|
+
L.extend({}, L.SVG.prototype);
|
|
544
569
|
|
|
545
570
|
L.SVG.include({
|
|
546
571
|
|
|
547
|
-
_update: function() {
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
},
|
|
572
|
+
// _update: function() {
|
|
573
|
+
// svgProto._update.apply(this, arguments);
|
|
574
|
+
// if (this._map._rotate) {
|
|
575
|
+
// this.fire('update');
|
|
576
|
+
// }
|
|
577
|
+
// },
|
|
553
578
|
|
|
554
579
|
});
|
|
555
580
|
|
|
556
581
|
/**
|
|
557
|
-
* L.Map
|
|
582
|
+
* @external L.Map
|
|
583
|
+
*
|
|
584
|
+
* @see https://github.com/Leaflet/Leaflet/blob/v1.9.3/src/map/Map.js
|
|
558
585
|
*/
|
|
586
|
+
|
|
559
587
|
const mapProto = L.extend({}, L.Map.prototype);
|
|
560
588
|
|
|
561
589
|
L.Map.mergeOptions({ rotate: false, bearing: 0, });
|
|
562
590
|
|
|
563
591
|
L.Map.include({
|
|
564
592
|
|
|
565
|
-
|
|
593
|
+
/**
|
|
594
|
+
* @param {(HTMLElement|String)} id html selector
|
|
595
|
+
* @param {Object} [options={}] leaflet map options
|
|
596
|
+
*/
|
|
597
|
+
initialize: function(id, options) {
|
|
566
598
|
if (options.rotate) {
|
|
567
599
|
this._rotate = true;
|
|
568
600
|
this._bearing = 0;
|
|
569
601
|
}
|
|
570
|
-
mapProto.initialize.
|
|
602
|
+
mapProto.initialize.apply(this, arguments);
|
|
571
603
|
if(this.options.rotate){
|
|
572
604
|
this.setBearing(this.options.bearing);
|
|
573
605
|
}
|
|
574
606
|
},
|
|
575
607
|
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
// }
|
|
586
|
-
// return mapProto.createPane.call(this, name, container || this._rotatePane);
|
|
587
|
-
// },
|
|
588
|
-
|
|
589
|
-
containerPointToLayerPoint: function(point) { // (Point)
|
|
608
|
+
/**
|
|
609
|
+
* Given a pixel coordinate relative to the map container,
|
|
610
|
+
* returns the corresponding pixel coordinate relative to
|
|
611
|
+
* the [origin pixel](#map-getpixelorigin).
|
|
612
|
+
*
|
|
613
|
+
* @param {L.Point} point pixel screen coordinates
|
|
614
|
+
* @returns {L.Point} transformed pixel point
|
|
615
|
+
*/
|
|
616
|
+
containerPointToLayerPoint: function(point) {
|
|
590
617
|
if (!this._rotate) {
|
|
591
|
-
return mapProto.containerPointToLayerPoint.
|
|
618
|
+
return mapProto.containerPointToLayerPoint.apply(this, arguments);
|
|
592
619
|
}
|
|
593
620
|
return L.point(point)
|
|
594
621
|
.subtract(this._getMapPanePos())
|
|
@@ -596,23 +623,16 @@
|
|
|
596
623
|
.subtract(this._getRotatePanePos());
|
|
597
624
|
},
|
|
598
625
|
|
|
599
|
-
|
|
626
|
+
/**
|
|
627
|
+
* Given a pixel coordinate relative to the [origin pixel](#map-getpixelorigin),
|
|
628
|
+
* returns the corresponding pixel coordinate relative to the map container.
|
|
629
|
+
*
|
|
630
|
+
* @param {L.Point} point pixel screen coordinates
|
|
631
|
+
* @returns {L.Point} transformed pixel point
|
|
632
|
+
*/
|
|
633
|
+
layerPointToContainerPoint: function(point) {
|
|
600
634
|
if (!this._rotate) {
|
|
601
|
-
return mapProto.
|
|
602
|
-
}
|
|
603
|
-
var size = this.getSize();
|
|
604
|
-
var topleft = this.layerPointToLatLng(this.containerPointToLayerPoint([0, 0])),
|
|
605
|
-
topright = this.layerPointToLatLng(this.containerPointToLayerPoint([size.x, 0])),
|
|
606
|
-
bottomright = this.layerPointToLatLng(this.containerPointToLayerPoint([size.x, size.y])),
|
|
607
|
-
bottomleft = this.layerPointToLatLng(this.containerPointToLayerPoint([0, size.y]));
|
|
608
|
-
|
|
609
|
-
// Use LatLngBounds' build-in constructor that automatically extends the bounds to fit the passed points
|
|
610
|
-
return new L.LatLngBounds([topleft, topright, bottomright, bottomleft]);
|
|
611
|
-
},
|
|
612
|
-
|
|
613
|
-
layerPointToContainerPoint: function(point) { // (Point)
|
|
614
|
-
if (!this._rotate) {
|
|
615
|
-
return mapProto.layerPointToContainerPoint.call(this, point);
|
|
635
|
+
return mapProto.layerPointToContainerPoint.apply(this, arguments);
|
|
616
636
|
}
|
|
617
637
|
return L.point(point)
|
|
618
638
|
.add(this._getRotatePanePos())
|
|
@@ -620,89 +640,215 @@
|
|
|
620
640
|
.add(this._getMapPanePos());
|
|
621
641
|
},
|
|
622
642
|
|
|
623
|
-
|
|
624
|
-
|
|
643
|
+
/**
|
|
644
|
+
* Converts a coordinate from the rotated pane reference system
|
|
645
|
+
* to the reference system of the not rotated map pane.
|
|
646
|
+
*
|
|
647
|
+
* (rotatePane) --> (mapPane)
|
|
648
|
+
* (rotatePane) --> (norotatePane)
|
|
649
|
+
*
|
|
650
|
+
* @param {L.Point} point pixel screen coordinates
|
|
651
|
+
* @returns {L.Point}
|
|
652
|
+
*
|
|
653
|
+
* @since leaflet-rotate (v0.1)
|
|
654
|
+
*/
|
|
655
|
+
rotatedPointToMapPanePoint: function(point) {
|
|
656
|
+
return L.point(point)
|
|
657
|
+
.rotate(this._bearing)
|
|
658
|
+
._add(this._getRotatePanePos());
|
|
659
|
+
},
|
|
660
|
+
|
|
661
|
+
/**
|
|
662
|
+
* Converts a coordinate from the not rotated map pane reference system
|
|
663
|
+
* to the reference system of the rotated pane.
|
|
664
|
+
*
|
|
665
|
+
* (mapPane) --> (rotatePane)
|
|
666
|
+
* (norotatePane) --> (rotatePane)
|
|
667
|
+
*
|
|
668
|
+
* @param {L.Point} point pixel screen coordinates
|
|
669
|
+
*
|
|
670
|
+
* @since leaflet-rotate (v0.1)
|
|
671
|
+
*/
|
|
672
|
+
mapPanePointToRotatedPoint: function(point) {
|
|
673
|
+
return L.point(point)
|
|
674
|
+
._subtract(this._getRotatePanePos())
|
|
675
|
+
.rotate(-this._bearing);
|
|
676
|
+
},
|
|
677
|
+
|
|
678
|
+
/**
|
|
679
|
+
* Given latlng bounds, returns the bounds in projected pixel
|
|
680
|
+
* relative to the map container.
|
|
681
|
+
*
|
|
682
|
+
* @see https://github.com/ronikar/Leaflet/blob/5c480ef959b947c3beed7065425a5a36c486262b/src/map/Map.js#L1114-L1135
|
|
683
|
+
*
|
|
684
|
+
* @param {L.LatLngBounds} bounds
|
|
685
|
+
* @returns {L.Bounds}
|
|
686
|
+
*
|
|
687
|
+
* @since leaflet-rotate (v0.2)
|
|
688
|
+
*/
|
|
689
|
+
mapBoundsToContainerBounds: function (bounds) {
|
|
690
|
+
if (!this._rotate && mapProto.mapBoundsToContainerBounds) {
|
|
691
|
+
return mapProto.mapBoundsToContainerBounds.apply(this, arguments);
|
|
692
|
+
}
|
|
693
|
+
const nw = this.latLngToContainerPoint(bounds.getNorthWest()),
|
|
694
|
+
ne = this.latLngToContainerPoint(bounds.getNorthEast()),
|
|
695
|
+
sw = this.latLngToContainerPoint(bounds.getSouthWest()),
|
|
696
|
+
se = this.latLngToContainerPoint(bounds.getSouthEast());
|
|
697
|
+
return L.bounds([
|
|
698
|
+
L.point(Math.min(nw.x, ne.x, se.x, sw.x), Math.min(nw.y, ne.y, se.y, sw.y)), // [ minX, minY ]
|
|
699
|
+
L.point(Math.max(nw.x, ne.x, se.x, sw.x), Math.max(nw.y, ne.y, se.y, sw.y)) // [ maxX, maxY ]
|
|
700
|
+
]);
|
|
701
|
+
},
|
|
702
|
+
|
|
703
|
+
/**
|
|
704
|
+
* Returns geographical bounds visible in the current map view
|
|
705
|
+
*
|
|
706
|
+
* @TODO find out if map bounds calculated by `L.Map::getBounds()`
|
|
707
|
+
* function should match the `rotatePane` or `norotatePane` bounds
|
|
708
|
+
*
|
|
709
|
+
* @see https://github.com/fnicollet/Leaflet/issues/7
|
|
710
|
+
*
|
|
711
|
+
* @returns {L.LatLngBounds}
|
|
712
|
+
*/
|
|
713
|
+
getBounds: function() {
|
|
714
|
+
if (!this._rotate) {
|
|
715
|
+
return mapProto.getBounds.apply(this, arguments);
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
// SEE: https://github.com/fnicollet/Leaflet/pull/22
|
|
719
|
+
//
|
|
720
|
+
// var bounds = this.getPixelBounds(),
|
|
721
|
+
// sw = this.unproject(bounds.getBottomLeft()),
|
|
722
|
+
// ne = this.unproject(bounds.getTopRight());
|
|
723
|
+
// return new LatLngBounds(sw, ne);
|
|
724
|
+
//
|
|
725
|
+
|
|
726
|
+
// LatLngBounds' constructor automatically
|
|
727
|
+
// extends the bounds to fit the passed points
|
|
728
|
+
var size = this.getSize();
|
|
729
|
+
return new L.LatLngBounds([
|
|
730
|
+
this.containerPointToLatLng([0, 0]), // topleft
|
|
731
|
+
this.containerPointToLatLng([size.x, 0]), // topright
|
|
732
|
+
this.containerPointToLatLng([size.x, size.y]), // bottomright
|
|
733
|
+
this.containerPointToLatLng([0, size.y]), // bottomleft
|
|
734
|
+
]);
|
|
735
|
+
},
|
|
736
|
+
|
|
737
|
+
/**
|
|
738
|
+
* Returns the bounds of the current map view in projected pixel
|
|
739
|
+
* coordinates (sometimes useful in layer and overlay implementations).
|
|
740
|
+
*
|
|
741
|
+
* @TODO find out if map bounds calculated by `L.Map::getPixelBounds()`
|
|
742
|
+
* function should match the `rotatePane` or `norotatePane` bounds
|
|
743
|
+
*
|
|
744
|
+
* @see https://github.com/fnicollet/Leaflet/issues/7
|
|
745
|
+
*
|
|
746
|
+
* @returns {L.Bounds}
|
|
747
|
+
*/
|
|
748
|
+
// getPixelBounds(center, zoom) {
|
|
749
|
+
// // const topLeftPoint = map.containerPointToLayerPoint(this._getTopLeftPoint());
|
|
750
|
+
// const topLeftPoint = this._getTopLeftPoint(center, zoom);
|
|
751
|
+
// return new L.Bounds(topLeftPoint, topLeftPoint.add(this.getSize()));
|
|
752
|
+
// },
|
|
753
|
+
|
|
754
|
+
/**
|
|
755
|
+
* Change map rotation
|
|
756
|
+
*
|
|
757
|
+
* @param {number} theta map degrees
|
|
758
|
+
*
|
|
759
|
+
* @since leaflet-rotate (v0.1)
|
|
760
|
+
*/
|
|
625
761
|
setBearing: function(theta) {
|
|
626
762
|
if (!L.Browser.any3d || !this._rotate) { return; }
|
|
627
763
|
|
|
628
|
-
var
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
rotatePanePos = rotatePanePos.rotateFrom(-this._bearing, this._pivot);
|
|
764
|
+
var bearing = L.Util.wrapNum(theta, [0, 360]) * L.DomUtil.DEG_TO_RAD,
|
|
765
|
+
center = this._getPixelCenter(),
|
|
766
|
+
oldPos = this._getRotatePanePos().rotateFrom(-this._bearing, center),
|
|
767
|
+
newPos = oldPos.rotateFrom(bearing, center);
|
|
633
768
|
|
|
634
|
-
|
|
635
|
-
|
|
769
|
+
// CSS transform
|
|
770
|
+
L.DomUtil.setPosition(this._rotatePane, oldPos, bearing, center);
|
|
636
771
|
|
|
637
|
-
|
|
772
|
+
this._pivot = center;
|
|
773
|
+
this._bearing = bearing;
|
|
774
|
+
this._rotatePanePos = newPos;
|
|
638
775
|
|
|
639
776
|
this.fire('rotate');
|
|
640
777
|
},
|
|
641
778
|
|
|
779
|
+
/**
|
|
780
|
+
* Get current map rotation
|
|
781
|
+
*
|
|
782
|
+
* @returns {number} theta map degrees
|
|
783
|
+
*
|
|
784
|
+
* @since leaflet-rotate (v0.1)
|
|
785
|
+
*/
|
|
642
786
|
getBearing: function() {
|
|
643
787
|
return this._bearing * L.DomUtil.RAD_TO_DEG;
|
|
644
788
|
},
|
|
645
789
|
|
|
790
|
+
/**
|
|
791
|
+
* Creates a new [map pane](#map-pane) with the given name if it doesn't
|
|
792
|
+
* exist already, then returns it. The pane is created as a child of
|
|
793
|
+
* `container`, or as a child of the main map pane if not set.
|
|
794
|
+
*
|
|
795
|
+
* @param {String} name leaflet pane
|
|
796
|
+
* @param {HTMLElement} [container] parent element
|
|
797
|
+
* @returns {HTMLElement} pane container
|
|
798
|
+
*/
|
|
799
|
+
// createPane: function(name, container) {
|
|
800
|
+
// if (!this._rotate || name == 'mapPane') {
|
|
801
|
+
// return mapProto.createPane.apply(this, arguments);
|
|
802
|
+
// }
|
|
803
|
+
// // init "rotatePane"
|
|
804
|
+
// if (!this._rotatePane) {
|
|
805
|
+
// // this._pivot = this.getSize().divideBy(2);
|
|
806
|
+
// this._rotatePane = mapProto.createPane.call(this, 'rotatePane', this._mapPane);
|
|
807
|
+
// L.DomUtil.setPosition(this._rotatePane, new L.Point(0, 0), this._bearing, this._pivot);
|
|
808
|
+
// }
|
|
809
|
+
// return mapProto.createPane.call(this, name, container || this._rotatePane);
|
|
810
|
+
// },
|
|
811
|
+
|
|
812
|
+
/**
|
|
813
|
+
* Panes are DOM elements used to control the ordering of layers on
|
|
814
|
+
* the map. You can access panes with [`map.getPane`](#map-getpane)
|
|
815
|
+
* or [`map.getPanes`](#map-getpanes) methods. New panes can be created
|
|
816
|
+
* with the [`map.createPane`](#map-createpane) method.
|
|
817
|
+
*
|
|
818
|
+
* Every map has the following default panes that differ only in zIndex:
|
|
819
|
+
*
|
|
820
|
+
* - mapPane [HTMLElement = 'auto'] - Pane that contains all other map panes
|
|
821
|
+
* - tilePane [HTMLElement = 2] - Pane for tile layers
|
|
822
|
+
* - overlayPane [HTMLElement = 4] - Pane for overlays like polylines and polygons
|
|
823
|
+
* - shadowPane [HTMLElement = 5] - Pane for overlay shadows (e.g. marker shadows)
|
|
824
|
+
* - markerPane [HTMLElement = 6] - Pane for marker icons
|
|
825
|
+
* - tooltipPane [HTMLElement = 650] - Pane for tooltips.
|
|
826
|
+
* - popupPane [HTMLElement = 700] - Pane for popups.
|
|
827
|
+
*/
|
|
646
828
|
_initPanes: function() {
|
|
647
829
|
var panes = this._panes = {};
|
|
648
830
|
this._paneRenderers = {};
|
|
649
831
|
|
|
650
|
-
// @section
|
|
651
|
-
//
|
|
652
|
-
// Panes are DOM elements used to control the ordering of layers on the map. You
|
|
653
|
-
// can access panes with [`map.getPane`](#map-getpane) or
|
|
654
|
-
// [`map.getPanes`](#map-getpanes) methods. New panes can be created with the
|
|
655
|
-
// [`map.createPane`](#map-createpane) method.
|
|
656
|
-
//
|
|
657
|
-
// Every map has the following default panes that differ only in zIndex.
|
|
658
|
-
//
|
|
659
|
-
// @pane mapPane: HTMLElement = 'auto'
|
|
660
|
-
// Pane that contains all other map panes
|
|
661
|
-
|
|
662
832
|
this._mapPane = this.createPane('mapPane', this._container);
|
|
663
833
|
L.DomUtil.setPosition(this._mapPane, new L.Point(0, 0));
|
|
664
834
|
|
|
665
835
|
if (this._rotate) {
|
|
666
836
|
this._rotatePane = this.createPane('rotatePane', this._mapPane);
|
|
667
837
|
this._norotatePane = this.createPane('norotatePane', this._mapPane);
|
|
668
|
-
|
|
669
|
-
// @pane tilePane: HTMLElement = 2
|
|
670
|
-
// Pane for tile layers
|
|
838
|
+
// rotatePane
|
|
671
839
|
this.createPane('tilePane', this._rotatePane);
|
|
672
|
-
// @pane overlayPane: HTMLElement = 4
|
|
673
|
-
// Pane for overlays like polylines and polygons
|
|
674
840
|
this.createPane('overlayPane', this._rotatePane);
|
|
675
|
-
|
|
676
|
-
// @pane shadowPane: HTMLElement = 5
|
|
677
|
-
// Pane for overlay shadows (e.g. marker shadows)
|
|
841
|
+
// norotatePane
|
|
678
842
|
this.createPane('shadowPane', this._norotatePane);
|
|
679
|
-
// @pane markerPane: HTMLElement = 6
|
|
680
|
-
// Pane for marker icons
|
|
681
843
|
this.createPane('markerPane', this._norotatePane);
|
|
682
|
-
// @pane tooltipPane: HTMLElement = 650
|
|
683
|
-
// Pane for tooltips.
|
|
684
844
|
this.createPane('tooltipPane', this._norotatePane);
|
|
685
|
-
// @pane popupPane: HTMLElement = 700
|
|
686
|
-
// Pane for popups.
|
|
687
845
|
this.createPane('popupPane', this._norotatePane);
|
|
688
846
|
} else {
|
|
689
|
-
// @pane tilePane: HTMLElement = 2
|
|
690
|
-
// Pane for tile layers
|
|
691
847
|
this.createPane('tilePane');
|
|
692
|
-
// @pane overlayPane: HTMLElement = 4
|
|
693
|
-
// Pane for overlays like polylines and polygons
|
|
694
848
|
this.createPane('overlayPane');
|
|
695
|
-
// @pane shadowPane: HTMLElement = 5
|
|
696
|
-
// Pane for overlay shadows (e.g. marker shadows)
|
|
697
849
|
this.createPane('shadowPane');
|
|
698
|
-
// @pane markerPane: HTMLElement = 6
|
|
699
|
-
// Pane for marker icons
|
|
700
850
|
this.createPane('markerPane');
|
|
701
|
-
// @pane tooltipPane: HTMLElement = 650
|
|
702
|
-
// Pane for tooltips.
|
|
703
851
|
this.createPane('tooltipPane');
|
|
704
|
-
// @pane popupPane: HTMLElement = 700
|
|
705
|
-
// Pane for popups.
|
|
706
852
|
this.createPane('popupPane');
|
|
707
853
|
}
|
|
708
854
|
|
|
@@ -712,37 +858,205 @@
|
|
|
712
858
|
}
|
|
713
859
|
},
|
|
714
860
|
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
861
|
+
/**
|
|
862
|
+
* Pans the map the minimum amount to make the `latlng` visible. Use
|
|
863
|
+
* padding options to fit the display to more restricted bounds.
|
|
864
|
+
* If `latlng` is already within the (optionally padded) display bounds,
|
|
865
|
+
* the map will not be panned.
|
|
866
|
+
*
|
|
867
|
+
* @see https://github.com/Raruto/leaflet-rotate/issues/18
|
|
868
|
+
*
|
|
869
|
+
* @param {L.LatLng} latlng coordinates
|
|
870
|
+
* @param {Object} [options={}] padding options
|
|
871
|
+
*
|
|
872
|
+
* @returns {L.Map} current map instance
|
|
873
|
+
*/
|
|
874
|
+
panInside(latlng, options) {
|
|
875
|
+
options = options || {};
|
|
876
|
+
|
|
877
|
+
const paddingTL = L.point(options.paddingTopLeft || options.padding || [0, 0]),
|
|
878
|
+
paddingBR = L.point(options.paddingBottomRight || options.padding || [0, 0]),
|
|
879
|
+
/** @TODO use mapProto.panInside */
|
|
880
|
+
// pixelPoint = this.project(latlng),
|
|
881
|
+
// pixelBounds = this.getPixelBounds(),
|
|
882
|
+
// pixelCenter = this.project(this.getCenter()),
|
|
883
|
+
rect = this._container.getBoundingClientRect(),
|
|
884
|
+
pixelPoint = this.latLngToContainerPoint(latlng),
|
|
885
|
+
pixelBounds = L.bounds([ L.point(rect), L.point(rect).add(this.getSize()) ]),
|
|
886
|
+
pixelCenter = pixelBounds.getCenter(),
|
|
887
|
+
//
|
|
888
|
+
paddedBounds = L.bounds([pixelBounds.min.add(paddingTL), pixelBounds.max.subtract(paddingBR)]),
|
|
889
|
+
paddedSize = paddedBounds.getSize();
|
|
890
|
+
|
|
891
|
+
if (!paddedBounds.contains(pixelPoint)) {
|
|
892
|
+
this._enforcingBounds = true;
|
|
893
|
+
const centerOffset = pixelPoint.subtract(paddedBounds.getCenter());
|
|
894
|
+
const offset = paddedBounds.extend(pixelPoint).getSize().subtract(paddedSize);
|
|
895
|
+
pixelCenter.x += centerOffset.x < 0 ? -offset.x : offset.x;
|
|
896
|
+
pixelCenter.y += centerOffset.y < 0 ? -offset.y : offset.y;
|
|
897
|
+
/** @TODO use mapProto.panInside */
|
|
898
|
+
// this.panTo(this.unproject(pixelCenter), options);
|
|
899
|
+
this.panTo(this.containerPointToLatLng(pixelCenter), options);
|
|
900
|
+
//
|
|
901
|
+
this._enforcingBounds = false;
|
|
902
|
+
}
|
|
903
|
+
return this;
|
|
904
|
+
},
|
|
905
|
+
|
|
906
|
+
/**
|
|
907
|
+
* Pans the map to the closest view that would lie inside the given bounds
|
|
908
|
+
* (if it's not already), controlling the animation using the options specific,
|
|
909
|
+
* if any.
|
|
910
|
+
*
|
|
911
|
+
* @TODO check if map bounds calculated by `L.Map::panInsideBounds()`
|
|
912
|
+
* function should match the `rotatePane` or `norotatePane` bounds
|
|
913
|
+
*
|
|
914
|
+
* @see https://github.com/fnicollet/Leaflet/issues/7
|
|
915
|
+
*
|
|
916
|
+
* @param {L.LatLngBounds} bounds coordinates
|
|
917
|
+
* @param {Object} [options] pan options
|
|
918
|
+
* @returns {L.Map} current map instance
|
|
919
|
+
*/
|
|
920
|
+
// panInsideBounds: function (bounds, options) {
|
|
921
|
+
// this._enforcingBounds = true;
|
|
922
|
+
// var center = this.getCenter(),
|
|
923
|
+
// newCenter = this._limitCenter(center, this._zoom, L.latLngBounds(bounds));
|
|
924
|
+
//
|
|
925
|
+
// if (!center.equals(newCenter)) {
|
|
926
|
+
// this.panTo(newCenter, options);
|
|
927
|
+
// }
|
|
928
|
+
//
|
|
929
|
+
// this._enforcingBounds = false;
|
|
930
|
+
// return this;
|
|
931
|
+
// },
|
|
721
932
|
|
|
722
|
-
//
|
|
723
|
-
//
|
|
724
|
-
//
|
|
725
|
-
|
|
726
|
-
|
|
933
|
+
// adjust center for view to get inside bounds
|
|
934
|
+
// _limitCenter(center, zoom, bounds) {
|
|
935
|
+
//
|
|
936
|
+
// if (!bounds) { return center; }
|
|
937
|
+
//
|
|
938
|
+
// const centerPoint = this.project(center, zoom),
|
|
939
|
+
// viewHalf = this.getSize().divideBy(2),
|
|
940
|
+
// viewBounds = new Bounds(centerPoint.subtract(viewHalf), centerPoint.add(viewHalf)),
|
|
941
|
+
// offset = this._getBoundsOffset(viewBounds, bounds, zoom);
|
|
942
|
+
//
|
|
943
|
+
// // If offset is less than a pixel, ignore.
|
|
944
|
+
// // This prevents unstable projections from getting into
|
|
945
|
+
// // an infinite loop of tiny offsets.
|
|
946
|
+
// if (Math.abs(offset.x) <= 1 && Math.abs(offset.y) <= 1) {
|
|
947
|
+
// return center;
|
|
948
|
+
// }
|
|
949
|
+
//
|
|
950
|
+
// return this.unproject(centerPoint.add(offset), zoom);
|
|
951
|
+
// },
|
|
952
|
+
|
|
953
|
+
// @method flyToBounds(bounds: LatLngBounds, options?: fitBounds options): this
|
|
954
|
+
// Sets the view of the map with a smooth animation like [`flyTo`](#map-flyto),
|
|
955
|
+
// but takes a bounds parameter like [`fitBounds`](#map-fitbounds).
|
|
956
|
+
// flyToBounds(bounds, options) {
|
|
957
|
+
// const target = this._getBoundsCenterZoom(bounds, options);
|
|
958
|
+
// return this.flyTo(target.center, target.zoom, options);
|
|
959
|
+
// },
|
|
960
|
+
|
|
961
|
+
// _getBoundsCenterZoom(bounds, options) {
|
|
962
|
+
//
|
|
963
|
+
// options = options || {};
|
|
964
|
+
// bounds = bounds.getBounds ? bounds.getBounds() : toLatLngBounds(bounds);
|
|
965
|
+
//
|
|
966
|
+
// const paddingTL = L.point(options.paddingTopLeft || options.padding || [0, 0]),
|
|
967
|
+
// paddingBR = L.point(options.paddingBottomRight || options.padding || [0, 0]);
|
|
968
|
+
//
|
|
969
|
+
// let zoom = this.getBoundsZoom(bounds, false, paddingTL.add(paddingBR));
|
|
970
|
+
//
|
|
971
|
+
// zoom = (typeof options.maxZoom === 'number') ? Math.min(options.maxZoom, zoom) : zoom;
|
|
972
|
+
//
|
|
973
|
+
// if (zoom === Infinity) {
|
|
974
|
+
// return { center: bounds.getCenter(), zoom };
|
|
975
|
+
// }
|
|
976
|
+
//
|
|
977
|
+
// return { center, zoom };
|
|
978
|
+
//
|
|
979
|
+
// },
|
|
980
|
+
|
|
981
|
+
/**
|
|
982
|
+
* Returns the maximum zoom level on which the given bounds fit to the map
|
|
983
|
+
* view in its entirety. If `inside` (optional) is set to `true`, the method
|
|
984
|
+
* instead returns the minimum zoom level on which the map view fits into
|
|
985
|
+
* the given bounds in its entirety.
|
|
986
|
+
*
|
|
987
|
+
* @param {L.LatLngBounds} bounds
|
|
988
|
+
* @param {Boolean} [inside=false]
|
|
989
|
+
* @param {L.Point} [padding=[0,0]]
|
|
990
|
+
*
|
|
991
|
+
* @returns {Number} zoom level
|
|
992
|
+
*/
|
|
993
|
+
getBoundsZoom(bounds, inside, padding) {
|
|
994
|
+
if (!this._rotate || Math.abs(this._bearing).toFixed(1) < 0.1) {
|
|
995
|
+
return mapProto.getBoundsZoom.apply(this, arguments);
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
bounds = L.latLngBounds(bounds);
|
|
999
|
+
padding = L.point(padding || [0, 0]);
|
|
1000
|
+
|
|
1001
|
+
let zoom = this.getZoom() || 0;
|
|
1002
|
+
const min = this.getMinZoom(),
|
|
1003
|
+
max = this.getMaxZoom(),
|
|
1004
|
+
/** @TODO use mapProto.getBoundsZoom */
|
|
1005
|
+
// nw = bounds.getNorthWest(),
|
|
1006
|
+
// se = bounds.getSouthEast(),
|
|
1007
|
+
// size = this.getSize().subtract(padding),
|
|
1008
|
+
// boundsSize = L.bounds(this.project(se, zoom), this.project(nw, zoom)).getSize(),
|
|
1009
|
+
size = this.getSize().subtract(padding),
|
|
1010
|
+
boundsSize = this.mapBoundsToContainerBounds(bounds).getSize(),
|
|
1011
|
+
snap = this.options.zoomSnap,
|
|
1012
|
+
scalex = size.x / boundsSize.x,
|
|
1013
|
+
scaley = size.y / boundsSize.y,
|
|
1014
|
+
scale = inside ? Math.max(scalex, scaley) : Math.min(scalex, scaley);
|
|
1015
|
+
|
|
1016
|
+
zoom = this.getScaleZoom(scale, zoom);
|
|
1017
|
+
|
|
1018
|
+
if (snap) {
|
|
1019
|
+
zoom = Math.round(zoom / (snap / 100)) * (snap / 100); // don't jump if within 1% of a snap level
|
|
1020
|
+
zoom = inside ? Math.ceil(zoom / snap) * snap : Math.floor(zoom / snap) * snap;
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
return Math.max(min, Math.min(max, zoom));
|
|
727
1024
|
},
|
|
728
1025
|
|
|
729
|
-
|
|
1026
|
+
/**
|
|
1027
|
+
* Layer point of the current center
|
|
1028
|
+
*
|
|
1029
|
+
* @returns {L.Point} layer center
|
|
1030
|
+
*/
|
|
1031
|
+
// _getCenterLayerPoint: function () {
|
|
1032
|
+
// return this.containerPointToLayerPoint(this.getSize()._divideBy(2));
|
|
1033
|
+
// },
|
|
1034
|
+
|
|
1035
|
+
/**
|
|
1036
|
+
* Offset of the specified place to the current center in pixels
|
|
1037
|
+
*
|
|
1038
|
+
* @param {L.LatLng} latlng map coordinates
|
|
1039
|
+
*/
|
|
730
1040
|
_getCenterOffset: function(latlng) {
|
|
731
|
-
var centerOffset = mapProto._getCenterOffset.
|
|
1041
|
+
var centerOffset = mapProto._getCenterOffset.apply(this, arguments);
|
|
732
1042
|
if (this._rotate) {
|
|
733
1043
|
centerOffset = centerOffset.rotate(this._bearing);
|
|
734
1044
|
}
|
|
735
1045
|
return centerOffset;
|
|
736
1046
|
},
|
|
737
1047
|
|
|
1048
|
+
/**
|
|
1049
|
+
* @since leaflet-rotate (v0.1)
|
|
1050
|
+
*/
|
|
738
1051
|
_getRotatePanePos: function() {
|
|
739
1052
|
return this._rotatePanePos || new L.Point(0, 0);
|
|
1053
|
+
// return L.DomUtil.getPosition(this._rotatePane) || new L.Point(0, 0);
|
|
740
1054
|
},
|
|
741
1055
|
|
|
742
1056
|
_getNewPixelOrigin: function(center, zoom) {
|
|
743
1057
|
var viewHalf = this.getSize()._divideBy(2);
|
|
744
1058
|
if (!this._rotate) {
|
|
745
|
-
mapProto._getNewPixelOrigin.
|
|
1059
|
+
return mapProto._getNewPixelOrigin.apply(this, arguments);
|
|
746
1060
|
}
|
|
747
1061
|
return this.project(center, zoom)
|
|
748
1062
|
.rotate(this._bearing)
|
|
@@ -753,10 +1067,72 @@
|
|
|
753
1067
|
._round();
|
|
754
1068
|
},
|
|
755
1069
|
|
|
1070
|
+
/**
|
|
1071
|
+
* @since leaflet-rotate (v0.2)
|
|
1072
|
+
*
|
|
1073
|
+
* @see src\layer\tile\GridLayer::_getTiledPixelBounds()
|
|
1074
|
+
*/
|
|
1075
|
+
_getNewPixelBounds: function(center, zoom) {
|
|
1076
|
+
center = center || this.getCenter();
|
|
1077
|
+
zoom = zoom || this.getZoom();
|
|
1078
|
+
if (!this._rotate && mapProto._getNewPixelBounds) {
|
|
1079
|
+
return mapProto._getNewPixelBounds.apply(this, arguments);
|
|
1080
|
+
}
|
|
1081
|
+
var mapZoom = this._animatingZoom ? Math.max(this._animateToZoom, this.getZoom()) : this.getZoom(),
|
|
1082
|
+
scale = this.getZoomScale(mapZoom, zoom),
|
|
1083
|
+
pixelCenter = this.project(center, zoom).floor(),
|
|
1084
|
+
size = this.getSize(),
|
|
1085
|
+
halfSize = new L.Bounds([
|
|
1086
|
+
this.containerPointToLayerPoint([0, 0]).floor(),
|
|
1087
|
+
this.containerPointToLayerPoint([size.x, 0]).floor(),
|
|
1088
|
+
this.containerPointToLayerPoint([0, size.y]).floor(),
|
|
1089
|
+
this.containerPointToLayerPoint([size.x, size.y]).floor()
|
|
1090
|
+
]).getSize().divideBy(scale * 2);
|
|
1091
|
+
|
|
1092
|
+
return new L.Bounds(pixelCenter.subtract(halfSize), pixelCenter.add(halfSize));
|
|
1093
|
+
},
|
|
1094
|
+
|
|
1095
|
+
/**
|
|
1096
|
+
* @since leaflet-rotate (v0.2)
|
|
1097
|
+
*
|
|
1098
|
+
* @return {L.Point} map pivot point (center)
|
|
1099
|
+
*/
|
|
1100
|
+
_getPixelCenter: function() {
|
|
1101
|
+
if (!this._rotate && mapProto._getPixelCenter) {
|
|
1102
|
+
return mapProto._getPixelCenter.apply(this, arguments);
|
|
1103
|
+
}
|
|
1104
|
+
return this.getSize()._divideBy(2)._subtract(this._getMapPanePos());
|
|
1105
|
+
},
|
|
1106
|
+
|
|
1107
|
+
/**
|
|
1108
|
+
* @since leaflet-rotate (v0.2)
|
|
1109
|
+
*
|
|
1110
|
+
* @see src\layer\vector\Renderer::_update()
|
|
1111
|
+
*/
|
|
1112
|
+
_getPaddedPixelBounds: function(padding) {
|
|
1113
|
+
if (!this._rotate && mapProto._getPaddedPixelBounds) {
|
|
1114
|
+
return mapProto._getPaddedPixelBounds.apply(this, arguments);
|
|
1115
|
+
}
|
|
1116
|
+
var p = padding,
|
|
1117
|
+
size = this.getSize(),
|
|
1118
|
+
padMin = size.multiplyBy(-p),
|
|
1119
|
+
padMax = size.multiplyBy(1 + p);
|
|
1120
|
+
//min = this.containerPointToLayerPoint(size.multiplyBy(-p)).round();
|
|
1121
|
+
|
|
1122
|
+
return new L.Bounds([
|
|
1123
|
+
this.containerPointToLayerPoint([padMin.x, padMin.y]).floor(),
|
|
1124
|
+
this.containerPointToLayerPoint([padMin.x, padMax.y]).floor(),
|
|
1125
|
+
this.containerPointToLayerPoint([padMax.x, padMin.y]).floor(),
|
|
1126
|
+
this.containerPointToLayerPoint([padMax.x, padMax.y]).floor()
|
|
1127
|
+
]);
|
|
1128
|
+
},
|
|
1129
|
+
|
|
756
1130
|
_handleGeolocationResponse: function(pos) {
|
|
1131
|
+
if (!this._container._leaflet_id) { return; }
|
|
1132
|
+
|
|
757
1133
|
var lat = pos.coords.latitude,
|
|
758
1134
|
lng = pos.coords.longitude,
|
|
759
|
-
|
|
1135
|
+
/** @TODO use mapProto._handleGeolocationResponse */
|
|
760
1136
|
hdg = pos.coords.heading,
|
|
761
1137
|
latlng = new L.LatLng(lat, lng),
|
|
762
1138
|
bounds = latlng.toBounds(pos.coords.accuracy),
|
|
@@ -771,7 +1147,7 @@
|
|
|
771
1147
|
latlng: latlng,
|
|
772
1148
|
bounds: bounds,
|
|
773
1149
|
timestamp: pos.timestamp,
|
|
774
|
-
|
|
1150
|
+
/** @TODO use mapProto._handleGeolocationResponse */
|
|
775
1151
|
heading: hdg
|
|
776
1152
|
};
|
|
777
1153
|
|
|
@@ -787,39 +1163,50 @@
|
|
|
787
1163
|
this.fire('locationfound', data);
|
|
788
1164
|
},
|
|
789
1165
|
|
|
1166
|
+
/**
|
|
1167
|
+
* @see https://github.com/ronikar/Leaflet/blob/5c480ef959b947c3beed7065425a5a36c486262b/src/geo/LatLngBounds.js#L253-L264
|
|
1168
|
+
*
|
|
1169
|
+
* @param {L.Bounds} points
|
|
1170
|
+
* @returns {L.Bounds}
|
|
1171
|
+
*/
|
|
1172
|
+
// toCircumscribedBounds(points) {
|
|
1173
|
+
// var minX = points.reduce(function (pv, v) { return Math.min(pv, v.x); }, points[0].x),
|
|
1174
|
+
// maxX = points.reduce(function (pv, v) { return Math.max(pv, v.x); }, points[0].x),
|
|
1175
|
+
// minY = points.reduce(function (pv, v) { return Math.min(pv, v.y); }, points[0].y),
|
|
1176
|
+
// maxY = points.reduce(function (pv, v) { return Math.max(pv, v.y); }, points[0].y);
|
|
1177
|
+
//
|
|
1178
|
+
// return L.bounds(L.point(minX, minY), L.point(maxX, maxY));
|
|
1179
|
+
// },
|
|
1180
|
+
|
|
790
1181
|
});
|
|
791
1182
|
|
|
792
|
-
|
|
793
|
-
*
|
|
1183
|
+
/**
|
|
1184
|
+
* Rotates the map according to a smartphone's compass.
|
|
1185
|
+
*
|
|
1186
|
+
* @typedef L.Map.CompassBearing
|
|
794
1187
|
*/
|
|
795
1188
|
|
|
796
1189
|
L.Map.CompassBearing = L.Handler.extend({
|
|
797
1190
|
|
|
798
1191
|
initialize: function(map) {
|
|
799
|
-
if (!window.DeviceOrientationEvent) {
|
|
800
|
-
this._capable = false;
|
|
801
|
-
return;
|
|
802
|
-
}
|
|
803
|
-
this._capable = true;
|
|
804
1192
|
this._map = map;
|
|
805
|
-
|
|
806
1193
|
this._throttled = L.Util.throttle(this._onDeviceOrientation, 1000, this);
|
|
807
1194
|
},
|
|
808
1195
|
|
|
809
1196
|
addHooks: function() {
|
|
810
|
-
if (this.
|
|
1197
|
+
if (this._map._rotate && window.DeviceOrientationEvent) {
|
|
811
1198
|
L.DomEvent.on(window, 'deviceorientation', this._throttled, this);
|
|
812
1199
|
}
|
|
813
1200
|
},
|
|
814
1201
|
|
|
815
1202
|
removeHooks: function() {
|
|
816
|
-
if (this.
|
|
1203
|
+
if (this._map._rotate && window.DeviceOrientationEvent) {
|
|
817
1204
|
L.DomEvent.off(window, 'deviceorientation', this._throttled, this);
|
|
818
1205
|
}
|
|
819
1206
|
},
|
|
820
1207
|
|
|
821
1208
|
_onDeviceOrientation: function(event) {
|
|
822
|
-
if (event.alpha !== null) {
|
|
1209
|
+
if (event.alpha !== null && window.orientation !== undefined) {
|
|
823
1210
|
this._map.setBearing(event.alpha - window.orientation);
|
|
824
1211
|
}
|
|
825
1212
|
},
|
|
@@ -831,8 +1218,10 @@
|
|
|
831
1218
|
// Compass bearing handler.
|
|
832
1219
|
L.Map.addInitHook('addHandler', 'compassBearing', L.Map.CompassBearing);
|
|
833
1220
|
|
|
834
|
-
|
|
835
|
-
*
|
|
1221
|
+
/**
|
|
1222
|
+
* Triggers `invalidateResize` when the map's DOM container mutates.
|
|
1223
|
+
*
|
|
1224
|
+
* @typedef L.Map.ContainerMutation
|
|
836
1225
|
*/
|
|
837
1226
|
|
|
838
1227
|
// @namespace Map
|
|
@@ -850,9 +1239,10 @@
|
|
|
850
1239
|
L.Map.ContainerMutation = L.Handler.extend({
|
|
851
1240
|
|
|
852
1241
|
addHooks: function() {
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
1242
|
+
/** @TODO check again this property. Will likely be added in future releases (leaflet > v1.9.3) */
|
|
1243
|
+
// if (!L.Browser.mutation) {
|
|
1244
|
+
// return;
|
|
1245
|
+
// }
|
|
856
1246
|
|
|
857
1247
|
if (!this._observer) {
|
|
858
1248
|
this._observer = new MutationObserver(L.Util.bind(this._onMutation, this));
|
|
@@ -868,9 +1258,10 @@
|
|
|
868
1258
|
},
|
|
869
1259
|
|
|
870
1260
|
removeHooks: function() {
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
1261
|
+
/** @TODO check again this property. Will likely be added in future releases (leaflet > v1.9.3) */
|
|
1262
|
+
// if (!L.Browser.mutation) {
|
|
1263
|
+
// return;
|
|
1264
|
+
// }
|
|
874
1265
|
this._observer.disconnect();
|
|
875
1266
|
},
|
|
876
1267
|
|
|
@@ -885,8 +1276,13 @@
|
|
|
885
1276
|
// Container mutation handler (disabled unless [`trackContainerMutation`](#map-trackcontainermutation) is set).
|
|
886
1277
|
L.Map.addInitHook('addHandler', 'trackContainerMutation', L.Map.ContainerMutation);
|
|
887
1278
|
|
|
888
|
-
|
|
889
|
-
*
|
|
1279
|
+
/**
|
|
1280
|
+
* TouchGestures is both TouchZoom plus TouchRotate
|
|
1281
|
+
*
|
|
1282
|
+
* @see https://github.com/fnicollet/Leaflet/commit/a77af51a6b10f308d1b9a16552091d1d0aee8834
|
|
1283
|
+
* @see https://github.com/Leaflet/Leaflet/blob/v1.9.3/src/map/handler/Map.TouchZoom.js
|
|
1284
|
+
*
|
|
1285
|
+
* @typedef L.Map.TouchGestures
|
|
890
1286
|
*/
|
|
891
1287
|
|
|
892
1288
|
// @namespace Map
|
|
@@ -950,11 +1346,11 @@
|
|
|
950
1346
|
|
|
951
1347
|
this._moved = false;
|
|
952
1348
|
|
|
953
|
-
map.
|
|
1349
|
+
map._stop();
|
|
954
1350
|
|
|
955
1351
|
L.DomEvent
|
|
956
1352
|
.on(document, 'touchmove', this._onTouchMove, this)
|
|
957
|
-
.on(document, 'touchend', this._onTouchEnd, this);
|
|
1353
|
+
.on(document, 'touchend touchcancel', this._onTouchEnd, this);
|
|
958
1354
|
|
|
959
1355
|
L.DomEvent.preventDefault(e);
|
|
960
1356
|
},
|
|
@@ -1005,20 +1401,20 @@
|
|
|
1005
1401
|
}
|
|
1006
1402
|
|
|
1007
1403
|
if (!this._moved) {
|
|
1008
|
-
map._moveStart(true);
|
|
1404
|
+
map._moveStart(true, false);
|
|
1009
1405
|
this._moved = true;
|
|
1010
1406
|
}
|
|
1011
1407
|
|
|
1012
1408
|
L.Util.cancelAnimFrame(this._animRequest);
|
|
1013
1409
|
|
|
1014
|
-
var moveFn =
|
|
1410
|
+
var moveFn = map._move.bind(map, this._center, this._zoom, { pinch: true, round: false }, undefined);
|
|
1015
1411
|
this._animRequest = L.Util.requestAnimFrame(moveFn, this, true);
|
|
1016
1412
|
|
|
1017
1413
|
L.DomEvent.preventDefault(e);
|
|
1018
1414
|
},
|
|
1019
1415
|
|
|
1020
1416
|
_onTouchEnd: function() {
|
|
1021
|
-
if (!this._moved || !this._zooming) {
|
|
1417
|
+
if (!this._moved || !(this._zooming || this._rotating)) {
|
|
1022
1418
|
this._zooming = false;
|
|
1023
1419
|
return;
|
|
1024
1420
|
}
|
|
@@ -1028,13 +1424,13 @@
|
|
|
1028
1424
|
L.Util.cancelAnimFrame(this._animRequest);
|
|
1029
1425
|
|
|
1030
1426
|
L.DomEvent
|
|
1031
|
-
.off(document, 'touchmove', this._onTouchMove)
|
|
1032
|
-
.off(document, 'touchend', this._onTouchEnd);
|
|
1427
|
+
.off(document, 'touchmove', this._onTouchMove, this)
|
|
1428
|
+
.off(document, 'touchend touchcancel', this._onTouchEnd, this);
|
|
1033
1429
|
|
|
1034
1430
|
if (this.zoom) {
|
|
1035
|
-
// Pinch updates GridLayers' levels only when
|
|
1431
|
+
// Pinch updates GridLayers' levels only when zoomSnap is off, so zoomSnap becomes noUpdate.
|
|
1036
1432
|
if (this._map.options.zoomAnimation) {
|
|
1037
|
-
this._map._animateZoom(this._center, this._map._limitZoom(this._zoom), true, this._map.options.
|
|
1433
|
+
this._map._animateZoom(this._center, this._map._limitZoom(this._zoom), true, this._map.options.zoomSnap);
|
|
1038
1434
|
} else {
|
|
1039
1435
|
this._map._resetView(this._center, this._map._limitZoom(this._zoom));
|
|
1040
1436
|
}
|
|
@@ -1048,8 +1444,10 @@
|
|
|
1048
1444
|
// Touch gestures handler.
|
|
1049
1445
|
L.Map.addInitHook('addHandler', 'touchGestures', L.Map.TouchGestures);
|
|
1050
1446
|
|
|
1051
|
-
|
|
1052
|
-
*
|
|
1447
|
+
/**
|
|
1448
|
+
* Rotates the map on two-finger (touch devices).
|
|
1449
|
+
*
|
|
1450
|
+
* @typedef L.Map.TouchRotate
|
|
1053
1451
|
*/
|
|
1054
1452
|
|
|
1055
1453
|
// @namespace Map
|
|
@@ -1081,8 +1479,10 @@
|
|
|
1081
1479
|
// Touch rotate handler.
|
|
1082
1480
|
L.Map.addInitHook('addHandler', 'touchRotate', L.Map.TouchRotate);
|
|
1083
1481
|
|
|
1084
|
-
|
|
1085
|
-
*
|
|
1482
|
+
/**
|
|
1483
|
+
* Rotates the map on shift key + mouseheel scrolling (desktop).
|
|
1484
|
+
*
|
|
1485
|
+
* @typedef L.Map.ShiftKeyRotate
|
|
1086
1486
|
*/
|
|
1087
1487
|
|
|
1088
1488
|
// @namespace Map
|
|
@@ -1134,8 +1534,12 @@
|
|
|
1134
1534
|
}
|
|
1135
1535
|
});
|
|
1136
1536
|
|
|
1137
|
-
|
|
1138
|
-
*
|
|
1537
|
+
/**
|
|
1538
|
+
* Adds pinch zoom rotation on mobile browsers
|
|
1539
|
+
*
|
|
1540
|
+
* @see https://github.com/Leaflet/Leaflet/blob/v1.9.3/src/map/handler/Map.TouchZoom.js
|
|
1541
|
+
*
|
|
1542
|
+
* @external L.Map.TouchZoom
|
|
1139
1543
|
*/
|
|
1140
1544
|
|
|
1141
1545
|
// @namespace Map
|
|
@@ -1147,10 +1551,18 @@
|
|
|
1147
1551
|
// Whether the map can be zoomed by touch-dragging with two fingers. If
|
|
1148
1552
|
// passed `'center'`, it will zoom to the center of the view regardless of
|
|
1149
1553
|
// where the touch events (fingers) were. Enabled for touch-capable web
|
|
1150
|
-
// browsers
|
|
1151
|
-
touchZoom: L.Browser.touch
|
|
1554
|
+
// browsers.
|
|
1555
|
+
touchZoom: L.Browser.touch,
|
|
1556
|
+
|
|
1557
|
+
/**
|
|
1558
|
+
* @TODO check if this is a duplicate of `L.Map.TouchGestures::bounceAtZoomLimits`
|
|
1559
|
+
*/
|
|
1152
1560
|
|
|
1561
|
+
// @option bounceAtZoomLimits: Boolean = true
|
|
1562
|
+
// Set it to false if you don't want the map to zoom beyond min/max zoom
|
|
1563
|
+
// and then bounce back when pinch-zooming.
|
|
1153
1564
|
bounceAtZoomLimits: false,
|
|
1565
|
+
|
|
1154
1566
|
});
|
|
1155
1567
|
|
|
1156
1568
|
L.Map.TouchZoom = L.Handler.extend({
|
|
@@ -1174,13 +1586,15 @@
|
|
|
1174
1586
|
L.Map.addInitHook('addHandler', 'touchZoom', L.Map.TouchZoom);
|
|
1175
1587
|
|
|
1176
1588
|
/**
|
|
1177
|
-
*
|
|
1589
|
+
* A tri-state control for map rotation, states are:
|
|
1590
|
+
*
|
|
1591
|
+
* - Locked (default)
|
|
1592
|
+
* - Unlocked (user can pinch-rotate)
|
|
1593
|
+
* - Follow (rotation follows device orientation, if available)
|
|
1594
|
+
*
|
|
1595
|
+
* @typedef L.Control.Rotate
|
|
1178
1596
|
*/
|
|
1179
1597
|
|
|
1180
|
-
// A tri-state control for map rotation. States are:
|
|
1181
|
-
// Locked (default)
|
|
1182
|
-
// Unlocked (user can pinch-rotate)
|
|
1183
|
-
// Follow (rotation follows device orientation, if available)
|
|
1184
1598
|
L.Control.Rotate = L.Control.extend({
|
|
1185
1599
|
|
|
1186
1600
|
options: {
|
|
@@ -1210,6 +1624,7 @@
|
|
|
1210
1624
|
link.appendChild(arrow);
|
|
1211
1625
|
link.href = '#';
|
|
1212
1626
|
link.title = 'Rotate map';
|
|
1627
|
+
// link.draggable = false;
|
|
1213
1628
|
|
|
1214
1629
|
L.DomEvent
|
|
1215
1630
|
.on(link, 'dblclick', L.DomEvent.stopPropagation)
|
|
@@ -1238,7 +1653,7 @@
|
|
|
1238
1653
|
},
|
|
1239
1654
|
|
|
1240
1655
|
_handleMouseDown: function(e) {
|
|
1241
|
-
L.DomEvent.stopPropagation(e);
|
|
1656
|
+
L.DomEvent.stop(e); // L.DomEvent.stopPropagation(e);
|
|
1242
1657
|
this.dragging = true;
|
|
1243
1658
|
this.dragstartX = e.pageX;
|
|
1244
1659
|
this.dragstartY = e.pageY;
|
|
@@ -1248,7 +1663,7 @@
|
|
|
1248
1663
|
},
|
|
1249
1664
|
|
|
1250
1665
|
_handleMouseUp: function(e) {
|
|
1251
|
-
L.DomEvent.stopPropagation(e);
|
|
1666
|
+
L.DomEvent.stop(e); // L.DomEvent.stopPropagation(e);
|
|
1252
1667
|
this.dragging = false;
|
|
1253
1668
|
|
|
1254
1669
|
L.DomEvent
|
|
@@ -1342,5 +1757,5 @@
|
|
|
1342
1757
|
}
|
|
1343
1758
|
});
|
|
1344
1759
|
|
|
1345
|
-
}))
|
|
1760
|
+
}));
|
|
1346
1761
|
//# sourceMappingURL=leaflet-rotate-src.js.map
|