leaflet
Version:
JavaScript library for mobile-friendly interactive maps
124 lines (95 loc) • 2.99 kB
JavaScript
/*
* L.Handler.BoxZoom is used to add shift-drag zoom interaction to the map
* (zoom to a selected bounding box), enabled by default.
*/
// @namespace Map
// @section Interaction Options
L.Map.mergeOptions({
// @option boxZoom: Boolean = true
// Whether the map can be zoomed to a rectangular area specified by
// dragging the mouse while pressing the shift key.
boxZoom: true
});
L.Map.BoxZoom = L.Handler.extend({
initialize: function (map) {
this._map = map;
this._container = map._container;
this._pane = map._panes.overlayPane;
},
addHooks: function () {
L.DomEvent.on(this._container, 'mousedown', this._onMouseDown, this);
},
removeHooks: function () {
L.DomEvent.off(this._container, 'mousedown', this._onMouseDown, this);
},
moved: function () {
return this._moved;
},
_resetState: function () {
this._moved = false;
},
_onMouseDown: function (e) {
if (!e.shiftKey || ((e.which !== 1) && (e.button !== 1))) { return false; }
this._resetState();
L.DomUtil.disableTextSelection();
L.DomUtil.disableImageDrag();
this._startPoint = this._map.mouseEventToContainerPoint(e);
L.DomEvent.on(document, {
contextmenu: L.DomEvent.stop,
mousemove: this._onMouseMove,
mouseup: this._onMouseUp,
keydown: this._onKeyDown
}, this);
},
_onMouseMove: function (e) {
if (!this._moved) {
this._moved = true;
this._box = L.DomUtil.create('div', 'leaflet-zoom-box', this._container);
L.DomUtil.addClass(this._container, 'leaflet-crosshair');
this._map.fire('boxzoomstart');
}
this._point = this._map.mouseEventToContainerPoint(e);
var bounds = new L.Bounds(this._point, this._startPoint),
size = bounds.getSize();
L.DomUtil.setPosition(this._box, bounds.min);
this._box.style.width = size.x + 'px';
this._box.style.height = size.y + 'px';
},
_finish: function () {
if (this._moved) {
L.DomUtil.remove(this._box);
L.DomUtil.removeClass(this._container, 'leaflet-crosshair');
}
L.DomUtil.enableTextSelection();
L.DomUtil.enableImageDrag();
L.DomEvent.off(document, {
contextmenu: L.DomEvent.stop,
mousemove: this._onMouseMove,
mouseup: this._onMouseUp,
keydown: this._onKeyDown
}, this);
},
_onMouseUp: function (e) {
if ((e.which !== 1) && (e.button !== 1)) { return; }
this._finish();
if (!this._moved) { return; }
// Postpone to next JS tick so internal click event handling
// still see it as "moved".
setTimeout(L.bind(this._resetState, this), 0);
var bounds = new L.LatLngBounds(
this._map.containerPointToLatLng(this._startPoint),
this._map.containerPointToLatLng(this._point));
this._map
.fitBounds(bounds)
.fire('boxzoomend', {boxZoomBounds: bounds});
},
_onKeyDown: function (e) {
if (e.keyCode === 27) {
this._finish();
}
}
});
// @section Handlers
// @property boxZoom: Handler
// Box (shift-drag with mouse) zoom handler.
L.Map.addInitHook('addHandler', 'boxZoom', L.Map.BoxZoom);