leaflet-rotate 0.4.0 → 0.5.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.
Files changed (39) hide show
  1. package/README.md +85 -5
  2. package/dist/leaflet-rotate-src.js +1325 -254
  3. package/dist/leaflet-rotate-src.js.map +4 -4
  4. package/dist/leaflet-rotate.js +1 -1
  5. package/dist/leaflet-rotate.js.map +4 -4
  6. package/lib/debug.js +62 -88
  7. package/lib/debug.min.js +16 -1
  8. package/misc/leaflet-heat-rotate.js +7 -0
  9. package/package.json +1 -1
  10. package/src/control/Rotate.js +160 -103
  11. package/src/dom/DomUtil.js +23 -12
  12. package/src/dom/Draggable.js +5 -0
  13. package/src/geo/LatLngBounds.js +5 -0
  14. package/src/geometry/Bounds.js +5 -0
  15. package/src/geometry/Point.js +17 -3
  16. package/src/index.js +4 -1
  17. package/src/layer/DivOverlay.js +34 -5
  18. package/src/layer/Popup.js +14 -3
  19. package/src/layer/Tooltip.js +16 -0
  20. package/src/layer/marker/Icon.js +12 -0
  21. package/src/layer/marker/Marker.js +86 -7
  22. package/src/layer/tile/GridLayer.js +38 -3
  23. package/src/layer/vector/Renderer.js +88 -34
  24. package/src/map/Map.js +578 -116
  25. package/src/map/handler/CompassBearing.js +34 -1
  26. package/src/map/handler/ContainerMutation.js +18 -1
  27. package/src/map/handler/ShiftKeyRotate.js +204 -13
  28. package/src/map/handler/TouchGestures.js +108 -10
  29. package/src/map/handler/TouchPitch.js +53 -0
  30. package/src/map/handler/TouchRotate.js +18 -1
  31. package/src/map/handler/TouchZoom.js +21 -1
  32. package/test/features/example.feature +8 -4
  33. package/test/features/gestures.feature +4 -0
  34. package/test/features/rotation.feature +60 -0
  35. package/test/index.html +342 -186
  36. package/test/steps/bearing.steps.js +535 -0
  37. package/test/steps/example.steps.js +56 -29
  38. package/test/steps/gestures.steps.js +55 -0
  39. package/test/support/hooks.js +4 -16
@@ -1,30 +1,85 @@
1
1
  /**
2
+ * Recalculates vector renderer bounds and transforms for rotated and pitched maps.
3
+ *
2
4
  * @external L.Renderer
3
5
  *
4
6
  * @see https://github.com/Leaflet/Leaflet/tree/v1.9.3/src/layer/vector/Renderer.js
7
+ *
8
+ * @since leaflet-rotate (v0.1.0)
5
9
  */
6
10
 
7
11
  const rendererProto = Object.defineProperties({}, Object.getOwnPropertyDescriptors(L.Renderer.prototype));
8
12
  const rendererBase = Object.getPrototypeOf(L.Renderer.prototype);
9
13
  const rendererGetEvents = rendererProto.getEvents || rendererBase.getEvents;
14
+ const rendererOnMoveEnd = rendererProto._onMoveEnd || rendererBase._onMoveEnd;
10
15
 
11
16
  L.Renderer.include({
12
17
 
13
18
  /**
14
- * Redraw L.Canvas and L.SVG renderer bounds after the
15
- * map is moved by just calling `map.setBearing(theta)`
19
+ * Subscribe the renderer to map rotation so its visible bounds are recalculated.
16
20
  *
17
21
  * @listens L.Map~rotate
22
+ *
23
+ * @returns {Object} Leaflet event map for the renderer.
24
+ *
25
+ * @since leaflet-rotate (v0.1.0)
18
26
  */
19
27
  getEvents() {
20
28
  const events = rendererGetEvents.apply(this, arguments);
21
- return L.version.startsWith('2.') ? events : Object.assign(events, { rotate: this._update });
29
+ return Object.assign(events, { rotate: this._onRotate });
30
+ },
31
+
32
+ /**
33
+ * Refresh renderer bounds after bearing or pitch changes.
34
+ *
35
+ * Paths are reprojected only when the pixel origin actually changed (eg. fractional centers
36
+ * after an off-center zoom), since reprojection is the main cost with long polylines.
37
+ *
38
+ * @since leaflet-rotate (v0.1.0)
39
+ */
40
+ _onRotate() {
41
+ if (!this._map._rotate) { return; }
42
+ const origin = this._map.getPixelOrigin();
43
+ if (!this._rotateOrigin || !this._rotateOrigin.equals(origin)) {
44
+ this._rotateOrigin = origin;
45
+ clearTimeout(this._rotateTimer);
46
+ this._onZoomEnd();
47
+ this._updateAfterRotate();
48
+ return;
49
+ }
50
+ // paths are still aligned: only redraw when the view leaves the already drawn area
51
+ if (this._bounds && this._bounds.contains(this._map._getPaddedPixelBounds(0))) { return; }
52
+ clearTimeout(this._rotateTimer);
53
+ const wait = (this._lastRotateUpdate || 0) + 100 - performance.now();
54
+ if (wait > 0) {
55
+ this._rotateTimer = setTimeout(() => this._map && this._updateAfterRotate(), wait);
56
+ } else {
57
+ this._updateAfterRotate();
58
+ }
59
+ },
60
+
61
+ /**
62
+ * Recalculate renderer bounds and redraw after bearing or pitch changes.
63
+ *
64
+ * @since leaflet-rotate (0.5.1)
65
+ */
66
+ _updateAfterRotate() {
67
+ this._lastRotateUpdate = performance.now();
68
+ if (L.version.startsWith('2.')) {
69
+ this._onMoveEnd();
70
+ } else {
71
+ this._update();
72
+ }
22
73
  },
23
74
 
24
75
  /**
25
- * Fix for `map.flyTo()` when `false === map.options.zoomAnimation`
76
+ * Add the zoom-animation class needed for correct renderer transforms in Leaflet 1.
77
+ *
78
+ * Fixes `map.flyTo()` when `map.options.zoomAnimation` is false.
26
79
  *
27
80
  * @see https://github.com/Leaflet/Leaflet/pull/8794
81
+ *
82
+ * @since leaflet-rotate (v0.2.0)
28
83
  */
29
84
  onAdd() {
30
85
  rendererProto.onAdd.apply(this, arguments);
@@ -35,56 +90,44 @@ L.Renderer.include({
35
90
  },
36
91
 
37
92
  /**
38
- * @FIXME layer drifts on `map.setZoom()` (eg. zoom during animation)
39
- *
40
- * the main cause seems to be related to `this._updateTransform(path._center, path._zoom))`
41
- * and `this._topLeft = this._map.layerPointToLatLng(this._bounds.min);`
42
- *
43
- * @example
44
- * map.setZoom(2);
45
- * path._renderer._update();
46
- * path._renderer._updateTransform(path._renderer._center, path._renderer._zoom);
93
+ * Update the renderer transform during zoom animation, accounting for rotated coordinates.
47
94
  *
48
95
  * @see https://github.com/Leaflet/Leaflet/pull/8794
49
96
  * @see https://github.com/Leaflet/Leaflet/pull/8103
50
97
  * @see https://github.com/Leaflet/Leaflet/issues/7466
51
98
  *
52
- * @TODO rechek this changes from leaflet@v1.9.3
99
+ * @param {L.LatLng} center Target map center.
100
+ * @param {number} zoom Target zoom level.
53
101
  *
54
- * @see https://github.com/Leaflet/Leaflet/compare/v1.7.0...v1.9.3
102
+ * @since leaflet-rotate (v0.1.0)
55
103
  */
56
104
  _updateTransform(center, zoom) {
57
- if (L.version.startsWith('2.')) {
58
- if (this._map._rotate) {
59
- const scale = this._map.getZoomScale(zoom, this._zoom),
60
- offset = this._topLeftPoint.multiplyBy(scale)
61
- .subtract(this._map._getNewPixelOrigin(center, zoom));
62
-
63
- L.DomUtil.setTransform(this._container, offset, scale);
64
- return;
65
- }
66
- return rendererBase._updateTransform.apply(this, arguments);
67
- }
105
+ const v2 = L.version.startsWith('2.');
68
106
  if (!this._map._rotate) {
69
- return rendererProto._updateTransform.apply(this, arguments);
107
+ return (v2 ? rendererBase : rendererProto)._updateTransform.apply(this, arguments);
70
108
  }
71
- if (zoom === this._zoom) {
109
+ if (!v2 && zoom === this._zoom) {
72
110
  // _reset() has already repositioned the renderer at the current zoom.
73
111
  return;
74
112
  }
75
- /**
76
- * @FIXME see path._renderer._reset();
77
- */
113
+ // Stay in pixel space: round-tripping `_topLeft` through lat/lng clamps at low zooms (layers jump).
78
114
  const scale = this._map.getZoomScale(zoom, this._zoom),
79
- offset = this._map._latLngToNewLayerPoint(this._topLeft, zoom, center);
115
+ offset = this._topLeftPoint.multiplyBy(scale)
116
+ .subtract(this._map._getNewPixelOrigin(center, zoom));
80
117
 
81
118
  L.DomUtil.setTransform(this._container, offset, scale);
82
-
83
119
  },
84
120
 
121
+ /**
122
+ * Recalculate bounds and finish renderer updates after movement on Leaflet 2.
123
+ *
124
+ * @param {Object} ev Map movement event.
125
+ *
126
+ * @since leaflet-rotate (v0.4.0)
127
+ */
85
128
  _onMoveEnd(ev) {
86
129
  if (!L.version.startsWith('2.') || !this._map._rotate) {
87
- return rendererBase._onMoveEnd.apply(this, arguments);
130
+ return rendererOnMoveEnd.apply(this, arguments);
88
131
  }
89
132
 
90
133
  this._bounds = this._map._getPaddedPixelBounds(this.options.padding);
@@ -97,6 +140,11 @@ L.Renderer.include({
97
140
  this._onSettled(ev);
98
141
  },
99
142
 
143
+ /**
144
+ * Resize the renderer container to cover the pitch-aware map bounds.
145
+ *
146
+ * @since leaflet-rotate (v0.4.0)
147
+ */
100
148
  _resizeContainer() {
101
149
  if (!L.version.startsWith('2.') || !this._map._rotate || !this._bounds) {
102
150
  return rendererBase._resizeContainer.apply(this, arguments);
@@ -150,6 +198,11 @@ L.Renderer.include({
150
198
  // }
151
199
  // },
152
200
 
201
+ /**
202
+ * Recalculate renderer bounds and cached view state.
203
+ *
204
+ * @since leaflet-rotate (v0.1.0)
205
+ */
153
206
  _update() {
154
207
  if (!this._map._rotate) {
155
208
  return rendererProto._update.apply(this, arguments);
@@ -160,6 +213,7 @@ L.Renderer.include({
160
213
  this._topLeft = this._map.layerPointToLatLng(this._bounds.min);
161
214
  this._center = this._map.getCenter();
162
215
  this._zoom = this._map.getZoom();
216
+ this._topLeftPoint = this._map._getNewPixelOrigin(this._center, this._zoom).add(this._bounds.min);
163
217
  },
164
218
 
165
219
  });