Skip to content

Commit

Permalink
[Editor] Improve zooming with a pinch gesture while drawing
Browse files Browse the repository at this point in the history
It lets the user make a pinch gesture with a finger on page with a drawing
and the second finger on an other page.
On mobile, it's pretty easy to be in such a situation.
  • Loading branch information
calixteman committed Jan 9, 2025
1 parent f1166f4 commit 5ac0eb0
Showing 1 changed file with 53 additions and 12 deletions.
65 changes: 53 additions & 12 deletions src/display/touch_manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ class TouchManager {

#onPinchEnd;

#pointerDownAC = null;

#signal;

#touchInfo = null;
Expand Down Expand Up @@ -78,26 +80,61 @@ class TouchManager {
}

#onTouchStart(evt) {
if (this.#isPinchingDisabled?.() || evt.touches.length < 2) {
if (this.#isPinchingDisabled?.()) {
return;
}

if (evt.touches.length === 1) {
const pointerDownAC = (this.#pointerDownAC = new AbortController());
const signal = AbortSignal.any([this.#signal, pointerDownAC.signal]);
const container = this.#container;

// We want to have the events at the capture phase to make sure we can
// cancel them.
const opts = { capture: true, signal, passive: false };
const cancelPointerDown = e => {
if (e.pointerType === "touch") {
this.#pointerDownAC.abort();
this.#pointerDownAC = null;
}
};
container.addEventListener(
"pointerdown",
e => {
if (e.pointerType === "touch") {
// This is the second finger so we don't want it select something
// or whatever.
stopEvent(e);
cancelPointerDown(e);
}
},
opts
);
container.addEventListener("pointerup", cancelPointerDown, opts);
container.addEventListener("pointercancel", cancelPointerDown, opts);
return;
}

if (!this.#touchMoveAC) {
this.#touchMoveAC = new AbortController();
const signal = AbortSignal.any([this.#signal, this.#touchMoveAC.signal]);
const container = this.#container;
const opt = { signal, passive: false };

const opt = { signal, capture: false, passive: false };
container.addEventListener(
"touchmove",
this.#onTouchMove.bind(this),
opt
);
container.addEventListener("touchend", this.#onTouchEnd.bind(this), opt);
container.addEventListener(
"touchcancel",
this.#onTouchEnd.bind(this),
opt
);
const onTouchEnd = this.#onTouchEnd.bind(this);
container.addEventListener("touchend", onTouchEnd, opt);
container.addEventListener("touchcancel", onTouchEnd, opt);

opt.capture = true;
container.addEventListener("pointerdown", stopEvent, opt);
container.addEventListener("pointermove", stopEvent, opt);
container.addEventListener("pointercancel", stopEvent, opt);
container.addEventListener("pointerup", stopEvent, opt);
this.#onPinchStart?.();
}

Expand Down Expand Up @@ -125,6 +162,8 @@ class TouchManager {
return;
}

stopEvent(evt);

let [touch0, touch1] = evt.touches;
if (touch0.identifier > touch1.identifier) {
[touch0, touch1] = [touch1, touch0];
Expand Down Expand Up @@ -158,8 +197,6 @@ class TouchManager {
touchInfo.touch1X = screen1X;
touchInfo.touch1Y = screen1Y;

evt.preventDefault();

if (!this.#isPinching) {
// Start pinching.
this.#isPinching = true;
Expand All @@ -173,22 +210,26 @@ class TouchManager {
}

#onTouchEnd(evt) {
if (evt.touches.length >= 2) {
return;
}
this.#touchMoveAC.abort();
this.#touchMoveAC = null;
this.#onPinchEnd?.();

if (!this.#touchInfo) {
return;
}

evt.preventDefault();
stopEvent(evt);
this.#touchInfo = null;
this.#isPinching = false;
}

destroy() {
this.#touchManagerAC?.abort();
this.#touchManagerAC = null;
this.#pointerDownAC?.abort();
this.#pointerDownAC = null;
}
}

Expand Down

0 comments on commit 5ac0eb0

Please sign in to comment.