258 lines
7.2 KiB
JavaScript
258 lines
7.2 KiB
JavaScript
/**
|
|
* @module ol/interaction/DragBox
|
|
*/
|
|
// FIXME draw drag box
|
|
import Event from '../events/Event.js';
|
|
import {inherits} from '../index.js';
|
|
import {always, mouseOnly, mouseActionButton} from '../events/condition.js';
|
|
import {UNDEFINED} from '../functions.js';
|
|
import PointerInteraction from '../interaction/Pointer.js';
|
|
import RenderBox from '../render/Box.js';
|
|
|
|
|
|
/**
|
|
* A function that takes a {@link module:ol/MapBrowserEvent~MapBrowserEvent} and two
|
|
* {@link module:ol~Pixel}s and returns a `{boolean}`. If the condition is met,
|
|
* true should be returned.
|
|
* @typedef {function(module:ol/MapBrowserEvent~MapBrowserEvent, module:ol~Pixel, module:ol~Pixel):boolean} EndCondition
|
|
*/
|
|
|
|
|
|
/**
|
|
* @typedef {Object} Options
|
|
* @property {string} [className='ol-dragbox'] CSS class name for styling the box.
|
|
* @property {module:ol/events/condition~Condition} [condition] A function that takes an {@link module:ol/MapBrowserEvent~MapBrowserEvent} and returns a boolean
|
|
* to indicate whether that event should be handled.
|
|
* Default is {@link ol/events/condition~always}.
|
|
* @property {number} [minArea=64] The minimum area of the box in pixel, this value is used by the default
|
|
* `boxEndCondition` function.
|
|
* @property {module:ol/interaction/DragBox~EndCondition} [boxEndCondition] A function that takes a {@link module:ol/MapBrowserEvent~MapBrowserEvent} and two
|
|
* {@link module:ol~Pixel}s to indicate whether a `boxend` event should be fired.
|
|
* Default is `true` if the area of the box is bigger than the `minArea` option.
|
|
*/
|
|
|
|
|
|
/**
|
|
* @enum {string}
|
|
*/
|
|
const DragBoxEventType = {
|
|
/**
|
|
* Triggered upon drag box start.
|
|
* @event module:ol/interaction/DragBox~DragBoxEvent#boxstart
|
|
* @api
|
|
*/
|
|
BOXSTART: 'boxstart',
|
|
|
|
/**
|
|
* Triggered on drag when box is active.
|
|
* @event module:ol/interaction/DragBox~DragBoxEvent#boxdrag
|
|
* @api
|
|
*/
|
|
BOXDRAG: 'boxdrag',
|
|
|
|
/**
|
|
* Triggered upon drag box end.
|
|
* @event module:ol/interaction/DragBox~DragBoxEvent#boxend
|
|
* @api
|
|
*/
|
|
BOXEND: 'boxend'
|
|
};
|
|
|
|
|
|
/**
|
|
* @classdesc
|
|
* Events emitted by {@link module:ol/interaction/DragBox~DragBox} instances are instances of
|
|
* this type.
|
|
*
|
|
* @param {string} type The event type.
|
|
* @param {module:ol/coordinate~Coordinate} coordinate The event coordinate.
|
|
* @param {module:ol/MapBrowserEvent~MapBrowserEvent} mapBrowserEvent Originating event.
|
|
* @extends {module:ol/events/Event~Event}
|
|
* @constructor
|
|
* @implements {oli.DragBoxEvent}
|
|
*/
|
|
const DragBoxEvent = function(type, coordinate, mapBrowserEvent) {
|
|
Event.call(this, type);
|
|
|
|
/**
|
|
* The coordinate of the drag event.
|
|
* @const
|
|
* @type {module:ol/coordinate~Coordinate}
|
|
* @api
|
|
*/
|
|
this.coordinate = coordinate;
|
|
|
|
/**
|
|
* @const
|
|
* @type {module:ol/MapBrowserEvent~MapBrowserEvent}
|
|
* @api
|
|
*/
|
|
this.mapBrowserEvent = mapBrowserEvent;
|
|
|
|
};
|
|
|
|
inherits(DragBoxEvent, Event);
|
|
|
|
|
|
/**
|
|
* @classdesc
|
|
* Allows the user to draw a vector box by clicking and dragging on the map,
|
|
* normally combined with an {@link module:ol/events/condition} that limits
|
|
* it to when the shift or other key is held down. This is used, for example,
|
|
* for zooming to a specific area of the map
|
|
* (see {@link module:ol/interaction/DragZoom~DragZoom} and
|
|
* {@link module:ol/interaction/DragRotateAndZoom}).
|
|
*
|
|
* This interaction is only supported for mouse devices.
|
|
*
|
|
* @constructor
|
|
* @extends {module:ol/interaction/Pointer~Pointer}
|
|
* @fires module:ol/interaction/DragBox~DragBoxEvent
|
|
* @param {module:ol/interaction/DragBox~Options=} opt_options Options.
|
|
* @api
|
|
*/
|
|
const DragBox = function(opt_options) {
|
|
|
|
PointerInteraction.call(this, {
|
|
handleDownEvent: handleDownEvent,
|
|
handleDragEvent: handleDragEvent,
|
|
handleUpEvent: handleUpEvent
|
|
});
|
|
|
|
const options = opt_options ? opt_options : {};
|
|
|
|
/**
|
|
* @type {module:ol/render/Box~Box}
|
|
* @private
|
|
*/
|
|
this.box_ = new RenderBox(options.className || 'ol-dragbox');
|
|
|
|
/**
|
|
* @type {number}
|
|
* @private
|
|
*/
|
|
this.minArea_ = options.minArea !== undefined ? options.minArea : 64;
|
|
|
|
/**
|
|
* @type {module:ol~Pixel}
|
|
* @private
|
|
*/
|
|
this.startPixel_ = null;
|
|
|
|
/**
|
|
* @private
|
|
* @type {module:ol/events/condition~Condition}
|
|
*/
|
|
this.condition_ = options.condition ? options.condition : always;
|
|
|
|
/**
|
|
* @private
|
|
* @type {module:ol/interaction/DragBox~EndCondition}
|
|
*/
|
|
this.boxEndCondition_ = options.boxEndCondition ?
|
|
options.boxEndCondition : defaultBoxEndCondition;
|
|
};
|
|
|
|
inherits(DragBox, PointerInteraction);
|
|
|
|
|
|
/**
|
|
* The default condition for determining whether the boxend event
|
|
* should fire.
|
|
* @param {module:ol/MapBrowserEvent~MapBrowserEvent} mapBrowserEvent The originating MapBrowserEvent
|
|
* leading to the box end.
|
|
* @param {module:ol~Pixel} startPixel The starting pixel of the box.
|
|
* @param {module:ol~Pixel} endPixel The end pixel of the box.
|
|
* @return {boolean} Whether or not the boxend condition should be fired.
|
|
* @this {module:ol/interaction/DragBox~DragBox}
|
|
*/
|
|
function defaultBoxEndCondition(mapBrowserEvent, startPixel, endPixel) {
|
|
const width = endPixel[0] - startPixel[0];
|
|
const height = endPixel[1] - startPixel[1];
|
|
return width * width + height * height >= this.minArea_;
|
|
}
|
|
|
|
|
|
/**
|
|
* @param {module:ol/MapBrowserPointerEvent~MapBrowserPointerEvent} mapBrowserEvent Event.
|
|
* @this {module:ol/interaction/DragBox~DragBox}
|
|
*/
|
|
function handleDragEvent(mapBrowserEvent) {
|
|
if (!mouseOnly(mapBrowserEvent)) {
|
|
return;
|
|
}
|
|
|
|
this.box_.setPixels(this.startPixel_, mapBrowserEvent.pixel);
|
|
|
|
this.dispatchEvent(new DragBoxEvent(DragBoxEventType.BOXDRAG,
|
|
mapBrowserEvent.coordinate, mapBrowserEvent));
|
|
}
|
|
|
|
|
|
/**
|
|
* Returns geometry of last drawn box.
|
|
* @return {module:ol/geom/Polygon~Polygon} Geometry.
|
|
* @api
|
|
*/
|
|
DragBox.prototype.getGeometry = function() {
|
|
return this.box_.getGeometry();
|
|
};
|
|
|
|
|
|
/**
|
|
* To be overridden by child classes.
|
|
* FIXME: use constructor option instead of relying on overriding.
|
|
* @param {module:ol/MapBrowserEvent~MapBrowserEvent} mapBrowserEvent Map browser event.
|
|
* @protected
|
|
*/
|
|
DragBox.prototype.onBoxEnd = UNDEFINED;
|
|
|
|
|
|
/**
|
|
* @param {module:ol/MapBrowserPointerEvent~MapBrowserPointerEvent} mapBrowserEvent Event.
|
|
* @return {boolean} Stop drag sequence?
|
|
* @this {module:ol/interaction/DragBox~DragBox}
|
|
*/
|
|
function handleUpEvent(mapBrowserEvent) {
|
|
if (!mouseOnly(mapBrowserEvent)) {
|
|
return true;
|
|
}
|
|
|
|
this.box_.setMap(null);
|
|
|
|
if (this.boxEndCondition_(mapBrowserEvent,
|
|
this.startPixel_, mapBrowserEvent.pixel)) {
|
|
this.onBoxEnd(mapBrowserEvent);
|
|
this.dispatchEvent(new DragBoxEvent(DragBoxEventType.BOXEND,
|
|
mapBrowserEvent.coordinate, mapBrowserEvent));
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
/**
|
|
* @param {module:ol/MapBrowserPointerEvent~MapBrowserPointerEvent} mapBrowserEvent Event.
|
|
* @return {boolean} Start drag sequence?
|
|
* @this {module:ol/interaction/DragBox~DragBox}
|
|
*/
|
|
function handleDownEvent(mapBrowserEvent) {
|
|
if (!mouseOnly(mapBrowserEvent)) {
|
|
return false;
|
|
}
|
|
|
|
if (mouseActionButton(mapBrowserEvent) &&
|
|
this.condition_(mapBrowserEvent)) {
|
|
this.startPixel_ = mapBrowserEvent.pixel;
|
|
this.box_.setMap(mapBrowserEvent.map);
|
|
this.box_.setPixels(this.startPixel_, this.startPixel_);
|
|
this.dispatchEvent(new DragBoxEvent(DragBoxEventType.BOXSTART,
|
|
mapBrowserEvent.coordinate, mapBrowserEvent));
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
export default DragBox;
|