Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify the code to zoom in using a pinch gesture #19124

Merged
merged 1 commit into from
Nov 29, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 38 additions & 52 deletions web/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,14 @@ import { ViewHistory } from "./view_history.js";

const FORCE_PAGES_LOADED_TIMEOUT = 10000; // ms

// The 35 is coming from:
// https://searchfox.org/mozilla-central/source/gfx/layers/apz/src/GestureEventListener.cpp#36
//
// The properties TouchEvent::screenX/Y are in screen CSS pixels:
// https://developer.mozilla.org/en-US/docs/Web/API/Touch/screenX#examples
// MIN_TOUCH_DISTANCE_TO_PINCH is in CSS pixels.
const MIN_TOUCH_DISTANCE_TO_PINCH = 35 / (window.devicePixelRatio || 1);

const ViewOnLoad = {
UNKNOWN: -1,
PREVIOUS: 0, // Default value.
Expand Down Expand Up @@ -179,6 +187,7 @@ const PDFViewerApplication = {
_title: document.title,
_printAnnotationStoragePromise: null,
_touchInfo: null,
_isPinching: false,
_isCtrlKeyDown: false,
_caretBrowsing: null,
_isScrolling: false,
Expand Down Expand Up @@ -2639,10 +2648,10 @@ function onTouchStart(evt) {
[touch0, touch1] = [touch1, touch0];
}
this._touchInfo = {
touch0X: touch0.pageX,
touch0Y: touch0.pageY,
touch1X: touch1.pageX,
touch1Y: touch1.pageY,
touch0X: touch0.screenX,
touch0Y: touch0.screenY,
touch1X: touch1.screenX,
touch1Y: touch1.screenY,
};
}

Expand All @@ -2656,69 +2665,45 @@ function onTouchMove(evt) {
if (touch0.identifier > touch1.identifier) {
[touch0, touch1] = [touch1, touch0];
}
const { pageX: page0X, pageY: page0Y } = touch0;
const { pageX: page1X, pageY: page1Y } = touch1;
const { screenX: screen0X, screenY: screen0Y } = touch0;
const { screenX: screen1X, screenY: screen1Y } = touch1;
calixteman marked this conversation as resolved.
Show resolved Hide resolved
const {
touch0X: pTouch0X,
touch0Y: pTouch0Y,
touch1X: pTouch1X,
touch1Y: pTouch1Y,
} = _touchInfo;

const prevGapX = pTouch1X - pTouch0X;
const prevGapY = pTouch1Y - pTouch0Y;
const currGapX = screen1X - screen0X;
const currGapY = screen1Y - screen0Y;

const distance = Math.hypot(currGapX, currGapY) || 1;
const pDistance = Math.hypot(prevGapX, prevGapY) || 1;
if (
Math.abs(pTouch0X - page0X) <= 1 &&
Math.abs(pTouch0Y - page0Y) <= 1 &&
Math.abs(pTouch1X - page1X) <= 1 &&
Math.abs(pTouch1Y - page1Y) <= 1
!this._isPinching &&
Math.abs(pDistance - distance) <= MIN_TOUCH_DISTANCE_TO_PINCH
) {
// Touches are really too close and it's hard do some basic
// geometry in order to guess something.
return;
}

_touchInfo.touch0X = page0X;
_touchInfo.touch0Y = page0Y;
_touchInfo.touch1X = page1X;
_touchInfo.touch1Y = page1Y;

if (pTouch0X === page0X && pTouch0Y === page0Y) {
// First touch is fixed, if the vectors are collinear then we've a pinch.
const v1X = pTouch1X - page0X;
const v1Y = pTouch1Y - page0Y;
const v2X = page1X - page0X;
const v2Y = page1Y - page0Y;
const det = v1X * v2Y - v1Y * v2X;
// 0.02 is approximatively sin(0.15deg).
if (Math.abs(det) > 0.02 * Math.hypot(v1X, v1Y) * Math.hypot(v2X, v2Y)) {
return;
}
} else if (pTouch1X === page1X && pTouch1Y === page1Y) {
// Second touch is fixed, if the vectors are collinear then we've a pinch.
const v1X = pTouch0X - page1X;
const v1Y = pTouch0Y - page1Y;
const v2X = page0X - page1X;
const v2Y = page0Y - page1Y;
const det = v1X * v2Y - v1Y * v2X;
if (Math.abs(det) > 0.02 * Math.hypot(v1X, v1Y) * Math.hypot(v2X, v2Y)) {
return;
}
} else {
const diff0X = page0X - pTouch0X;
const diff1X = page1X - pTouch1X;
const diff0Y = page0Y - pTouch0Y;
const diff1Y = page1Y - pTouch1Y;
const dotProduct = diff0X * diff1X + diff0Y * diff1Y;
if (dotProduct >= 0) {
// The two touches go in almost the same direction.
return;
}
}
_touchInfo.touch0X = screen0X;
_touchInfo.touch0Y = screen0Y;
_touchInfo.touch1X = screen1X;
_touchInfo.touch1Y = screen1Y;

evt.preventDefault();

const origin = [(page0X + page1X) / 2, (page0Y + page1Y) / 2];
const distance = Math.hypot(page0X - page1X, page0Y - page1Y) || 1;
const pDistance = Math.hypot(pTouch0X - pTouch1X, pTouch0Y - pTouch1Y) || 1;
if (!this._isPinching) {
// Start pinching.
this._isPinching = true;

// We return here else the first pinch is a bit too much
return;
}

const origin = [(screen0X + screen1X) / 2, (screen0Y + screen1Y) / 2];
if (supportsPinchToZoom) {
const newScaleFactor = this._accumulateFactor(
pdfViewer.currentScale,
Expand All @@ -2745,6 +2730,7 @@ function onTouchEnd(evt) {
this._touchInfo = null;
this._touchUnusedTicks = 0;
this._touchUnusedFactor = 1;
this._isPinching = false;
}

function onClick(evt) {
Expand Down