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
Try This Code:
Now try this