本文介绍一种通过隐藏原生光标并使用 css `translate` 驱动父容器位移的方式,让多个“假光标”完美同步鼠标运动,彻底解决传统 `mousemove` + `offsetleft/top` 方案存在的视觉延迟问题。
在开发类似“躲猫猫鼠标”类互动游戏时,一个常见痛点是:当试图用多个 元素模拟随鼠标移动的“假光标”时,若采用监听 mousemove 事件、逐帧计算位移并更新 style.left/top 的方式(如 img.style.left = img.offsetLeft + deltaX + 'px'),会因 DOM 读写强制重排(Layout Thrashing)、样式计算开销及 JavaScript 执行延迟,导致视觉上明显滞后——尤其在快速移动或高刷新率屏幕上,“假光标”仿佛被拖着走,极易被玩家识破。
根本原因在于:
✅ 最优解:放弃逐元素定位,改用「单层容器 + transform」驱动
核心思路是:
以下是关键实现代码:
const elPointers = document.querySelector("#pointers");
const elBody = document.body;
const movePointers = (evt) => {
// 归一化:将 clientX/Y 映射为 [-0.5, +0.5] 区间(
中心为 0)
const xCenter = evt.clientX / elBody.offsetWidth - 0.5;
const yCenter = evt.clientY / elBody.offsetHeight - 0.5;
// 使用 translate 实现硬件加速位移
elPointers.style.translate = `${xCenter * 100}% ${yCenter * 100}%`;
};
elBody.addEventListener("pointermove", movePointers);对应 CSS 需确保:
#pointers {
position: absolute;
width: 100%;
height: 100%;
pointer-events: none; /* 关键!允许鼠标穿透到下方按钮 */
/* 主光标可设为背景图,居中显示 */
background: url("cursor.png") 50% 50% no-repeat;
background-size: 25px 32px;
}
.pointer {
position: absolute;
width: 25px;
height: 32px;
background: url("cursor.png");
/* 随机分布于容器内 */
}⚠️ 注意事项与进阶建议:
最终效果:无论鼠标如何疾驰,所有假光标均如影随形,与真实指针轨迹完全一致——这才是真正“难找”的鼠标游戏体验。