Skip to content

Commit

Permalink
Enhance PanAndZoom with touch support for pinch zoom and single-finge…
Browse files Browse the repository at this point in the history
…r pan (#71)

* Enhance PanAndZoom with touch support for pinch zoom and single-finger pan

* npm run format

* Fix null handling and adjust handle_zoom signature
  • Loading branch information
sago35 authored Jan 11, 2024
1 parent bcfd612 commit 5c38d14
Showing 1 changed file with 60 additions and 6 deletions.
66 changes: 60 additions & 6 deletions src/base/dom/pan-and-zoom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,59 @@ export class PanAndZoom {
(e: WheelEvent) => this.#on_wheel(e),
{ passive: false },
);

let startDistance: number | null = null;
let startPosition: TouchList | null = null;

this.target.addEventListener("touchstart", (e: TouchEvent) => {
if (e.touches.length === 2) {
startDistance = this.#getDistanceBetweenTouches(e.touches);
} else if (e.touches.length === 1) {
startPosition = e.touches;
}
});

this.target.addEventListener("touchmove", (e: TouchEvent) => {
if (e.touches.length === 2) {
if (startDistance !== null) {
const currentDistance = this.#getDistanceBetweenTouches(
e.touches,
);
if (Math.abs(startDistance - currentDistance) < 10) {
const scale = (currentDistance / startDistance) * 4;
if (startDistance < currentDistance) {
this.#handle_zoom(scale * -1);
} else {
this.#handle_zoom(scale);
}
}
startDistance = currentDistance;
}
} else if (e.touches.length === 1 && startPosition !== null) {
const sx = startPosition[0]?.clientX ?? 0;
const sy = startPosition[0]?.clientY ?? 0;
const ex = e.touches[0]?.clientX ?? 0;
const ey = e.touches[0]?.clientY ?? 0;
if (Math.abs(sx - ex) < 100 && Math.abs(sy - ey) < 100) {
this.#handle_pan(sx - ex, sy - ey);
}
startPosition = e.touches;
}
});

this.target.addEventListener("touchend", () => {
startDistance = null;
startPosition = null;
});
}

#getDistanceBetweenTouches(touches: TouchList) {
if (touches[0] && touches[1]) {
const dx = touches[0].clientX - touches[1].clientX;
const dy = touches[0].clientY - touches[1].clientY;
return Math.sqrt(dx * dx + dy * dy);
}
return 0;
}

#on_wheel(e: WheelEvent) {
Expand Down Expand Up @@ -109,19 +162,20 @@ export class PanAndZoom {
}
}

#handle_zoom(delta: number, mouse: Vec2) {
const mouse_world = this.camera.screen_to_world(mouse);

#handle_zoom(delta: number, mouse?: Vec2) {
this.camera.zoom *= Math.exp(delta * -zoom_speed);
this.camera.zoom = Math.min(
this.max_zoom,
Math.max(this.camera.zoom, this.min_zoom),
);

const new_world = this.camera.screen_to_world(mouse);
const center_delta = mouse_world.sub(new_world);
if (mouse != null) {
const mouse_world = this.camera.screen_to_world(mouse);
const new_world = this.camera.screen_to_world(mouse);
const center_delta = mouse_world.sub(new_world);

this.camera.translate(center_delta);
this.camera.translate(center_delta);
}

if (this.callback) {
this.callback();
Expand Down

0 comments on commit 5c38d14

Please sign in to comment.