核心思路是监听mousemove事件获取clientx/clienty,用transform: translate()更新元素位置;需设position: fixed/absolute、加pointer-events: none、防抖节流,并确保dom就绪。

用 mousemove 监听鼠标位置并更新元素坐标
核心思路是监听 document 或容器的 mousemove 事件,读取 event.clientX 和 event.clientY,再用它们设置目标元素的 style.left 和 style.top。注意必须给元素设置 position: absolute 或 position: fixed,否则 left/top 不生效。
常见错误是直接写 element.style.left = e.clientX + 'px',结果元素总偏移——因为 clientX/Y 是相对于视口的,而元素若在滚动容器内(比如 overflow: auto 的 div),就得改用 getBoundingClientRect() 做坐标换算,或者把监听对象换成该容器本身。
实操建议:
- 优先监听
document,覆盖全页面交互场景 - 给跟随元素加
pointer-events: none,避免它挡住下方点击 - 初始时用
getComputedStyle(element).transform检查是否已有 transform,有则需合并计算,否则位移会错乱 - 如果要兼容移动端,得同时监听
touchmove并取e.touches[0].clientX
用 transform 替代 left/top 提升性能
直接改 style.left 会触发 Layout(重排),频繁移动时掉帧明显;而 transform: translate(x, y) 只走 Composite 阶段,GPU 加速更顺滑。
示例代码片段:
document.addEventListener('mousemove', (e) => {
follower.style.transform = `translate(${e.clientX}px, ${e.clientY}px)`;
});
注意点:
- 必须确保元素没有设置
top/left等定位属性干扰,否则 transform 会被覆盖 - 如果需要偏移(比如让光标中心对准元素中心),直接在 translate 里加负半宽高:
translate(${e.clientX - 20}px, ${e.clientY - 20}px) - 某些旧版 Safari 对
transform动画有渲染 bug,可加will-change: transform强制提升图层
防抖与节流:避免 mousemove 过载
原生 mousemove 在快速移动时每秒可能触发上百次,尤其低端设备容易卡顿。不处理的话,transform 更新也会堆积,反而更慢。
推荐用时间戳节流(比 setTimeout 更精准):
let lastTime = 0;
document.addEventListener('mousemove', (e) => {
const now = Date.now();
if (now - lastTime > 16) { // ≈60fps
follower.style.transform = `translate(${e.clientX}px, ${e.clientY}px)`;
lastTime = now;
}
});
关键细节:
- 阈值设为
16而非10或24,兼顾响应与性能 - 不要用 Lodash 的
throttle,它默认 leading/trailing 行为在鼠标连续移动中反而增加无效调用 - 如果页面有大量其他
mousemove处理逻辑,建议统一用一个事件处理器分发,避免多次绑定
遇到 Uncaught TypeError: Cannot set property 'transform' of null 怎么办
这是最常见的运行时错误,说明 follower 元素没拿到 DOM 节点。根本原因通常是脚本执行时机早于 HTML 解析完成。
解决方式只有两个有效路径:
- 把
<script></script>标签放到
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











