terriajs
Version:
Geospatial data visualization platform.
160 lines (122 loc) • 4.15 kB
JavaScript
'use strict';
/*
* L.Handler.DragBox is used internally by L.Map to add a drag rectangle (shift-mousebutton1).
* Taken with modifications from Leaflet: leaflet/src/map/handler/Map.BoxZoom.js
*/
function installDragBox(L) {
L.Map.mergeOptions({
dragBox: false // enabled/disabled as needed
});
L.Map.DragBox = L.Handler.extend({
initialize: function (map) {
this._map = map;
this._container = map._container;
this._pane = map._panes.overlayPane;
this._moved = false;
this._dragging = map.dragging.enabled();
},
addHooks: function () {
// disable dragging as it blocks all events on mousedown, create our own mousedown handler and add it
// before re-enabling dragging - is there an issue with ordering here? We rely on our mousedown handler
// getting executed before the dragging mousedown handler
if (this._dragging) {
this._map.dragging.disable();
}
this._map.boxZoom.disable();
L.DomEvent.on(this._container, 'mousedown', this._onMouseDown, this);
if (this._dragging) {
this._map.dragging.enable();
}
this._map.boxZoom.enable();
},
removeHooks: function () {
if (this._dragging) {
this._map.dragging.enable();
}
L.DomEvent.off(this._container, 'mousedown', this._onMouseDown);
this._moved = false;
},
_onMouseDown: function (e) {
this._moved = false;
// enable using shift-mousedown
if (!e.shiftKey || ((e.which !== 1) && (e.button !== 1))) { return false; }
if (this._dragging) {
this._map.dragging.disable();
}
this._map.boxZoom.disable();
L.DomUtil.disableTextSelection();
L.DomUtil.disableImageDrag();
this._startLayerPoint = this._map.mouseEventToLayerPoint(e);
L.DomEvent
.on(document, 'mousemove', this._onMouseMove, this)
.on(document, 'mouseup', this._onMouseUp, this)
.on(document, 'keydown', this._onKeyDown, this);
},
_onMouseMove: function (e) {
if (!this._moved) {
this._box = L.DomUtil.create('div', 'leaflet-zoom-box', this._pane);
L.DomUtil.setPosition(this._box, this._startLayerPoint);
//TODO refactor: move cursor to styles
this._container.style.cursor = 'crosshair';
this._map.fire('dragboxstart');
}
var startPoint = this._startLayerPoint,
box = this._box,
layerPoint = this._map.mouseEventToLayerPoint(e),
offset = layerPoint.subtract(startPoint),
newPos = new L.Point(
Math.min(layerPoint.x, startPoint.x),
Math.min(layerPoint.y, startPoint.y));
L.DomUtil.setPosition(box, newPos);
this._moved = true;
// TODO refactor: remove hardcoded 4 pixels
box.style.width = (Math.abs(offset.x) - 4) + 'px';
box.style.height = (Math.abs(offset.y) - 4) + 'px';
},
_finish: function () {
if (this._moved) {
this._pane.removeChild(this._box);
this._container.style.cursor = '';
}
if (this._dragging) {
this._map.dragging.enable();
}
this._map.boxZoom.enable();
L.DomUtil.enableTextSelection();
L.DomUtil.enableImageDrag();
L.DomEvent
.off(document, 'mousemove', this._onMouseMove)
.off(document, 'mouseup', this._onMouseUp)
.off(document, 'keydown', this._onKeyDown);
},
_onMouseUp: function(e) {
this._finish();
var map = this._map,
layerPoint = map.mouseEventToLayerPoint(e);
if (this._startLayerPoint.equals(layerPoint)) { return; }
var bounds = new L.LatLngBounds(
map.layerPointToLatLng(this._startLayerPoint),
map.layerPointToLatLng(layerPoint));
map.fire("dragboxend", {
dragBoxBounds: bounds
});
},
_onKeyDown: function (e) {
if (e.keyCode === 27) {
this._finish();
}
}
});
L.Map.addInitHook('addHandler', 'dragBox', L.Map.DragBox);
}
var isDragBoxInstalled = false;
var LeafletDragBox = {
initialize: function(leaflet) {
if (isDragBoxInstalled) {
return;
}
isDragBoxInstalled = true;
installDragBox(leaflet);
}
};
module.exports = LeafletDragBox;