Skip to content

Instantly share code, notes, and snippets.

@jsprpalm
Created May 23, 2019 12:25
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save jsprpalm/12217feab2f1acc14bd8e8508291619e to your computer and use it in GitHub Desktop.
Save jsprpalm/12217feab2f1acc14bd8e8508291619e to your computer and use it in GitHub Desktop.
Pinch zoom implementation for PDF.js viewer
<!-- Goes into viewer.html just before ending </body> -->
<script>
let pinchZoomEnabled = false;
function enablePinchZoom(pdfViewer) {
let startX = 0, startY = 0;
let initialPinchDistance = 0;
let pinchScale = 1;
const viewer = document.getElementById("viewer");
const container = document.getElementById("viewerContainer");
const reset = () => { startX = startY = initialPinchDistance = 0; pinchScale = 1; };
// Prevent native iOS page zoom
document.addEventListener("touchmove", (e) => { if (e.scale !== 1) { e.preventDefault(); } }, { passive: false });
viewer.addEventListener("touchstart", (e) => {
if (e.touches.length > 1) {
startX = (e.touches[0].pageX + e.touches[1].pageX) / 2;
startY = (e.touches[0].pageY + e.touches[1].pageY) / 2;
initialPinchDistance = Math.hypot((e.touches[1].pageX - e.touches[0].pageX), (e.touches[1].pageY - e.touches[0].pageY));
} else {
initialPinchDistance = 0;
}
});
viewer.addEventListener("touchmove", (e) => {
if (initialPinchDistance <= 0 || e.touches.length < 2) { return; }
const pinchDistance = Math.hypot((e.touches[1].pageX - e.touches[0].pageX), (e.touches[1].pageY - e.touches[0].pageY));
const originX = startX + container.scrollLeft;
const originY = startY + container.scrollTop;
pinchScale = pinchDistance / initialPinchDistance;
viewer.style.transform = `scale(${pinchScale})`;
viewer.style.transformOrigin = `${originX}px ${originY}px`;
});
viewer.addEventListener("touchend", (e) => {
if (initialPinchDistance <= 0) { return; }
viewer.style.transform = `none`;
viewer.style.transformOrigin = `unset`;
PDFViewerApplication.pdfViewer.currentScale *= pinchScale;
const rect = container.getBoundingClientRect();
const dx = startX - rect.left;
const dy = startY - rect.top;
container.scrollLeft += dx * (pinchScale - 1);
container.scrollTop += dy * (pinchScale - 1);
reset();
});
}
document.addEventListener('webviewerloaded', () => {
if (!pinchZoomEnabled) {
pinchZoomEnabled = true;
enablePinchZoom();
}
});
</script>
@MickLesk
Copy link

@rodgaldeano i dont know what you mean with

adding the code in line 13 to the corresponding event.

I use xF 4.2 and i cant swipe pages

@larsneo
Copy link

larsneo commented Nov 7, 2019

guess this means instead of line 13 add the stuff in the corresponding touchmove-function

       document.addEventListener("touchmove", (e) => {
            if (initialPinchDistance <= 0 || e.touches.length < 2) { return; }
            if (e.scale !== 1) { e.preventDefault(); }
            const pinchDistance = Math.hypot((e.touches[1].pageX - e.touches[0].pageX), (e.touches[1].pageY - e.touches[0].pageY));
            const originX = startX + container.scrollLeft;
            const originY = startY + container.scrollTop;
            pinchScale = pinchDistance / initialPinchDistance;
            viewer.style.transform = `scale(${pinchScale})`;
            viewer.style.transformOrigin = `${originX}px ${originY}px`;
        }, { passive: false });

@aidrouge
Copy link

aidrouge commented Nov 8, 2019

@larsneo thank you so so so much its working prefectly now

<script> let pinchZoomEnabled = false; function enablePinchZoom(pdfViewer) { let startX = 0, startY = 0; let initialPinchDistance = 0; let pinchScale = 1; const viewer = document.getElementById("viewer"); const container = document.getElementById("viewerContainer"); const reset = () => { startX = startY = initialPinchDistance = 0; pinchScale = 1; }; // Prevent native iOS page zoom document.addEventListener("touchstart", (e) => { if (e.touches.length > 1) { startX = (e.touches[0].pageX + e.touches[1].pageX) / 2; startY = (e.touches[0].pageY + e.touches[1].pageY) / 2; initialPinchDistance = Math.hypot((e.touches[1].pageX - e.touches[0].pageX), (e.touches[1].pageY - e.touches[0].pageY)); } else { initialPinchDistance = 0; } }); document.addEventListener("touchmove", (e) => { if (initialPinchDistance <= 0 || e.touches.length < 2) { return; } if (e.scale !== 1) { e.preventDefault(); } const pinchDistance = Math.hypot((e.touches[1].pageX - e.touches[0].pageX), (e.touches[1].pageY - e.touches[0].pageY)); const originX = startX + container.scrollLeft; const originY = startY + container.scrollTop; pinchScale = pinchDistance / initialPinchDistance; viewer.style.transform = `scale(${pinchScale})`; viewer.style.transformOrigin = `${originX}px ${originY}px`; }, { passive: false }); document.addEventListener("touchend", (e) => { if (initialPinchDistance <= 0) { return; } viewer.style.transform = `none`; viewer.style.transformOrigin = `unset`; PDFViewerApplication.pdfViewer.currentScale *= pinchScale; const rect = container.getBoundingClientRect(); const dx = startX - rect.left; const dy = startY - rect.top; container.scrollLeft += dx * (pinchScale - 1); container.scrollTop += dy * (pinchScale - 1); reset(); }); } document.addEventListener('webviewerloaded', () => { if (!pinchZoomEnabled) { pinchZoomEnabled = true; enablePinchZoom(); } }); </script>

@larsneo
Copy link

larsneo commented Nov 8, 2019

my pleasure, complete code also forked at https://gist.github.com/larsneo/bb75616e9426ae589f50e8c8411020f6

@cepm-nate
Copy link

cepm-nate commented Apr 13, 2021

This works well for zooming, but seems to disable the normal drag-on-finger-to-pan action because of line 13. If I change the condition to be e.touches.length > 1 && e.scale !== 1, then it seems to work without problem on Android.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment