184 lines
4.1 KiB
JavaScript
184 lines
4.1 KiB
JavaScript
|
|
import {Map} from '../Map';
|
||
|
|
import {Handler} from '../../core/Handler';
|
||
|
|
import {on, off, stop} from '../../dom/DomEvent';
|
||
|
|
import {toPoint} from '../../geometry/Point';
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
* L.Map.Keyboard is handling keyboard interaction with the map, enabled by default.
|
||
|
|
*/
|
||
|
|
|
||
|
|
// @namespace Map
|
||
|
|
// @section Keyboard Navigation Options
|
||
|
|
Map.mergeOptions({
|
||
|
|
// @option keyboard: Boolean = true
|
||
|
|
// Makes the map focusable and allows users to navigate the map with keyboard
|
||
|
|
// arrows and `+`/`-` keys.
|
||
|
|
keyboard: true,
|
||
|
|
|
||
|
|
// @option keyboardPanDelta: Number = 80
|
||
|
|
// Amount of pixels to pan when pressing an arrow key.
|
||
|
|
keyboardPanDelta: 80
|
||
|
|
});
|
||
|
|
|
||
|
|
export var Keyboard = Handler.extend({
|
||
|
|
|
||
|
|
keyCodes: {
|
||
|
|
left: [37],
|
||
|
|
right: [39],
|
||
|
|
down: [40],
|
||
|
|
up: [38],
|
||
|
|
zoomIn: [187, 107, 61, 171],
|
||
|
|
zoomOut: [189, 109, 54, 173]
|
||
|
|
},
|
||
|
|
|
||
|
|
initialize: function (map) {
|
||
|
|
this._map = map;
|
||
|
|
|
||
|
|
this._setPanDelta(map.options.keyboardPanDelta);
|
||
|
|
this._setZoomDelta(map.options.zoomDelta);
|
||
|
|
},
|
||
|
|
|
||
|
|
addHooks: function () {
|
||
|
|
var container = this._map._container;
|
||
|
|
|
||
|
|
// make the container focusable by tabbing
|
||
|
|
if (container.tabIndex <= 0) {
|
||
|
|
container.tabIndex = '0';
|
||
|
|
}
|
||
|
|
|
||
|
|
on(container, {
|
||
|
|
focus: this._onFocus,
|
||
|
|
blur: this._onBlur,
|
||
|
|
mousedown: this._onMouseDown
|
||
|
|
}, this);
|
||
|
|
|
||
|
|
this._map.on({
|
||
|
|
focus: this._addHooks,
|
||
|
|
blur: this._removeHooks
|
||
|
|
}, this);
|
||
|
|
},
|
||
|
|
|
||
|
|
removeHooks: function () {
|
||
|
|
this._removeHooks();
|
||
|
|
|
||
|
|
off(this._map._container, {
|
||
|
|
focus: this._onFocus,
|
||
|
|
blur: this._onBlur,
|
||
|
|
mousedown: this._onMouseDown
|
||
|
|
}, this);
|
||
|
|
|
||
|
|
this._map.off({
|
||
|
|
focus: this._addHooks,
|
||
|
|
blur: this._removeHooks
|
||
|
|
}, this);
|
||
|
|
},
|
||
|
|
|
||
|
|
_onMouseDown: function () {
|
||
|
|
if (this._focused) { return; }
|
||
|
|
|
||
|
|
var body = document.body,
|
||
|
|
docEl = document.documentElement,
|
||
|
|
top = body.scrollTop || docEl.scrollTop,
|
||
|
|
left = body.scrollLeft || docEl.scrollLeft;
|
||
|
|
|
||
|
|
this._map._container.focus();
|
||
|
|
|
||
|
|
window.scrollTo(left, top);
|
||
|
|
},
|
||
|
|
|
||
|
|
_onFocus: function () {
|
||
|
|
this._focused = true;
|
||
|
|
this._map.fire('focus');
|
||
|
|
},
|
||
|
|
|
||
|
|
_onBlur: function () {
|
||
|
|
this._focused = false;
|
||
|
|
this._map.fire('blur');
|
||
|
|
},
|
||
|
|
|
||
|
|
_setPanDelta: function (panDelta) {
|
||
|
|
var keys = this._panKeys = {},
|
||
|
|
codes = this.keyCodes,
|
||
|
|
i, len;
|
||
|
|
|
||
|
|
for (i = 0, len = codes.left.length; i < len; i++) {
|
||
|
|
keys[codes.left[i]] = [-1 * panDelta, 0];
|
||
|
|
}
|
||
|
|
for (i = 0, len = codes.right.length; i < len; i++) {
|
||
|
|
keys[codes.right[i]] = [panDelta, 0];
|
||
|
|
}
|
||
|
|
for (i = 0, len = codes.down.length; i < len; i++) {
|
||
|
|
keys[codes.down[i]] = [0, panDelta];
|
||
|
|
}
|
||
|
|
for (i = 0, len = codes.up.length; i < len; i++) {
|
||
|
|
keys[codes.up[i]] = [0, -1 * panDelta];
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
_setZoomDelta: function (zoomDelta) {
|
||
|
|
var keys = this._zoomKeys = {},
|
||
|
|
codes = this.keyCodes,
|
||
|
|
i, len;
|
||
|
|
|
||
|
|
for (i = 0, len = codes.zoomIn.length; i < len; i++) {
|
||
|
|
keys[codes.zoomIn[i]] = zoomDelta;
|
||
|
|
}
|
||
|
|
for (i = 0, len = codes.zoomOut.length; i < len; i++) {
|
||
|
|
keys[codes.zoomOut[i]] = -zoomDelta;
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
_addHooks: function () {
|
||
|
|
on(document, 'keydown', this._onKeyDown, this);
|
||
|
|
},
|
||
|
|
|
||
|
|
_removeHooks: function () {
|
||
|
|
off(document, 'keydown', this._onKeyDown, this);
|
||
|
|
},
|
||
|
|
|
||
|
|
_onKeyDown: function (e) {
|
||
|
|
if (e.altKey || e.ctrlKey || e.metaKey) { return; }
|
||
|
|
|
||
|
|
var key = e.keyCode,
|
||
|
|
map = this._map,
|
||
|
|
offset;
|
||
|
|
|
||
|
|
if (key in this._panKeys) {
|
||
|
|
if (!map._panAnim || !map._panAnim._inProgress) {
|
||
|
|
offset = this._panKeys[key];
|
||
|
|
if (e.shiftKey) {
|
||
|
|
offset = toPoint(offset).multiplyBy(3);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (map.options.maxBounds) {
|
||
|
|
offset = map._limitOffset(toPoint(offset), map.options.maxBounds);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (map.options.worldCopyJump) {
|
||
|
|
var newLatLng = map.wrapLatLng(map.unproject(map.project(map.getCenter()).add(offset)));
|
||
|
|
map.panTo(newLatLng);
|
||
|
|
} else {
|
||
|
|
map.panBy(offset);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
} else if (key in this._zoomKeys) {
|
||
|
|
map.setZoom(map.getZoom() + (e.shiftKey ? 3 : 1) * this._zoomKeys[key]);
|
||
|
|
|
||
|
|
} else if (key === 27 && map._popup && map._popup.options.closeOnEscapeKey) {
|
||
|
|
map.closePopup();
|
||
|
|
|
||
|
|
} else {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
stop(e);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
// @section Handlers
|
||
|
|
// @section Handlers
|
||
|
|
// @property keyboard: Handler
|
||
|
|
// Keyboard navigation handler.
|
||
|
|
Map.addInitHook('addHandler', 'keyboard', Keyboard);
|