239 lines
7.5 KiB
JavaScript
239 lines
7.5 KiB
JavaScript
/**
|
|
* @module ol/interaction/Pointer
|
|
*/
|
|
import Interaction from './Interaction.js';
|
|
import MapBrowserEventType from '../MapBrowserEventType.js';
|
|
import {getValues} from '../obj.js';
|
|
|
|
/**
|
|
* @typedef {Object} Options
|
|
* @property {function(import("../MapBrowserEvent.js").default):boolean} [handleDownEvent]
|
|
* Function handling "down" events. If the function returns `true` then a drag
|
|
* sequence is started.
|
|
* @property {function(import("../MapBrowserEvent.js").default):void} [handleDragEvent]
|
|
* Function handling "drag" events. This function is called on "move" events
|
|
* during a drag sequence.
|
|
* @property {function(import("../MapBrowserEvent.js").default):boolean} [handleEvent]
|
|
* Method called by the map to notify the interaction that a browser event was
|
|
* dispatched to the map. The function may return `false` to prevent the
|
|
* propagation of the event to other interactions in the map's interactions
|
|
* chain.
|
|
* @property {function(import("../MapBrowserEvent.js").default):void} [handleMoveEvent]
|
|
* Function handling "move" events. This function is called on "move" events.
|
|
* This functions is also called during a drag sequence, so during a drag
|
|
* sequence both the `handleDragEvent` function and this function are called.
|
|
* If `handleDownEvent` is defined and it returns true this function will not
|
|
* be called during a drag sequence.
|
|
* @property {function(import("../MapBrowserEvent.js").default):boolean} [handleUpEvent]
|
|
* Function handling "up" events. If the function returns `false` then the
|
|
* current drag sequence is stopped.
|
|
* @property {function(boolean):boolean} [stopDown]
|
|
* Should the down event be propagated to other interactions, or should be
|
|
* stopped?
|
|
*/
|
|
|
|
/**
|
|
* @classdesc
|
|
* Base class that calls user-defined functions on `down`, `move` and `up`
|
|
* events. This class also manages "drag sequences".
|
|
*
|
|
* When the `handleDownEvent` user function returns `true` a drag sequence is
|
|
* started. During a drag sequence the `handleDragEvent` user function is
|
|
* called on `move` events. The drag sequence ends when the `handleUpEvent`
|
|
* user function is called and returns `false`.
|
|
* @api
|
|
*/
|
|
class PointerInteraction extends Interaction {
|
|
/**
|
|
* @param {Options} [opt_options] Options.
|
|
*/
|
|
constructor(opt_options) {
|
|
const options = opt_options ? opt_options : {};
|
|
|
|
super(
|
|
/** @type {import("./Interaction.js").InteractionOptions} */ (options)
|
|
);
|
|
|
|
if (options.handleDownEvent) {
|
|
this.handleDownEvent = options.handleDownEvent;
|
|
}
|
|
|
|
if (options.handleDragEvent) {
|
|
this.handleDragEvent = options.handleDragEvent;
|
|
}
|
|
|
|
if (options.handleMoveEvent) {
|
|
this.handleMoveEvent = options.handleMoveEvent;
|
|
}
|
|
|
|
if (options.handleUpEvent) {
|
|
this.handleUpEvent = options.handleUpEvent;
|
|
}
|
|
|
|
if (options.stopDown) {
|
|
this.stopDown = options.stopDown;
|
|
}
|
|
|
|
/**
|
|
* @type {boolean}
|
|
* @protected
|
|
*/
|
|
this.handlingDownUpSequence = false;
|
|
|
|
/**
|
|
* @type {!Object<string, PointerEvent>}
|
|
* @private
|
|
*/
|
|
this.trackedPointers_ = {};
|
|
|
|
/**
|
|
* @type {Array<PointerEvent>}
|
|
* @protected
|
|
*/
|
|
this.targetPointers = [];
|
|
}
|
|
|
|
/**
|
|
* Returns the current number of pointers involved in the interaction,
|
|
* e.g. `2` when two fingers are used.
|
|
* @return {number} The number of pointers.
|
|
* @api
|
|
*/
|
|
getPointerCount() {
|
|
return this.targetPointers.length;
|
|
}
|
|
|
|
/**
|
|
* Handle pointer down events.
|
|
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Event.
|
|
* @return {boolean} If the event was consumed.
|
|
* @protected
|
|
*/
|
|
handleDownEvent(mapBrowserEvent) {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Handle pointer drag events.
|
|
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Event.
|
|
* @protected
|
|
*/
|
|
handleDragEvent(mapBrowserEvent) {}
|
|
|
|
/**
|
|
* Handles the {@link module:ol/MapBrowserEvent~MapBrowserEvent map browser event} and may call into
|
|
* other functions, if event sequences like e.g. 'drag' or 'down-up' etc. are
|
|
* detected.
|
|
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.
|
|
* @return {boolean} `false` to stop event propagation.
|
|
* @api
|
|
*/
|
|
handleEvent(mapBrowserEvent) {
|
|
if (!mapBrowserEvent.originalEvent) {
|
|
return true;
|
|
}
|
|
|
|
let stopEvent = false;
|
|
this.updateTrackedPointers_(mapBrowserEvent);
|
|
if (this.handlingDownUpSequence) {
|
|
if (mapBrowserEvent.type == MapBrowserEventType.POINTERDRAG) {
|
|
this.handleDragEvent(mapBrowserEvent);
|
|
// prevent page scrolling during dragging
|
|
mapBrowserEvent.originalEvent.preventDefault();
|
|
} else if (mapBrowserEvent.type == MapBrowserEventType.POINTERUP) {
|
|
const handledUp = this.handleUpEvent(mapBrowserEvent);
|
|
this.handlingDownUpSequence =
|
|
handledUp && this.targetPointers.length > 0;
|
|
}
|
|
} else {
|
|
if (mapBrowserEvent.type == MapBrowserEventType.POINTERDOWN) {
|
|
const handled = this.handleDownEvent(mapBrowserEvent);
|
|
this.handlingDownUpSequence = handled;
|
|
stopEvent = this.stopDown(handled);
|
|
} else if (mapBrowserEvent.type == MapBrowserEventType.POINTERMOVE) {
|
|
this.handleMoveEvent(mapBrowserEvent);
|
|
}
|
|
}
|
|
return !stopEvent;
|
|
}
|
|
|
|
/**
|
|
* Handle pointer move events.
|
|
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Event.
|
|
* @protected
|
|
*/
|
|
handleMoveEvent(mapBrowserEvent) {}
|
|
|
|
/**
|
|
* Handle pointer up events.
|
|
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Event.
|
|
* @return {boolean} If the event was consumed.
|
|
* @protected
|
|
*/
|
|
handleUpEvent(mapBrowserEvent) {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* This function is used to determine if "down" events should be propagated
|
|
* to other interactions or should be stopped.
|
|
* @param {boolean} handled Was the event handled by the interaction?
|
|
* @return {boolean} Should the `down` event be stopped?
|
|
*/
|
|
stopDown(handled) {
|
|
return handled;
|
|
}
|
|
|
|
/**
|
|
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Event.
|
|
* @private
|
|
*/
|
|
updateTrackedPointers_(mapBrowserEvent) {
|
|
if (isPointerDraggingEvent(mapBrowserEvent)) {
|
|
const event = mapBrowserEvent.originalEvent;
|
|
|
|
const id = event.pointerId.toString();
|
|
if (mapBrowserEvent.type == MapBrowserEventType.POINTERUP) {
|
|
delete this.trackedPointers_[id];
|
|
} else if (mapBrowserEvent.type == MapBrowserEventType.POINTERDOWN) {
|
|
this.trackedPointers_[id] = event;
|
|
} else if (id in this.trackedPointers_) {
|
|
// update only when there was a pointerdown event for this pointer
|
|
this.trackedPointers_[id] = event;
|
|
}
|
|
this.targetPointers = getValues(this.trackedPointers_);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {Array<PointerEvent>} pointerEvents List of events.
|
|
* @return {import("../pixel.js").Pixel} Centroid pixel.
|
|
*/
|
|
export function centroid(pointerEvents) {
|
|
const length = pointerEvents.length;
|
|
let clientX = 0;
|
|
let clientY = 0;
|
|
for (let i = 0; i < length; i++) {
|
|
clientX += pointerEvents[i].clientX;
|
|
clientY += pointerEvents[i].clientY;
|
|
}
|
|
return [clientX / length, clientY / length];
|
|
}
|
|
|
|
/**
|
|
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Event.
|
|
* @return {boolean} Whether the event is a pointerdown, pointerdrag
|
|
* or pointerup event.
|
|
*/
|
|
function isPointerDraggingEvent(mapBrowserEvent) {
|
|
const type = mapBrowserEvent.type;
|
|
return (
|
|
type === MapBrowserEventType.POINTERDOWN ||
|
|
type === MapBrowserEventType.POINTERDRAG ||
|
|
type === MapBrowserEventType.POINTERUP
|
|
);
|
|
}
|
|
|
|
export default PointerInteraction;
|