动画Blob偏离鼠标位置问题排查与修复求助
聚光灯Blob鼠标跟随偏移问题修复方案
问题描述
我在网站背景实现了聚光灯效果,通过深灰色层透出背景渐变。期望Blob随鼠标移动时保持居中且变形,但当前Blob会偏离鼠标位置,移动鼠标后甚至会移出屏幕再返回,静止时也无法保持固定位置。怀疑和背景层为矩形有关,求修复方案。
问题根源
- 初始
#blob设置了transform: translate(-50%, -50%)居中,但JS动画直接修改left/top为鼠标坐标,导致Blob左上角对齐鼠标而非中心对齐,产生偏移。 - 鼠标移动时多次触发
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




