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

鼠标与触屏环境下捏合缩放+拖拽功能的缩放原点异常问题求助

鼠标与触屏环境下捏合缩放+拖拽功能的缩放原点异常问题求助

大家好,我现在在做一个触屏显示器上的图片交互功能:希望能实现放大图片局部、拖拽移动、并从拖拽结束点缩小的效果。我用了GSAP库来做拖拽和缩放,配合Hammer.js处理触屏事件。

目前基础功能已经跑通了,但遇到一个问题:如果我先放大图片,然后拖拽到图片的另一端,再缩小的时候,图片不会以我当前鼠标/触摸的位置为原点缩放。但如果在同一个位置反复缩放,效果是完全正常的。我怀疑是transform-origin和translate3D()的冲突导致的,但不确定是不是漏了什么明显的细节。

有没有大佬能帮忙看看问题出在哪,或者给点建议?

复现提示:需要引入GSAP主库,以及Draggable和Observer插件。

HTML代码

<img src="https://img.freepik.com/free-photo/painting-mountain-lake-with-mountain-background_188544-9126.jpg?t=st=1736502806~exp=1736506406~hmac=55191bc567a6b56fa91081c238a86595d5a85ff785179070a8deb52b1ba05041&w=1380" class="zoom-item">

CSS代码

body {
  display: flex;
  justify-content: center;
  align-items: center;
  overflow: hidden;
}

.box {
  width: 300px;
  height: 300px;
  background: red;
}

JavaScript代码

let image = document.querySelector(".zoom-item"),
  hammer = new Hammer(image),
  mousePosArr = [],
  pinchPosArr = [];

hammer.get("pinch").set({
  enable: true
});

hammer.on("pinchstart", (e) => {
  let pinchX = e.srcEvent.offsetX,
    pinchY = e.srcEvent.offsetY;

  pinchPosArr.push(pinchX, pinchY);

  zoomDrag[0].disable();
});

hammer.on("pinch", (e) => {
  console.log(pinchPosArr);

  let roundedX = Math.ceil(pinchPosArr[0]),
    roundedY = Math.ceil(pinchPosArr[1]);

  switch (e.additionalEvent) {
    case "pinchout":
      //round the numbers to nearest whole one
      zoom_control("+=0.03", roundedX, roundedY);
      break;
    case "pinchin":
      if (gsap.getProperty(e.target, "scale") >= 1.2) {
        zoom_control("-=0.03", roundedX, roundedY);
      }
      break;
  }
});

hammer.on("pinchend", () => {
  pinchPosArr = [];
  zoomDrag[0].enable();
});

let zoomObserver = Observer.create({
    target: ".zoom-item",
    type: "wheel", // Will only fire on the wheel scroll
    ease: "linear", // makes the animations more slower
    wheelSpeed: 0.1, // Changed how fast the zoom in happens
    onUp: (self) => {
      mousePosArr = [];
      let mouseX = self.event.offsetX,
        mouseY = self.event.offsetY;

      mousePosArr.push(mouseX, mouseY);
      // Creates an array and pushes each instance of mouseX and mouseY into the array

      const [posA, posB] = mousePosArr.slice(-2); // slice() helps me grab the last two added items into the array

      //using the posA and posB means that it zoom into wherever my mouse currently is
      console.log(image.style.scale);
      zoom_control("+=0.3", posA, posB);
    },
    onDown: (self) => {
      // Will only fire if the scale is above the 1.2
      if (gsap.getProperty(self.target, "scale") >= 1.2) {
        zoom_control("-=0.3", mousePosArr[0], mousePosArr[1]);
      }
    }
  }),
  zoomDrag = Draggable.create(".zoom-item", {
    zIndexBoost: false, // zIndexBoost set to false to stop it creasing on each click
    onDrag: () => {
      zoomObserver.disable();
    },
    onDragEnd: () => {
      zoomObserver.enable();
    }
  });

function zoom_control(scaleNum, transformX, transformY) {
  gsap.set(image, {
    transformOrigin: `${transformX}px ${transformY}px`
  });
  let scaleSetter = gsap.quickSetter(image, "css");
  scaleSetter({
    scale: scaleNum
  });
}

备注:内容来源于stack exchange,提问作者WesCritch

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 13:33:00