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;