使用 javascript 平移/缩放时限制图像的边界

问题描述 投票:0回答:2

我想在平移时限制图像的边界,因此,从左向右平移时图像的左侧不应超出容器的左边缘,并且图像的右边缘不应超出容器的右侧从右向左平移时的容器。在较小的规模下,代码中的边界条件有效,但在较大的规模下,边界条件不起作用,我无法弄清楚问题出在哪里。

// ------------------- 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)";
    });

javascript html css zooming panning
2个回答
0
投票

试试这个代码:

((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 + ")";
});

0
投票

现在试试这个

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)";
});
© www.soinside.com 2019 - 2024. All rights reserved.