You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

动画Blob偏离鼠标位置问题排查与修复求助

聚光灯Blob鼠标跟随偏移问题修复方案

问题描述

我在网站背景实现了聚光灯效果,通过深灰色层透出背景渐变。期望Blob随鼠标移动时保持居中且变形,但当前Blob会偏离鼠标位置,移动鼠标后甚至会移出屏幕再返回,静止时也无法保持固定位置。怀疑和背景层为矩形有关,求修复方案。

问题根源

  1. 初始#blob设置了transform: translate(-50%, -50%)居中,但JS动画直接修改left/top为鼠标坐标,导致Blob左上角对齐鼠标而非中心对齐,产生偏移。
  2. 鼠标移动时多次触发animate,动画队列叠加导致Blob出现延迟、乱跑的情况。

修复方案

1. 修正鼠标跟随的定位逻辑

放弃修改left/top,改为直接修改transform属性,让Blob的中心精准对齐鼠标坐标。

2. 清理动画队列

每次鼠标移动时,先取消Blob上的现有动画,避免多个动画叠加冲突。

3. 调整层级与混合模式

调整元素z-index,确保渐变背景在Blob下方,让聚光灯的遮罩效果正确生效。

修改后的完整代码

HTML

<div id="gradient-color"></div>
<div id="blob"></div>
<div id="blur"></div>

CSS

body {
  background-color: #222020;
  height: 100vh;
  margin: 0;
  overflow: hidden;
  position: relative;
}

#gradient-color {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 1; /* 放到Blob下方 */
  background: radial-gradient(50% 123.47% at 50% 50%, #00ff94 0%, #720059 100%), linear-gradient(121.28deg, #669600 0%, #ff0000 100%), linear-gradient(360deg, #0029ff 0%, #8fff00 100%), radial-gradient(100% 164.72% at 100% 100%, #6100ff 0%, #00ff57 100%), radial-gradient(100% 148.07% at 0% 0%, #fff500 0%, #51d500 100%);
  background-blend-mode: screen, color-dodge, overlay, difference, normal;
}

#blob {
  width: 1px;
  height: 1px;
  position: fixed;
  left: 0;
  top: 0;
  transform: translate(-50%, -50%);
  overflow: visible;
  background-color: white;
  mix-blend-mode: multiply;
  z-index: 2; /* 确保在渐变上方 */
}

#blob::before {
  content: "";
  display: block;
  width: 200vw;
  height: 200vh;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  background-color: #000;
}

#blob::after {
  content: "";
  display: block;
  width: 34vmax;
  aspect-ratio: 1;
  border-radius: 50%;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  background-color: #fff;
  animation: rotate 20s infinite;
}

@keyframes rotate {
  from {
    rotate: 0deg;
  }
  50% {
    scale: 1 1.5;
  }
  to {
    rotate: 360deg;
  }
}

#blur {
  height: 100%;
  width: 100%;
  position: fixed;
  backdrop-filter: blur(12vmax);
  z-index: 3; /* 模糊层在最上方 */
}

JavaScript

document.addEventListener("DOMContentLoaded", () => {
  const blob = document.getElementById("blob");

  window.onpointermove = event => {
    const { clientX, clientY } = event;
    // 先取消现有动画,避免队列叠加
    blob.getAnimations().forEach(anim => anim.cancel());
    // 修改transform让Blob中心对齐鼠标
    blob.animate({
      transform: `translate(${clientX}px, ${clientY}px) translate(-50%, -50%)`
    }, {
      duration: 2500,
      fill: "forwards"
    });
  };
});

内容的提问来源于stack exchange,提问作者soupbin

火山引擎 最新活动