leaflet-with-dashoffset-canvas-fix 1.9.4

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 (90) hide show
  1. package/CHANGELOG.md +2191 -0
  2. package/LICENSE +26 -0
  3. package/README.md +3 -0
  4. package/package.json +149 -0
  5. package/src/Leaflet.js +24 -0
  6. package/src/control/Control.Attribution.js +148 -0
  7. package/src/control/Control.Layers.js +443 -0
  8. package/src/control/Control.Scale.js +132 -0
  9. package/src/control/Control.Zoom.js +146 -0
  10. package/src/control/Control.js +174 -0
  11. package/src/control/index.js +17 -0
  12. package/src/core/Browser.js +220 -0
  13. package/src/core/Class.js +135 -0
  14. package/src/core/Events.js +344 -0
  15. package/src/core/Handler.js +57 -0
  16. package/src/core/Util.js +241 -0
  17. package/src/core/index.js +15 -0
  18. package/src/dom/DomEvent.DoubleTap.js +91 -0
  19. package/src/dom/DomEvent.Pointer.js +97 -0
  20. package/src/dom/DomEvent.js +315 -0
  21. package/src/dom/DomUtil.js +349 -0
  22. package/src/dom/Draggable.js +220 -0
  23. package/src/dom/PosAnimation.js +113 -0
  24. package/src/dom/index.js +9 -0
  25. package/src/geo/LatLng.js +137 -0
  26. package/src/geo/LatLngBounds.js +251 -0
  27. package/src/geo/crs/CRS.EPSG3395.js +20 -0
  28. package/src/geo/crs/CRS.EPSG3857.js +27 -0
  29. package/src/geo/crs/CRS.EPSG4326.js +23 -0
  30. package/src/geo/crs/CRS.Earth.js +33 -0
  31. package/src/geo/crs/CRS.Simple.js +36 -0
  32. package/src/geo/crs/CRS.js +139 -0
  33. package/src/geo/crs/index.js +15 -0
  34. package/src/geo/index.js +7 -0
  35. package/src/geo/projection/Projection.LonLat.js +28 -0
  36. package/src/geo/projection/Projection.Mercator.js +49 -0
  37. package/src/geo/projection/Projection.SphericalMercator.js +44 -0
  38. package/src/geo/projection/index.js +26 -0
  39. package/src/geometry/Bounds.js +219 -0
  40. package/src/geometry/LineUtil.js +306 -0
  41. package/src/geometry/Point.js +222 -0
  42. package/src/geometry/PolyUtil.js +129 -0
  43. package/src/geometry/Transformation.js +79 -0
  44. package/src/geometry/index.js +8 -0
  45. package/src/images/layers.svg +1 -0
  46. package/src/images/logo.svg +1 -0
  47. package/src/images/marker.svg +1 -0
  48. package/src/layer/DivOverlay.js +348 -0
  49. package/src/layer/FeatureGroup.js +94 -0
  50. package/src/layer/GeoJSON.js +452 -0
  51. package/src/layer/ImageOverlay.js +270 -0
  52. package/src/layer/Layer.js +275 -0
  53. package/src/layer/LayerGroup.js +159 -0
  54. package/src/layer/Popup.js +506 -0
  55. package/src/layer/SVGOverlay.js +50 -0
  56. package/src/layer/Tooltip.js +444 -0
  57. package/src/layer/VideoOverlay.js +106 -0
  58. package/src/layer/index.js +24 -0
  59. package/src/layer/marker/DivIcon.js +74 -0
  60. package/src/layer/marker/Icon.Default.js +66 -0
  61. package/src/layer/marker/Icon.js +165 -0
  62. package/src/layer/marker/Marker.Drag.js +161 -0
  63. package/src/layer/marker/Marker.js +419 -0
  64. package/src/layer/marker/index.js +8 -0
  65. package/src/layer/tile/GridLayer.js +923 -0
  66. package/src/layer/tile/TileLayer.WMS.js +137 -0
  67. package/src/layer/tile/TileLayer.js +289 -0
  68. package/src/layer/tile/index.js +6 -0
  69. package/src/layer/vector/Canvas.js +493 -0
  70. package/src/layer/vector/Circle.js +113 -0
  71. package/src/layer/vector/CircleMarker.js +109 -0
  72. package/src/layer/vector/Path.js +148 -0
  73. package/src/layer/vector/Polygon.js +159 -0
  74. package/src/layer/vector/Polyline.js +307 -0
  75. package/src/layer/vector/Rectangle.js +57 -0
  76. package/src/layer/vector/Renderer.getRenderer.js +45 -0
  77. package/src/layer/vector/Renderer.js +133 -0
  78. package/src/layer/vector/SVG.Util.js +39 -0
  79. package/src/layer/vector/SVG.VML.js +144 -0
  80. package/src/layer/vector/SVG.js +207 -0
  81. package/src/layer/vector/index.js +14 -0
  82. package/src/map/Map.js +1751 -0
  83. package/src/map/handler/Map.BoxZoom.js +152 -0
  84. package/src/map/handler/Map.DoubleClickZoom.js +55 -0
  85. package/src/map/handler/Map.Drag.js +235 -0
  86. package/src/map/handler/Map.Keyboard.js +183 -0
  87. package/src/map/handler/Map.ScrollWheelZoom.js +91 -0
  88. package/src/map/handler/Map.TapHold.js +102 -0
  89. package/src/map/handler/Map.TouchZoom.js +130 -0
  90. package/src/map/index.js +17 -0
@@ -0,0 +1,152 @@
1
+ import {Map} from '../Map';
2
+ import {Handler} from '../../core/Handler';
3
+ import * as Util from '../../core/Util';
4
+ import * as DomUtil from '../../dom/DomUtil';
5
+ import * as DomEvent from '../../dom/DomEvent';
6
+ import {LatLngBounds} from '../../geo/LatLngBounds';
7
+ import {Bounds} from '../../geometry/Bounds';
8
+
9
+ /*
10
+ * L.Handler.BoxZoom is used to add shift-drag zoom interaction to the map
11
+ * (zoom to a selected bounding box), enabled by default.
12
+ */
13
+
14
+ // @namespace Map
15
+ // @section Interaction Options
16
+ Map.mergeOptions({
17
+ // @option boxZoom: Boolean = true
18
+ // Whether the map can be zoomed to a rectangular area specified by
19
+ // dragging the mouse while pressing the shift key.
20
+ boxZoom: true
21
+ });
22
+
23
+ export var BoxZoom = Handler.extend({
24
+ initialize: function (map) {
25
+ this._map = map;
26
+ this._container = map._container;
27
+ this._pane = map._panes.overlayPane;
28
+ this._resetStateTimeout = 0;
29
+ map.on('unload', this._destroy, this);
30
+ },
31
+
32
+ addHooks: function () {
33
+ DomEvent.on(this._container, 'mousedown', this._onMouseDown, this);
34
+ },
35
+
36
+ removeHooks: function () {
37
+ DomEvent.off(this._container, 'mousedown', this._onMouseDown, this);
38
+ },
39
+
40
+ moved: function () {
41
+ return this._moved;
42
+ },
43
+
44
+ _destroy: function () {
45
+ DomUtil.remove(this._pane);
46
+ delete this._pane;
47
+ },
48
+
49
+ _resetState: function () {
50
+ this._resetStateTimeout = 0;
51
+ this._moved = false;
52
+ },
53
+
54
+ _clearDeferredResetState: function () {
55
+ if (this._resetStateTimeout !== 0) {
56
+ clearTimeout(this._resetStateTimeout);
57
+ this._resetStateTimeout = 0;
58
+ }
59
+ },
60
+
61
+ _onMouseDown: function (e) {
62
+ if (!e.shiftKey || ((e.which !== 1) && (e.button !== 1))) { return false; }
63
+
64
+ // Clear the deferred resetState if it hasn't executed yet, otherwise it
65
+ // will interrupt the interaction and orphan a box element in the container.
66
+ this._clearDeferredResetState();
67
+ this._resetState();
68
+
69
+ DomUtil.disableTextSelection();
70
+ DomUtil.disableImageDrag();
71
+
72
+ this._startPoint = this._map.mouseEventToContainerPoint(e);
73
+
74
+ DomEvent.on(document, {
75
+ contextmenu: DomEvent.stop,
76
+ mousemove: this._onMouseMove,
77
+ mouseup: this._onMouseUp,
78
+ keydown: this._onKeyDown
79
+ }, this);
80
+ },
81
+
82
+ _onMouseMove: function (e) {
83
+ if (!this._moved) {
84
+ this._moved = true;
85
+
86
+ this._box = DomUtil.create('div', 'leaflet-zoom-box', this._container);
87
+ DomUtil.addClass(this._container, 'leaflet-crosshair');
88
+
89
+ this._map.fire('boxzoomstart');
90
+ }
91
+
92
+ this._point = this._map.mouseEventToContainerPoint(e);
93
+
94
+ var bounds = new Bounds(this._point, this._startPoint),
95
+ size = bounds.getSize();
96
+
97
+ DomUtil.setPosition(this._box, bounds.min);
98
+
99
+ this._box.style.width = size.x + 'px';
100
+ this._box.style.height = size.y + 'px';
101
+ },
102
+
103
+ _finish: function () {
104
+ if (this._moved) {
105
+ DomUtil.remove(this._box);
106
+ DomUtil.removeClass(this._container, 'leaflet-crosshair');
107
+ }
108
+
109
+ DomUtil.enableTextSelection();
110
+ DomUtil.enableImageDrag();
111
+
112
+ DomEvent.off(document, {
113
+ contextmenu: DomEvent.stop,
114
+ mousemove: this._onMouseMove,
115
+ mouseup: this._onMouseUp,
116
+ keydown: this._onKeyDown
117
+ }, this);
118
+ },
119
+
120
+ _onMouseUp: function (e) {
121
+ if ((e.which !== 1) && (e.button !== 1)) { return; }
122
+
123
+ this._finish();
124
+
125
+ if (!this._moved) { return; }
126
+ // Postpone to next JS tick so internal click event handling
127
+ // still see it as "moved".
128
+ this._clearDeferredResetState();
129
+ this._resetStateTimeout = setTimeout(Util.bind(this._resetState, this), 0);
130
+
131
+ var bounds = new LatLngBounds(
132
+ this._map.containerPointToLatLng(this._startPoint),
133
+ this._map.containerPointToLatLng(this._point));
134
+
135
+ this._map
136
+ .fitBounds(bounds)
137
+ .fire('boxzoomend', {boxZoomBounds: bounds});
138
+ },
139
+
140
+ _onKeyDown: function (e) {
141
+ if (e.keyCode === 27) {
142
+ this._finish();
143
+ this._clearDeferredResetState();
144
+ this._resetState();
145
+ }
146
+ }
147
+ });
148
+
149
+ // @section Handlers
150
+ // @property boxZoom: Handler
151
+ // Box (shift-drag with mouse) zoom handler.
152
+ Map.addInitHook('addHandler', 'boxZoom', BoxZoom);
@@ -0,0 +1,55 @@
1
+ import {Map} from '../Map';
2
+ import {Handler} from '../../core/Handler';
3
+
4
+ /*
5
+ * L.Handler.DoubleClickZoom is used to handle double-click zoom on the map, enabled by default.
6
+ */
7
+
8
+ // @namespace Map
9
+ // @section Interaction Options
10
+
11
+ Map.mergeOptions({
12
+ // @option doubleClickZoom: Boolean|String = true
13
+ // Whether the map can be zoomed in by double clicking on it and
14
+ // zoomed out by double clicking while holding shift. If passed
15
+ // `'center'`, double-click zoom will zoom to the center of the
16
+ // view regardless of where the mouse was.
17
+ doubleClickZoom: true
18
+ });
19
+
20
+ export var DoubleClickZoom = Handler.extend({
21
+ addHooks: function () {
22
+ this._map.on('dblclick', this._onDoubleClick, this);
23
+ },
24
+
25
+ removeHooks: function () {
26
+ this._map.off('dblclick', this._onDoubleClick, this);
27
+ },
28
+
29
+ _onDoubleClick: function (e) {
30
+ var map = this._map,
31
+ oldZoom = map.getZoom(),
32
+ delta = map.options.zoomDelta,
33
+ zoom = e.originalEvent.shiftKey ? oldZoom - delta : oldZoom + delta;
34
+
35
+ if (map.options.doubleClickZoom === 'center') {
36
+ map.setZoom(zoom);
37
+ } else {
38
+ map.setZoomAround(e.containerPoint, zoom);
39
+ }
40
+ }
41
+ });
42
+
43
+ // @section Handlers
44
+ //
45
+ // Map properties include interaction handlers that allow you to control
46
+ // interaction behavior in runtime, enabling or disabling certain features such
47
+ // as dragging or touch zoom (see `Handler` methods). For example:
48
+ //
49
+ // ```js
50
+ // map.doubleClickZoom.disable();
51
+ // ```
52
+ //
53
+ // @property doubleClickZoom: Handler
54
+ // Double click zoom handler.
55
+ Map.addInitHook('addHandler', 'doubleClickZoom', DoubleClickZoom);
@@ -0,0 +1,235 @@
1
+ import {Map} from '../Map';
2
+ import {Handler} from '../../core/Handler';
3
+ import {Draggable} from '../../dom/Draggable';
4
+ import * as Util from '../../core/Util';
5
+ import * as DomUtil from '../../dom/DomUtil';
6
+ import {toLatLngBounds as latLngBounds} from '../../geo/LatLngBounds';
7
+ import {toBounds} from '../../geometry/Bounds';
8
+
9
+ /*
10
+ * L.Handler.MapDrag is used to make the map draggable (with panning inertia), enabled by default.
11
+ */
12
+
13
+ // @namespace Map
14
+ // @section Interaction Options
15
+ Map.mergeOptions({
16
+ // @option dragging: Boolean = true
17
+ // Whether the map is draggable with mouse/touch or not.
18
+ dragging: true,
19
+
20
+ // @section Panning Inertia Options
21
+ // @option inertia: Boolean = *
22
+ // If enabled, panning of the map will have an inertia effect where
23
+ // the map builds momentum while dragging and continues moving in
24
+ // the same direction for some time. Feels especially nice on touch
25
+ // devices. Enabled by default.
26
+ inertia: true,
27
+
28
+ // @option inertiaDeceleration: Number = 3000
29
+ // The rate with which the inertial movement slows down, in pixels/second².
30
+ inertiaDeceleration: 3400, // px/s^2
31
+
32
+ // @option inertiaMaxSpeed: Number = Infinity
33
+ // Max speed of the inertial movement, in pixels/second.
34
+ inertiaMaxSpeed: Infinity, // px/s
35
+
36
+ // @option easeLinearity: Number = 0.2
37
+ easeLinearity: 0.2,
38
+
39
+ // TODO refactor, move to CRS
40
+ // @option worldCopyJump: Boolean = false
41
+ // With this option enabled, the map tracks when you pan to another "copy"
42
+ // of the world and seamlessly jumps to the original one so that all overlays
43
+ // like markers and vector layers are still visible.
44
+ worldCopyJump: false,
45
+
46
+ // @option maxBoundsViscosity: Number = 0.0
47
+ // If `maxBounds` is set, this option will control how solid the bounds
48
+ // are when dragging the map around. The default value of `0.0` allows the
49
+ // user to drag outside the bounds at normal speed, higher values will
50
+ // slow down map dragging outside bounds, and `1.0` makes the bounds fully
51
+ // solid, preventing the user from dragging outside the bounds.
52
+ maxBoundsViscosity: 0.0
53
+ });
54
+
55
+ export var Drag = Handler.extend({
56
+ addHooks: function () {
57
+ if (!this._draggable) {
58
+ var map = this._map;
59
+
60
+ this._draggable = new Draggable(map._mapPane, map._container);
61
+
62
+ this._draggable.on({
63
+ dragstart: this._onDragStart,
64
+ drag: this._onDrag,
65
+ dragend: this._onDragEnd
66
+ }, this);
67
+
68
+ this._draggable.on('predrag', this._onPreDragLimit, this);
69
+ if (map.options.worldCopyJump) {
70
+ this._draggable.on('predrag', this._onPreDragWrap, this);
71
+ map.on('zoomend', this._onZoomEnd, this);
72
+
73
+ map.whenReady(this._onZoomEnd, this);
74
+ }
75
+ }
76
+ DomUtil.addClass(this._map._container, 'leaflet-grab leaflet-touch-drag');
77
+ this._draggable.enable();
78
+ this._positions = [];
79
+ this._times = [];
80
+ },
81
+
82
+ removeHooks: function () {
83
+ DomUtil.removeClass(this._map._container, 'leaflet-grab');
84
+ DomUtil.removeClass(this._map._container, 'leaflet-touch-drag');
85
+ this._draggable.disable();
86
+ },
87
+
88
+ moved: function () {
89
+ return this._draggable && this._draggable._moved;
90
+ },
91
+
92
+ moving: function () {
93
+ return this._draggable && this._draggable._moving;
94
+ },
95
+
96
+ _onDragStart: function () {
97
+ var map = this._map;
98
+
99
+ map._stop();
100
+ if (this._map.options.maxBounds && this._map.options.maxBoundsViscosity) {
101
+ var bounds = latLngBounds(this._map.options.maxBounds);
102
+
103
+ this._offsetLimit = toBounds(
104
+ this._map.latLngToContainerPoint(bounds.getNorthWest()).multiplyBy(-1),
105
+ this._map.latLngToContainerPoint(bounds.getSouthEast()).multiplyBy(-1)
106
+ .add(this._map.getSize()));
107
+
108
+ this._viscosity = Math.min(1.0, Math.max(0.0, this._map.options.maxBoundsViscosity));
109
+ } else {
110
+ this._offsetLimit = null;
111
+ }
112
+
113
+ map
114
+ .fire('movestart')
115
+ .fire('dragstart');
116
+
117
+ if (map.options.inertia) {
118
+ this._positions = [];
119
+ this._times = [];
120
+ }
121
+ },
122
+
123
+ _onDrag: function (e) {
124
+ if (this._map.options.inertia) {
125
+ var time = this._lastTime = +new Date(),
126
+ pos = this._lastPos = this._draggable._absPos || this._draggable._newPos;
127
+
128
+ this._positions.push(pos);
129
+ this._times.push(time);
130
+
131
+ this._prunePositions(time);
132
+ }
133
+
134
+ this._map
135
+ .fire('move', e)
136
+ .fire('drag', e);
137
+ },
138
+
139
+ _prunePositions: function (time) {
140
+ while (this._positions.length > 1 && time - this._times[0] > 50) {
141
+ this._positions.shift();
142
+ this._times.shift();
143
+ }
144
+ },
145
+
146
+ _onZoomEnd: function () {
147
+ var pxCenter = this._map.getSize().divideBy(2),
148
+ pxWorldCenter = this._map.latLngToLayerPoint([0, 0]);
149
+
150
+ this._initialWorldOffset = pxWorldCenter.subtract(pxCenter).x;
151
+ this._worldWidth = this._map.getPixelWorldBounds().getSize().x;
152
+ },
153
+
154
+ _viscousLimit: function (value, threshold) {
155
+ return value - (value - threshold) * this._viscosity;
156
+ },
157
+
158
+ _onPreDragLimit: function () {
159
+ if (!this._viscosity || !this._offsetLimit) { return; }
160
+
161
+ var offset = this._draggable._newPos.subtract(this._draggable._startPos);
162
+
163
+ var limit = this._offsetLimit;
164
+ if (offset.x < limit.min.x) { offset.x = this._viscousLimit(offset.x, limit.min.x); }
165
+ if (offset.y < limit.min.y) { offset.y = this._viscousLimit(offset.y, limit.min.y); }
166
+ if (offset.x > limit.max.x) { offset.x = this._viscousLimit(offset.x, limit.max.x); }
167
+ if (offset.y > limit.max.y) { offset.y = this._viscousLimit(offset.y, limit.max.y); }
168
+
169
+ this._draggable._newPos = this._draggable._startPos.add(offset);
170
+ },
171
+
172
+ _onPreDragWrap: function () {
173
+ // TODO refactor to be able to adjust map pane position after zoom
174
+ var worldWidth = this._worldWidth,
175
+ halfWidth = Math.round(worldWidth / 2),
176
+ dx = this._initialWorldOffset,
177
+ x = this._draggable._newPos.x,
178
+ newX1 = (x - halfWidth + dx) % worldWidth + halfWidth - dx,
179
+ newX2 = (x + halfWidth + dx) % worldWidth - halfWidth - dx,
180
+ newX = Math.abs(newX1 + dx) < Math.abs(newX2 + dx) ? newX1 : newX2;
181
+
182
+ this._draggable._absPos = this._draggable._newPos.clone();
183
+ this._draggable._newPos.x = newX;
184
+ },
185
+
186
+ _onDragEnd: function (e) {
187
+ var map = this._map,
188
+ options = map.options,
189
+
190
+ noInertia = !options.inertia || e.noInertia || this._times.length < 2;
191
+
192
+ map.fire('dragend', e);
193
+
194
+ if (noInertia) {
195
+ map.fire('moveend');
196
+
197
+ } else {
198
+ this._prunePositions(+new Date());
199
+
200
+ var direction = this._lastPos.subtract(this._positions[0]),
201
+ duration = (this._lastTime - this._times[0]) / 1000,
202
+ ease = options.easeLinearity,
203
+
204
+ speedVector = direction.multiplyBy(ease / duration),
205
+ speed = speedVector.distanceTo([0, 0]),
206
+
207
+ limitedSpeed = Math.min(options.inertiaMaxSpeed, speed),
208
+ limitedSpeedVector = speedVector.multiplyBy(limitedSpeed / speed),
209
+
210
+ decelerationDuration = limitedSpeed / (options.inertiaDeceleration * ease),
211
+ offset = limitedSpeedVector.multiplyBy(-decelerationDuration / 2).round();
212
+
213
+ if (!offset.x && !offset.y) {
214
+ map.fire('moveend');
215
+
216
+ } else {
217
+ offset = map._limitOffset(offset, map.options.maxBounds);
218
+
219
+ Util.requestAnimFrame(function () {
220
+ map.panBy(offset, {
221
+ duration: decelerationDuration,
222
+ easeLinearity: ease,
223
+ noMoveStart: true,
224
+ animate: true
225
+ });
226
+ });
227
+ }
228
+ }
229
+ }
230
+ });
231
+
232
+ // @section Handlers
233
+ // @property dragging: Handler
234
+ // Map dragging handler (by both mouse and touch).
235
+ Map.addInitHook('addHandler', 'dragging', Drag);
@@ -0,0 +1,183 @@
1
+ import {Map} from '../Map';
2
+ import {Handler} from '../../core/Handler';
3
+ import {on, off, stop} from '../../dom/DomEvent';
4
+ import {toPoint} from '../../geometry/Point';
5
+
6
+
7
+ /*
8
+ * L.Map.Keyboard is handling keyboard interaction with the map, enabled by default.
9
+ */
10
+
11
+ // @namespace Map
12
+ // @section Keyboard Navigation Options
13
+ Map.mergeOptions({
14
+ // @option keyboard: Boolean = true
15
+ // Makes the map focusable and allows users to navigate the map with keyboard
16
+ // arrows and `+`/`-` keys.
17
+ keyboard: true,
18
+
19
+ // @option keyboardPanDelta: Number = 80
20
+ // Amount of pixels to pan when pressing an arrow key.
21
+ keyboardPanDelta: 80
22
+ });
23
+
24
+ export var Keyboard = Handler.extend({
25
+
26
+ keyCodes: {
27
+ left: [37],
28
+ right: [39],
29
+ down: [40],
30
+ up: [38],
31
+ zoomIn: [187, 107, 61, 171],
32
+ zoomOut: [189, 109, 54, 173]
33
+ },
34
+
35
+ initialize: function (map) {
36
+ this._map = map;
37
+
38
+ this._setPanDelta(map.options.keyboardPanDelta);
39
+ this._setZoomDelta(map.options.zoomDelta);
40
+ },
41
+
42
+ addHooks: function () {
43
+ var container = this._map._container;
44
+
45
+ // make the container focusable by tabbing
46
+ if (container.tabIndex <= 0) {
47
+ container.tabIndex = '0';
48
+ }
49
+
50
+ on(container, {
51
+ focus: this._onFocus,
52
+ blur: this._onBlur,
53
+ mousedown: this._onMouseDown
54
+ }, this);
55
+
56
+ this._map.on({
57
+ focus: this._addHooks,
58
+ blur: this._removeHooks
59
+ }, this);
60
+ },
61
+
62
+ removeHooks: function () {
63
+ this._removeHooks();
64
+
65
+ off(this._map._container, {
66
+ focus: this._onFocus,
67
+ blur: this._onBlur,
68
+ mousedown: this._onMouseDown
69
+ }, this);
70
+
71
+ this._map.off({
72
+ focus: this._addHooks,
73
+ blur: this._removeHooks
74
+ }, this);
75
+ },
76
+
77
+ _onMouseDown: function () {
78
+ if (this._focused) { return; }
79
+
80
+ var body = document.body,
81
+ docEl = document.documentElement,
82
+ top = body.scrollTop || docEl.scrollTop,
83
+ left = body.scrollLeft || docEl.scrollLeft;
84
+
85
+ this._map._container.focus();
86
+
87
+ window.scrollTo(left, top);
88
+ },
89
+
90
+ _onFocus: function () {
91
+ this._focused = true;
92
+ this._map.fire('focus');
93
+ },
94
+
95
+ _onBlur: function () {
96
+ this._focused = false;
97
+ this._map.fire('blur');
98
+ },
99
+
100
+ _setPanDelta: function (panDelta) {
101
+ var keys = this._panKeys = {},
102
+ codes = this.keyCodes,
103
+ i, len;
104
+
105
+ for (i = 0, len = codes.left.length; i < len; i++) {
106
+ keys[codes.left[i]] = [-1 * panDelta, 0];
107
+ }
108
+ for (i = 0, len = codes.right.length; i < len; i++) {
109
+ keys[codes.right[i]] = [panDelta, 0];
110
+ }
111
+ for (i = 0, len = codes.down.length; i < len; i++) {
112
+ keys[codes.down[i]] = [0, panDelta];
113
+ }
114
+ for (i = 0, len = codes.up.length; i < len; i++) {
115
+ keys[codes.up[i]] = [0, -1 * panDelta];
116
+ }
117
+ },
118
+
119
+ _setZoomDelta: function (zoomDelta) {
120
+ var keys = this._zoomKeys = {},
121
+ codes = this.keyCodes,
122
+ i, len;
123
+
124
+ for (i = 0, len = codes.zoomIn.length; i < len; i++) {
125
+ keys[codes.zoomIn[i]] = zoomDelta;
126
+ }
127
+ for (i = 0, len = codes.zoomOut.length; i < len; i++) {
128
+ keys[codes.zoomOut[i]] = -zoomDelta;
129
+ }
130
+ },
131
+
132
+ _addHooks: function () {
133
+ on(document, 'keydown', this._onKeyDown, this);
134
+ },
135
+
136
+ _removeHooks: function () {
137
+ off(document, 'keydown', this._onKeyDown, this);
138
+ },
139
+
140
+ _onKeyDown: function (e) {
141
+ if (e.altKey || e.ctrlKey || e.metaKey) { return; }
142
+
143
+ var key = e.keyCode,
144
+ map = this._map,
145
+ offset;
146
+
147
+ if (key in this._panKeys) {
148
+ if (!map._panAnim || !map._panAnim._inProgress) {
149
+ offset = this._panKeys[key];
150
+ if (e.shiftKey) {
151
+ offset = toPoint(offset).multiplyBy(3);
152
+ }
153
+
154
+ if (map.options.maxBounds) {
155
+ offset = map._limitOffset(toPoint(offset), map.options.maxBounds);
156
+ }
157
+
158
+ if (map.options.worldCopyJump) {
159
+ var newLatLng = map.wrapLatLng(map.unproject(map.project(map.getCenter()).add(offset)));
160
+ map.panTo(newLatLng);
161
+ } else {
162
+ map.panBy(offset);
163
+ }
164
+ }
165
+ } else if (key in this._zoomKeys) {
166
+ map.setZoom(map.getZoom() + (e.shiftKey ? 3 : 1) * this._zoomKeys[key]);
167
+
168
+ } else if (key === 27 && map._popup && map._popup.options.closeOnEscapeKey) {
169
+ map.closePopup();
170
+
171
+ } else {
172
+ return;
173
+ }
174
+
175
+ stop(e);
176
+ }
177
+ });
178
+
179
+ // @section Handlers
180
+ // @section Handlers
181
+ // @property keyboard: Handler
182
+ // Keyboard navigation handler.
183
+ Map.addInitHook('addHandler', 'keyboard', Keyboard);
@@ -0,0 +1,91 @@
1
+ import {Map} from '../Map';
2
+ import {Handler} from '../../core/Handler';
3
+ import * as DomEvent from '../../dom/DomEvent';
4
+ import * as Util from '../../core/Util';
5
+
6
+ /*
7
+ * L.Handler.ScrollWheelZoom is used by L.Map to enable mouse scroll wheel zoom on the map.
8
+ */
9
+
10
+ // @namespace Map
11
+ // @section Interaction Options
12
+ Map.mergeOptions({
13
+ // @section Mouse wheel options
14
+ // @option scrollWheelZoom: Boolean|String = true
15
+ // Whether the map can be zoomed by using the mouse wheel. If passed `'center'`,
16
+ // it will zoom to the center of the view regardless of where the mouse was.
17
+ scrollWheelZoom: true,
18
+
19
+ // @option wheelDebounceTime: Number = 40
20
+ // Limits the rate at which a wheel can fire (in milliseconds). By default
21
+ // user can't zoom via wheel more often than once per 40 ms.
22
+ wheelDebounceTime: 40,
23
+
24
+ // @option wheelPxPerZoomLevel: Number = 60
25
+ // How many scroll pixels (as reported by [L.DomEvent.getWheelDelta](#domevent-getwheeldelta))
26
+ // mean a change of one full zoom level. Smaller values will make wheel-zooming
27
+ // faster (and vice versa).
28
+ wheelPxPerZoomLevel: 60
29
+ });
30
+
31
+ export var ScrollWheelZoom = Handler.extend({
32
+ addHooks: function () {
33
+ DomEvent.on(this._map._container, 'wheel', this._onWheelScroll, this);
34
+
35
+ this._delta = 0;
36
+ },
37
+
38
+ removeHooks: function () {
39
+ DomEvent.off(this._map._container, 'wheel', this._onWheelScroll, this);
40
+ },
41
+
42
+ _onWheelScroll: function (e) {
43
+ var delta = DomEvent.getWheelDelta(e);
44
+
45
+ var debounce = this._map.options.wheelDebounceTime;
46
+
47
+ this._delta += delta;
48
+ this._lastMousePos = this._map.mouseEventToContainerPoint(e);
49
+
50
+ if (!this._startTime) {
51
+ this._startTime = +new Date();
52
+ }
53
+
54
+ var left = Math.max(debounce - (+new Date() - this._startTime), 0);
55
+
56
+ clearTimeout(this._timer);
57
+ this._timer = setTimeout(Util.bind(this._performZoom, this), left);
58
+
59
+ DomEvent.stop(e);
60
+ },
61
+
62
+ _performZoom: function () {
63
+ var map = this._map,
64
+ zoom = map.getZoom(),
65
+ snap = this._map.options.zoomSnap || 0;
66
+
67
+ map._stop(); // stop panning and fly animations if any
68
+
69
+ // map the delta with a sigmoid function to -4..4 range leaning on -1..1
70
+ var d2 = this._delta / (this._map.options.wheelPxPerZoomLevel * 4),
71
+ d3 = 4 * Math.log(2 / (1 + Math.exp(-Math.abs(d2)))) / Math.LN2,
72
+ d4 = snap ? Math.ceil(d3 / snap) * snap : d3,
73
+ delta = map._limitZoom(zoom + (this._delta > 0 ? d4 : -d4)) - zoom;
74
+
75
+ this._delta = 0;
76
+ this._startTime = null;
77
+
78
+ if (!delta) { return; }
79
+
80
+ if (map.options.scrollWheelZoom === 'center') {
81
+ map.setZoom(zoom + delta);
82
+ } else {
83
+ map.setZoomAround(this._lastMousePos, zoom + delta);
84
+ }
85
+ }
86
+ });
87
+
88
+ // @section Handlers
89
+ // @property scrollWheelZoom: Handler
90
+ // Scroll wheel zoom handler.
91
+ Map.addInitHook('addHandler', 'scrollWheelZoom', ScrollWheelZoom);