import { Control } from "ol/control"; import { DragPan } from "ol/interaction"; import { unByKey } from "ol/Observable"; import type { Map, MapBrowserEvent } from "ol"; import type { Options } from "ol/control/Control"; import type { EventsKey } from "ol/events"; export type DragPanWarningOptions = { className?: string; element?: HTMLElement; } & Options; class DragPanWarning extends Control { dragPan?: DragPan; icon: HTMLDivElement; onPointerDragRef?: EventsKey; text: HTMLParagraphElement; constructor(options: DragPanWarningOptions = {}) { let element = options.element; if (!element) { element = document.createElement("div"); element.className = options.className !== undefined ? options.className : "ol-drag-pan-warning"; } element.style.display = "none"; element.style.pointerEvents = "auto"; super({ element, render: options.render, target: options.target, }); if (!options.element) { this.icon = document.createElement("div"); this.icon.className = `${element.className}-icon`; // sbb icons: sbb/two-finger-tap-large.svg'; this.icon.innerHTML = ` `; this.element.appendChild(this.icon); this.text = document.createElement("p"); this.text.className = `${element.className}-text`; this.text.innerHTML = "Benutzen Sie 2 Finger um die Karte zu bedienen."; this.element.appendChild(this.text); } this.dragPan = undefined; this.onPointerDragRef = undefined; this.onPointerDrag = this.onPointerDrag.bind(this); this.onTouchEnd = this.onTouchEnd.bind(this); } onPointerDrag(event: MapBrowserEvent) { // Show the warning on next pointerdrag events. if (event.activePointers?.length !== 1) { return true; } this.element.style.display = "flex"; document.addEventListener("touchend", this.onTouchEnd, { once: true }); return false; } onTouchEnd() { unByKey(this.onPointerDragRef); this.element.style.display = "none"; } setMap(map: Map) { super.setMap(map); document.removeEventListener("touchend", this.onTouchEnd); unByKey(this.onPointerDragRef); if (map) { const viewport = map.getViewport(); // We allow default scroll behavior for touch events. viewport.style.touchAction = "pan-x pan-y"; // Deactivate drag pan only on touch events. this.dragPan = map .getInteractions() .getArray() .find((interaction) => { return interaction instanceof DragPan; }); if (!this.dragPan) { // eslint-disable-next-line no-console console.error( "Impossible to find the DragPan interaction, DragPanWarning will not work as expected.", ); return; } this.listenerKeys.push( // @ts-expect-error - we need to listen to pointerdown events map.on("pointerdown", (evt: MapBrowserEvent) => { document.removeEventListener("touchend", this.onTouchEnd); if ( evt.originalEvent.pointerType !== "touch" || // @ts-expect-error - condition_ is a private method !this.dragPan?.condition_(evt) ) { this.element.style.display = "none"; return true; } this.onPointerDragRef = map.on("pointerdrag", this.onPointerDrag); return true; }), ); this.element.addEventListener("click", this.onTouchEnd); } } } export default DragPanWarning;