You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何计算图像缩放后居中所需的像素偏移量?

问题描述

在两个独立的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偏移让这个点与容器中心重合。

偏移量计算方法

  1. X轴偏移:缩放后,鼠标在原图的x坐标mousePosImage.x对应到缩放图上的位置是 mousePosImage.x * scale。容器中心的x位置是150px(300/2),因此图像需要向左偏移的距离为 (mousePosImage.x * scale) - 150,对应translateX取负值。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 08:35:57