skip to Main Content

i want to limit the bound of my image while panning, thus, the left of the image should not go beyond the left edge of the container when panning from left to right and the right edge of the image should not go beyond the right of the container when panning from right to left. At a smaller scale, the boundary condition in the code works, but at a larger scale, the boundary condition does not work and I can’t figure out where the problem is.

// ------------------- Zoom and pan the image ------------------------------
var scale = 1,
panning = false,
pointX = 0,
pointY = 0,
mid_x = 0,
mid_y = 0,
start = { x: 0, y: 0 },
zoommap = document.getElementById("immagine");
let newPointX, newPointY;

// Mouse down || touchstart
((zoommap, event_names, zoom_start) => {
    event_names.forEach( (event_name) => {
        zoommap.addEventListener(event_name, zoom_start)
    })
})(zoommap, ['mousedown', 'touchstart'], (e) => {
    e.preventDefault();
    panning = true;
    if (e.type == 'mousedown'){
        start = { x: e.clientX - pointX, y: e.clientY - pointY };
    } 
    else if (e.type == 'touchstart'){
        if (e.touches.length === 1){
            start = { x: e.touches[0].clientX - pointX, y: e.touches[0].clientY - pointY};          
        } else if (e.touches.length === 2){
            start = { x: (e.touches[0].clientX + e.touches[1].clientX) / 2 - pointX, 
                y: (e.touches[0].clientY + e.touches[1].clientY) / 2 - pointY,
                dist: Math.hypot(e.touches[0].clientX - e.touches[1].clientX, e.touches[0].clientY - e.touches[1].clientY)
            };
        }
    }
});

// Mouse up || touchend
((zoommap, event_names, zoom_end) => {
    event_names.forEach( (event_name) => {
        zoommap.addEventListener(event_name, zoom_end)
    })
})(zoommap, ['mouseup', 'touchend', 'touchcancel'], (e) => {
    panning = false;
});

// Mouse move || touchmove || Panning the image
((zoommap, event_names, zoom_end) => {
    event_names.forEach( (event_name) => {
        zoommap.addEventListener(event_name, zoom_end)
    })
})(zoommap, ['mousemove', 'touchmove'], (e) => {
    e.preventDefault();
    if (!panning || scale === 1) {
        return;
    }

    if (e.type == 'mousemove'){

        newPointY = (e.clientY - start.y);
        newPointX = (e.clientX - start.x);

    } else if (e.type == 'touchmove'){
        if (e.touches.length === 1){
            newPointX = (e.touches[0].clientX - start.x);
            newPointY = (e.touches[0].clientY - start.y);
        }       
    }

    var mapimg_div = document.getElementById("mapimg");
    const map_dim = mapimg_div.getBoundingClientRect();
    const img_dim = zoommap.getBoundingClientRect();

    console.log(scale)
    // Calculate the maximum allowed positions
    const maxX = map_dim.left + (img_dim.width * scale - map_dim.width)/scale - map_dim.right;
    const maxY = map_dim.top + (img_dim.height * scale - map_dim.bottom)/scale - map_dim.height;
    const minX = map_dim.right - img_dim.width*scale - map_dim.left + map_dim.width; // Adjusted to allow intersection
    const minY = map_dim.bottom - img_dim.height*scale - map_dim.top + map_dim.height; // Adjusted to allow intersection

    // Clamp the new positions to stay within the boundaries
    if (newPointX > maxX) {
        newPointX = maxX;
    } else if (newPointX < minX) {
        newPointX = minX;
    }

    if (newPointY > maxY) {
        newPointY = maxY;
    } else if (newPointY < minY) {
        newPointY = minY;
    }

    // Update pointX and pointY with the new values
    pointX = newPointX;
    pointY = newPointY;

    zoommap.style.transform = "translate(" + pointX + "px, " + pointY + "px) scale(" + scale + ")"; 
});

//Zooming functionality
((zoommap, event_names, zoom_move) => {
    event_names.forEach( (event_name) => {
        zoommap.addEventListener(event_name, zoom_move)
    })
})(zoommap, ['mousewheel', 'touchmove'], (e) => {
    e.preventDefault();
    zoommap.style.transform = "none";
    var img_dim = zoommap.getBoundingClientRect();

    if (e.type == 'mousewheel'){
        var x = ((img_dim.width - (img_dim.right- e.clientX ))/img_dim.width) * 100; //x position within the img element
        var y = ((img_dim.height - (img_dim.bottom- e.clientY))/img_dim.height) * 100; //y position within the img element
        zoommap.style.transformOrigin = x + "% " + y + "%";
        var delta = (e.wheelDelta ? e.wheelDelta : -e.deltaY);
        (delta > 0) ? (scale *= 1.2) : (scale /= 1.2);
    } else if (e.type == 'touchmove'){
        if (e.touches.length == 2){

            if (e.scale) {
                scale = e.scale;
            } else {
                var move_dist = Math.hypot(e.touches[0].clientX - e.touches[1].clientX, e.touches[0].clientY - e.touches[1].clientY);
                (move_dist > start.dist) ? (scale *= 1.01) : (scale /= 1.01);
            } 

            // Calculate how much the fingers have moved on the X and Y axis
              var x = ((img_dim.width - (img_dim.right- mid_x ))/img_dim.width) * 100; 
              var y = ((img_dim.height - (img_dim.bottom- mid_y))/img_dim.height) * 100; 
              zoommap.style.transformOrigin = x + "% " + y + "%";
              mid_x = ( + e.touches[1].clientX) / 2
              mid_y = (e.touches[0].clientY + e.touches[1].clientY) / 2
              pointX = (mid_x - start.x);
              pointY = (mid_y - start.y);
            }
        }

        scale = Math.min(Math.max(1, scale), 20);
        pointX = 0;
        pointY = 0;
        zoommap.style.transform = "scale(" + scale + ") translate(" + pointX + "px, " + pointY + "px)";
    });

2

Answers


  1. Try This Code:

    ((zoommap, event_names, zoom_move) => {
        event_names.forEach((event_name) => {
            zoommap.addEventListener(event_name, zoom_move)
        })
    })(zoommap, ['mousemove', 'touchmove'], (e) => {
        e.preventDefault();
        if (!panning || scale === 1) {
            return;
        }
    
        if (e.type == 'mousemove') {
            newPointY = (e.clientY - start.y);
            newPointX = (e.clientX - start.x);
        } else if (e.type == 'touchmove') {
            if (e.touches.length === 1) {
                newPointX = (e.touches[0].clientX - start.x);
                newPointY = (e.touches[0].clientY - start.y);
            }
        }
    
        var mapimg_div = document.getElementById("mapimg");
        const map_dim = mapimg_div.getBoundingClientRect();
        const img_dim = zoommap.getBoundingClientRect();
    
    
        const maxX = map_dim.left;
        const maxY = map_dim.top;
        const minX = map_dim.right - img_dim.width * scale;
        const minY = map_dim.bottom - img_dim.height * scale;
    
    
        if (newPointX > maxX) {
            newPointX = maxX;
        } else if (newPointX < minX) {
            newPointX = minX;
        }
    
        if (newPointY > maxY) {
            newPointY = maxY;
        } else if (newPointY < minY) {
            newPointY = minY;
        }
    
        // Update pointX and pointY with the new values
        pointX = newPointX;
        pointY = newPointY;
    
        zoommap.style.transform = "translate(" + pointX + "px, " + pointY + "px) scale(" + scale + ")";
    });
    
    Login or Signup to reply.
  2. Now try this

    var scale = 1,
        panning = false,
        pointX = 0,
        pointY = 0,
        mid_x = 0,
        mid_y = 0,
        start = { x: 0, y: 0 },
        zoommap = document.getElementById("immagine");
    let newPointX, newPointY;
    
    ((zoommap, event_names, zoom_start) => {
        event_names.forEach((event_name) => {
            zoommap.addEventListener(event_name, zoom_start);
        });
    })(zoommap, ['mousedown', 'touchstart'], (e) => {
        e.preventDefault();
        panning = true;
        if (e.type == 'mousedown') {
            start = { x: e.clientX - pointX, y: e.clientY - pointY };
        } else if (e.type == 'touchstart') {
            if (e.touches.length === 1) {
                start = { x: e.touches[0].clientX - pointX, y: e.touches[0].clientY - pointY };
            } else if (e.touches.length === 2) {
                start = {
                    x: (e.touches[0].clientX + e.touches[1].clientX) / 2 - pointX,
                    y: (e.touches[0].clientY + e.touches[1].clientY) / 2 - pointY,
                    dist: Math.hypot(e.touches[0].clientX - e.touches[1].clientX, e.touches[0].clientY - e.touches[1].clientY)
                };
            }
        }
    });
    
    ((zoommap, event_names, zoom_end) => {
        event_names.forEach((event_name) => {
            zoommap.addEventListener(event_name, zoom_end);
        });
    })(zoommap, ['mouseup', 'touchend', 'touchcancel'], (e) => {
        panning = false;
    });
    
    ((zoommap, event_names, zoom_end) => {
        event_names.forEach((event_name) => {
            zoommap.addEventListener(event_name, zoom_end);
        });
    })(zoommap, ['mousemove', 'touchmove'], (e) => {
        e.preventDefault();
        if (!panning || scale === 1) {
            return;
        }
    
        if (e.type == 'mousemove') {
            newPointY = (e.clientY - start.y);
            newPointX = (e.clientX - start.x);
        } else if (e.type == 'touchmove') {
            if (e.touches.length === 1) {
                newPointX = (e.touches[0].clientX - start.x);
                newPointY = (e.touches[0].clientY - start.y);
            }
        }
    
        var mapimg_div = document.getElementById("mapimg");
        const map_dim = mapimg_div.getBoundingClientRect();
        const img_dim = zoommap.getBoundingClientRect();
    
        const maxX = map_dim.left;
        const maxY = map_dim.top;
        const minX = map_dim.right - img_dim.width * scale;
        const minY = map_dim.bottom - img_dim.height * scale;
    
        if (newPointX > maxX) {
            newPointX = maxX;
        } else if (newPointX < minX) {
            newPointX = minX;
        }
    
        if (newPointY > maxY) {
            newPointY = maxY;
        } else if (newPointY < minY) {
            newPointY = minY;
        }
    
        pointX = newPointX;
        pointY = newPointY;
    
        zoommap.style.transform = "translate(" + pointX + "px, " + pointY + "px) scale(" + scale + ")";
    });
    
    ((zoommap, event_names, zoom_move) => {
        event_names.forEach((event_name) => {
            zoommap.addEventListener(event_name, zoom_move);
        });
    })(zoommap, ['mousewheel', 'touchmove'], (e) => {
        e.preventDefault();
        zoommap.style.transform = "none";
        var img_dim = zoommap.getBoundingClientRect();
    
        if (e.type == 'mousewheel') {
            var x = ((img_dim.width - (img_dim.right - e.clientX)) / img_dim.width) * 100;
            var y = ((img_dim.height - (img_dim.bottom - e.clientY)) / img_dim.height) * 100;
            zoommap.style.transformOrigin = x + "% " + y + "%";
            var delta = (e.wheelDelta ? e.wheelDelta : -e.deltaY);
            (delta > 0) ? (scale *= 1.2) : (scale /= 1.2);
        } else if (e.type == 'touchmove') {
            if (e.touches.length == 2) {
                if (e.scale) {
                    scale = e.scale;
                } else {
                    var move_dist = Math.hypot(e.touches[0].clientX - e.touches[1].clientX, e.touches[0].clientY - e.touches[1].clientY);
                    (move_dist > start.dist) ? (scale *= 1.01) : (scale /= 1.01);
                }
    
                var x = ((img_dim.width - (img_dim.right - mid_x)) / img_dim.width) * 100;
                var y = ((img_dim.height - (img_dim.bottom - mid_y)) / img_dim.height) * 100;
                zoommap.style.transformOrigin = x + "% " + y + "%";
                mid_x = (e.touches[0].clientX + e.touches[1].clientX) / 2;
                mid_y = (e.touches[0].clientY + e.touches[1].clientY) / 2;
                pointX = (mid_x - start.x);
                pointY = (mid_y - start.y);
            }
        }
    
        scale = Math.min(Math.max(1, scale), 20);
    
        pointX = pointX * scale;
        pointY = pointY * scale;
    
        zoommap.style.transform = "scale(" + scale + ") translate(" + pointX + "px, " + pointY + "px)";
    });
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search