Zoom page with mouse wheel, click and drag to pan

1.7k Views Asked by At

How would I go about making a scroll-and-pan effect with the mouse wheel for the entire page? Basically like any 2D editor with the scroll to zoom, click and drag to pan but for the entire body.

I haven't been able to find anything online about it.

2

There are 2 best solutions below

0
vsync On

If you don't know where to start, you will very soon hit another wall, because knowing where to start is the easy part. Here is a rough guide:

  1. Add event listener to the wheel event (learn how](https://stackoverflow.com/a/51276012/104380))
  2. Start with an initial (current) zoom value and calculate the delta from the wheel event and update your zoom value.
  3. Use the zoom value to manipulate the scale of the page in some form. You can use CSS transform: scale() for that, on the body element.
  4. Add event listener for the mousemove event (learn how](https://developer.mozilla.org/en-US/docs/Web/API/Element/mousemove_event))
  5. Act upon the detected mouse move, and calculate how much you need to pan the zoomed body element in order to reach any of the 4 edges, and not beyond. panning may be done via CSS transform: translate(x,y)
0
Seth Alexander On

Implementation I made based off of vsyncs answer:

window.onload = init;

let root;
let content;
let zoom = 1.0;
let translateY = 0;
let translateX = 0;
let middleMouseDown = false;

function init(){
    content = document.getElementById("content");
    root = document.getElementById("root");

    root.addEventListener("wheel", (event)=>{
        zoom += event.wheelDelta / 1000;
        if(zoom > 2.0){zoom = 2.0}
        else if (zoom < 0.5) {zoom = 0.5}
        console.log(zoom);

        transform();
    })
    
    root.addEventListener("mousedown", (event)=>{
        event.preventDefault();
        middleMouseDown = (event.button == 1);
    })

    root.addEventListener("mouseup", (event)=>{
        if(event.button == 1){
            middleMouseDown = false;
        }
    })

    root.addEventListener("mousemove", (event)=>{
        // console.log(event);
        if(middleMouseDown){
            translateY += event.movementY;
            translateX += event.movementX;
            transform();
        }
    })
}

function transform(){
    content.style.transform = `scale(${zoom}, ${zoom}) translate(${translateX}px, ${translateY}px)`;
}
body{
    margin: 0px;
}

#root{
    width: 400px;
    height: 400px;
    border: 1px solid red;
    overflow: scroll;
}

#content{
    width: 200px;
    height: 200px;
    border: 1px solid black;
}
<html lang="en">
    <head>
        <link rel="stylesheet" href="index.css">
        <script src="main.js"></script>
    </head>
    <body>
        <div id="root">
            <div id="content">
            </div>
        </div>
    </body>

</html>