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

鼠标移动触发的图片动画实现优化求助

优化视差鼠标交互动画流畅度的方案

核心问题分析

原实现的卡顿主要来自:

  • setTimeout 与 requestAnimationFrame 的时序冲突,导致动画帧不同步
  • 每次鼠标移动都生成新的延迟任务,造成任务队列堆积
  • 未使用自然的缓动曲线,且偏移计算未考虑容器位置偏移

具体优化措施

  1. 移除setTimeout,用缓动系数实现层级延迟效果
    放弃定时器,给每个图片设置不同的深度系数,让层级靠后的图片移动幅度更小、响应更慢,模拟延迟效果,完全贴合浏览器渲染帧。

  2. 使用容器相对坐标计算偏移
    用getBoundingClientRect()获取容器在视口的位置,计算鼠标相对于容器中心的偏移,避免视口滚动导致的坐标错误。

  3. 添加平滑的缓动过渡
    给CSS的transition设置自然的缓动函数(如cubic-bezier(0.25, 0.46, 0.45, 0.94)),替换生硬的linear;同时在JS中用增量更新实现帧间平滑,避免跳变。

  4. 优化鼠标移出的复位动画
    统一用CSS过渡处理复位,避免JS直接覆盖样式导致的突兀。

修改后的完整代码

HTML

<h5>PRACTICE TESTING ANIMATIONS</h5>

<div class="image-container">
  <img src="image1.jpg" class="image" data-depth="0.1" id="image1">
  <img src="image2.jpg" class="image" data-depth="0.2" id="image2">
  <img src="image3.jpg" class="image" data-depth="0.3" id="image3">
  <img src="image4.jpg" class="image" data-depth="0.4" id="image4">
</div>

CSS

body {
  background-color: azure;
  margin: 0;
  padding: 0;
  overflow: hidden;
}

h5 {
  text-align: center;
}

img {
  width: 100px;
  height: 100px;
}

.image-container {
  position: relative;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
}

.image {
  position: absolute;
  /* 使用自然的缓动曲线 */
  transition: transform 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
  /* 提示浏览器提前优化渲染 */
  will-change: transform;
}

.image:hover {
  transform: translate(0, 0) !important;
}

#image1 {
  left: 20%;
  top: 20%;
}

#image2 {
  left: 27%;
  bottom: 20%;
}

#image3 {
  left: 60%;
  top: 60%;
}

#image4 {
  right: 20%;
  top: 20%;
}

JavaScript

const images = document.querySelectorAll(".image");
const container = document.querySelector(".image-container");
let animationFrameId = null;
// 存储当前偏移量,用于帧间平滑过渡
let currentX = 0;
let currentY = 0;

container.addEventListener("mousemove", (e) => {
  const rect = container.getBoundingClientRect();
  // 计算鼠标相对于容器中心的偏移
  const mouseX = e.clientX - rect.left - rect.width / 2;
  const mouseY = e.clientY - rect.top - rect.height / 2;

  if (animationFrameId) {
    cancelAnimationFrame(animationFrameId);
  }

  animationFrameId = requestAnimationFrame(() => {
    // 缓动更新当前偏移量,0.1为缓动系数,值越小动画越平滑
    currentX += (mouseX * -0.1 - currentX) * 0.1;
    currentY += (mouseY * -0.1 - currentY) * 0.1;

    images.forEach(image => {
      // 用data-depth属性控制每个图片的移动幅度
      const depth = parseFloat(image.dataset.depth);
      const xOffset = currentX * depth;
      const yOffset = currentY * depth;

      if (!image.classList.contains("hovered")) {
        image.style.transform = `translate(${xOffset}px, ${yOffset}px)`;
      }
    });
  });
});

container.addEventListener("mouseout", () => {
  if (animationFrameId) {
    cancelAnimationFrame(animationFrameId);
  }
  // 重置偏移量,让动画平滑复位
  currentX = 0;
  currentY = 0;
  images.forEach(image => {
    image.style.transform = "translate(0, 0)";
  });
});

额外优化提示

如果图片数量较多,可使用节流函数限制mousemove事件的触发频率,进一步减少计算压力。

内容的提问来源于stack exchange,提问作者David K.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 04:35:30