1
0
Fork 0
mirror of https://github.com/mozilla/pdf.js.git synced 2025-04-19 14:48:08 +02:00

Move the pinch stuff in its own file in order to use for editors

This commit is contained in:
Calixte Denizet 2024-12-11 16:41:35 +01:00
parent a9c5bb25b8
commit e0b63ecd03
5 changed files with 233 additions and 123 deletions

View file

@ -54,6 +54,7 @@ import {
PDFWorker,
shadow,
stopEvent,
TouchManager,
UnexpectedResponseException,
version,
} from "pdfjs-lib";
@ -94,14 +95,6 @@ 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.
@ -182,14 +175,13 @@ const PDFViewerApplication = {
_saveInProgress: false,
_wheelUnusedTicks: 0,
_wheelUnusedFactor: 1,
_touchManager: null,
_touchUnusedTicks: 0,
_touchUnusedFactor: 1,
_PDFBug: null,
_hasAnnotationEditors: false,
_title: document.title,
_printAnnotationStoragePromise: null,
_touchInfo: null,
_isPinching: false,
_isCtrlKeyDown: false,
_caretBrowsing: null,
_isScrolling: false,
@ -825,6 +817,29 @@ const PDFViewerApplication = {
this.pdfViewer.currentScaleValue = DEFAULT_SCALE_VALUE;
},
touchPinchCallback(origin, prevDistance, distance) {
if (this.supportsPinchToZoom) {
const newScaleFactor = this._accumulateFactor(
this.pdfViewer.currentScale,
distance / prevDistance,
"_touchUnusedFactor"
);
this.updateZoom(null, newScaleFactor, origin);
} else {
const PIXELS_PER_LINE_SCALE = 30;
const ticks = this._accumulateTicks(
(distance - prevDistance) / PIXELS_PER_LINE_SCALE,
"_touchUnusedTicks"
);
this.updateZoom(ticks, null, origin);
}
},
touchPinchEndCallback() {
this._touchUnusedTicks = 0;
this._touchUnusedFactor = 1;
},
get pagesCount() {
return this.pdfDocument ? this.pdfDocument.numPages : 0;
},
@ -2029,6 +2044,15 @@ const PDFViewerApplication = {
_windowAbortController: { signal },
} = this;
this._touchManager = new TouchManager({
container: window,
isPinchingDisabled: () => this.pdfViewer.isInPresentationMode,
isPinchingStopped: () => this.overlayManager?.active,
onPinching: this.touchPinchCallback.bind(this),
onPinchEnd: this.touchPinchEndCallback.bind(this),
signal,
});
function addWindowResolutionChange(evt = null) {
if (evt) {
pdfViewer.refresh();
@ -2047,18 +2071,6 @@ const PDFViewerApplication = {
passive: false,
signal,
});
window.addEventListener("touchstart", onTouchStart.bind(this), {
passive: false,
signal,
});
window.addEventListener("touchmove", onTouchMove.bind(this), {
passive: false,
signal,
});
window.addEventListener("touchend", onTouchEnd.bind(this), {
passive: false,
signal,
});
window.addEventListener("click", onClick.bind(this), { signal });
window.addEventListener("keydown", onKeyDown.bind(this), { signal });
window.addEventListener("keyup", onKeyUp.bind(this), { signal });
@ -2157,6 +2169,7 @@ const PDFViewerApplication = {
unbindWindowEvents() {
this._windowAbortController?.abort();
this._windowAbortController = null;
this._touchManager = null;
},
/**
@ -2638,107 +2651,6 @@ function onWheel(evt) {
}
}
function onTouchStart(evt) {
if (this.pdfViewer.isInPresentationMode || evt.touches.length < 2) {
return;
}
evt.preventDefault();
if (evt.touches.length !== 2 || this.overlayManager.active) {
this._touchInfo = null;
return;
}
let [touch0, touch1] = evt.touches;
if (touch0.identifier > touch1.identifier) {
[touch0, touch1] = [touch1, touch0];
}
this._touchInfo = {
touch0X: touch0.screenX,
touch0Y: touch0.screenY,
touch1X: touch1.screenX,
touch1Y: touch1.screenY,
};
}
function onTouchMove(evt) {
if (!this._touchInfo || evt.touches.length !== 2) {
return;
}
const { pdfViewer, _touchInfo, supportsPinchToZoom } = this;
let [touch0, touch1] = evt.touches;
if (touch0.identifier > touch1.identifier) {
[touch0, touch1] = [touch1, touch0];
}
const { screenX: screen0X, screenY: screen0Y } = touch0;
const { screenX: screen1X, screenY: screen1Y } = touch1;
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 (
!this._isPinching &&
Math.abs(pDistance - distance) <= MIN_TOUCH_DISTANCE_TO_PINCH
) {
return;
}
_touchInfo.touch0X = screen0X;
_touchInfo.touch0Y = screen0Y;
_touchInfo.touch1X = screen1X;
_touchInfo.touch1Y = screen1Y;
evt.preventDefault();
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,
distance / pDistance,
"_touchUnusedFactor"
);
this.updateZoom(null, newScaleFactor, origin);
} else {
const PIXELS_PER_LINE_SCALE = 30;
const ticks = this._accumulateTicks(
(distance - pDistance) / PIXELS_PER_LINE_SCALE,
"_touchUnusedTicks"
);
this.updateZoom(ticks, null, origin);
}
}
function onTouchEnd(evt) {
if (!this._touchInfo) {
return;
}
evt.preventDefault();
this._touchInfo = null;
this._touchUnusedTicks = 0;
this._touchUnusedFactor = 1;
this._isPinching = false;
}
function closeSecondaryToolbar(evt) {
if (!this.secondaryToolbar?.isOpen) {
return;