如何计算图像缩放后居中所需的像素偏移量?
问题描述
在两个独立的div中各放置了一张图片,需求为:当鼠标悬停在第一个div的完整图片上时,第二个尺寸为300x300的div内的图片产生缩放效果并保持居中。目前未应用缩放时,图像能在第二个div中正常居中,但当设置scale为2这类缩放因子后,图像无法居中,现需计算需要添加的像素偏移量以实现缩放后的居中效果。
相关代码
HTML代码
<!DOCTYPE html> <html> <head> <title>Your Page Title</title> <!-- Include jQuery from CDN or from your local project directory --> <!-- <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> --> <!-- Include ElevateZoom from your local project directory --> <!--<script src="./zoom.js"></script>--> <script src="./helloworld.js"></script> <!-- Your other head elements --> <style> .zoom-outer-container { border: solid 20px green; display: flex; justify-content: center; overflow: hidden; } .zoom-inner-container { /*border: solid 30px red;*/ overflow: hidden; } .zoom-inner-container img { height: 100%; width: 1000px; transform-origin: center; /* Set the transform origin to the center */ transition: transform 0.5s ease; /* Adding the transition property for smooth animation */ } </style> </head> <body> <div class="zoom-outer-container" style="border: solid 20px green; display: flex; justify-content: center; overflow: hidden;"> <div class="zoom-inner-container" style="position: relative;"> <img style="height: 500px; width: 1000px;" src="download.jfif" alt="Image to Zoom" id="zoom-image" /> <div class="zoomed-image-container" style="position: absolute; top: 0; left: 100%; width: 100px; height: 100px; background-image: url(download.jfif); background-size: 150%;"></div> </div> <div class="mouse-follow-div" style="display: block; background-color: red;overflow: hidden;height: 300px; width: 300px;"> <img style="height: 500px; width: 1000px;" src="download.jfif" alt="Image to Zoom" id="zoom-image-2" /> </div> </div> <p> Mouse pos global: <b><span id="mouse-pos"></span></b> Mouse pos image: <b><span id="mouse-pos-image"></span></b> </p> <script> var imageElement = document.getElementById("zoom-image"); MyLibrary.addZoomTool(imageElement,document.querySelector(".mouse-follow-div"),document.querySelector("#zoom-image-2"), 2); // Zoom in by a scale factor of 1.2 </script> </body> </html>
JavaScript代码
var MyLibrary = {}; MyLibrary.sayHello = function() { return "Hello, World!"; }; MyLibrary.addZoomTool = function(imageElement,imageBlock,imageScaled,scaleFactor) { const mousePosText = document.getElementById('mouse-pos'); const mousePosTextImage = document.getElementById('mouse-pos-image'); let mousePos = { x: undefined, y: undefined }; let mousePosImage = { x: undefined, y: undefined }; let inImg = { onImage : false}; imageElement.addEventListener("mouseenter", function(event) { inImg.onImage = true; }); imageElement.addEventListener("mousemove", function(event) { //const element = document.getElementById('myElement'); const rect = imageBlock.getBoundingClientRect(); console.log('--------------------------'); console.log('Top:', rect.top); console.log('Bottom:', rect.bottom); console.log('Left:', rect.left); console.log('Right:', rect.right); console.log('Width:', rect.width); console.log('Height:', rect.height); console.log('--------------------------'); //inImg.onImage = true; mousePosImage = { x: event.offsetX, y: event.offsetY }; var scale = scaleFactor || 1.5; //Hay que coger el punto medio del otro ahora var centerWidthimageScaled = imageScaled.offsetWidth / 2; var centerHeightimageScaled = imageScaled.offsetHeight / 2; //150 es el ancho de la caja para que quede centrado //imageScaled.style.transform = `scale(${scale})`; var moveNewX = (mousePosImage.x ) - (300/2); var moveNewY = (mousePosImage.y ) - (300/2); imageScaled.style.position = "relative"; //imageScaled.style.right = moveNewX + "px"; //imageScaled.style.bottom = moveNewY + "px"; scaleFactor = 1; //-moveNewX + (-moveNewX) //Hay que sumar el pixel que falta tanto en x como en y imageScaled.style.transform = `translate(${-moveNewX}px, ${-moveNewY}px) scale(${scaleFactor})`; }); imageElement.addEventListener("mouseleave", function(event) { inImg.onImage = false; mousePosImage = { x: undefined, y: undefined }; }); window.addEventListener('mousemove', (event) => { //console.log(inImg); if(inImg.onImage){ //console.log("in img"); //imageElement.style.transform = 'scale(2)'; //Para saber donde empieza la imagen, hay que coger la posicion del raton y restarle el ancho de la imagen // Show the mouse-follow-div imageBlock.style.display = "block"; // Update the position of the mouse-follow-div based on the mouse cursor var mouseX = event.clientX; var mouseY = event.clientY; // Offset the position of the div so it aligns with the cursor var offset = 25; // Half the width/height of the div to center it on the cursor //imageBlock.style.left = (100 + mouseX - offset) + "px"; //imageBlock.style.top = (mouseY - offset) + "px"; }else{ //console.log("out of img"); //var mouseFollowDiv = imageBlock; //imageBlock.display = "hide"; //imageBlock.style.display = "none"; } mousePos = { x: event.clientX, y: event.clientY }; mousePosText.textContent = `(${mousePos.x}, ${mousePos.y})`; mousePosTextImage.textContent = `(${mousePosImage.x}, ${mousePosImage.y})`; }); };
解决方案
核心逻辑是:图像缩放后,鼠标在原图上的对应点需要恰好落在300x300容器的中心。通过计算缩放后该点的位置,再用translate偏移让这个点与容器中心重合。
偏移量计算方法
- X轴偏移:缩放后,鼠标在原图的x坐标
mousePosImage.x对应到缩放图上的位置是mousePosImage.x * scale。容器中心的x位置是150px(300/2),因此图像需要向左偏移的距离为(mousePosImage.x * scale) - 150,对应translateX取负值。 - Y轴偏移:同理,缩放后鼠标对应点的y位置是
mousePosImage.y * scale,容器中心y位置是150px,图像需要向上偏移的距离为(mousePosImage.y * scale) - 150,对应translateY取负值。
修改后的关键代码
将imageElement.addEventListener("mousemove")中的变换代码替换为:
mousePosImage = { x: event.offsetX, y: event.offsetY }; var scale = scaleFactor || 1.5; // 计算缩放后需要的偏移量 const containerHalfWidth = 300 / 2; const containerHalfHeight = 300 / 2; const translateX = -((mousePosImage.x * scale) - containerHalfWidth); const translateY = -((mousePosImage.y * scale) - containerHalfHeight); imageScaled.style.transform = `translate(${translateX}px, ${translateY}px) scale(${scale})`;
完整修改后的JavaScript函数片段
imageElement.addEventListener("mousemove", function(event) { const rect = imageBlock.getBoundingClientRect(); console.log('--------------------------'); console.log('Top:', rect.top); console.log('Bottom:', rect.bottom); console.log('Left:', rect.left); console.log('Right:', rect.right); console.log('Width:', rect.width); console.log('Height:', rect.height); console.log('--------------------------'); mousePosImage = { x: event.offsetX, y: event.offsetY }; var scale = scaleFactor || 1.5; // 计算偏移量 const containerHalfWidth = 300 / 2; const containerHalfHeight = 300 / 2; const translateX = -((mousePosImage.x * scale) - containerHalfWidth); const translateY = -((mousePosImage.y * scale) - containerHalfHeight); imageScaled.style.transform = `translate(${translateX}px, ${translateY}px) scale(${scale})`; });
修改后,无论缩放因子设置为多少,鼠标指向的原图区域都会始终居中显示在300x300的容器内。
内容的提问来源于stack exchange,提问作者dreid
相关产品推荐
相关产品推荐

