Skip to content

Instantly share code, notes, and snippets.

@larsneo
Forked from jsprpalm/viewer.html
Last active July 24, 2024 03:15
Show Gist options
  • Save larsneo/bb75616e9426ae589f50e8c8411020f6 to your computer and use it in GitHub Desktop.
Save larsneo/bb75616e9426ae589f50e8c8411020f6 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 });
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>
@meghrathod
Copy link

Hence the final code should be this:

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 });
    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("DOMContentLoaded", () => {
    if (!pinchZoomEnabled) {
        pinchZoomEnabled = true;
        enablePinchZoom();
    }
});

It can be placed in a file called zoom.js and you can just add this line before the final </body> tag in viewer.html file in the web folder.

<body>
    ---
    ---
    <script src="zoom.js"></script>
</body>

@yc-cui
Copy link

yc-cui commented Aug 15, 2022

Is this just suitable for viewer.html? Can I utilize it within my customed viewer? Like a viewer in a div using canvas backend?

@sergiobellini
Copy link

sergiobellini commented Sep 13, 2022

Unfortunately pinch-to-zoom doesn't work if I put the viewer in an iframe :( Is there any kind of solution?

@meghrathod
Copy link

Is this just suitable for viewer.html? Can I utilize it within my customed viewer? Like a viewer in a div using canvas backend?

I think it should work but you would have to make appropriate changes as required by the back end that you make.

@azazel404
Copy link

hello guys , when i implement and test it on my application ,it doesn't work

@duandre
Copy link

duandre commented Apr 15, 2023

Thank you @meghrathod - It's working for BlazorWebView in MAUI Blazor

@mazhewei
Copy link

hi guys, if you use modern browser, please upgrade pdfjs to latest version or the supported version(version >=3.3.122, for more info see this PR), pdfjs now support pinch-to-zoom feature.
if unfortunately, not use modern browser(for example, you have to use pdfjs version v2.x), this code work perfectly!

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