如何通过鼠标点击设置背景移动方向与速度?含代码优化及问题排查
背景跟随鼠标点击移动优化方案
核心需求
- 背景根据鼠标点击位置的方向移动,速度由点击点与div中点的距离决定
- 修复每次点击后速度加快的问题
- 改用
requestAnimationFrame实现流畅动画 - 用
transform: translate替代background-position提升性能
原代码问题分析
- 速度叠加:每次
mousedown触发时新建setInterval,多个定时器同时更新位置,导致速度翻倍 - 性能低下:
background-position修改会触发浏览器重排,动画卡顿风险高 - 动画精度差:
setInterval时间间隔不精确,无法同步浏览器刷新帧率
优化后的完整代码
function flight() { const wmap = document.querySelector('#wmap'); let offsetX = wmap.clientWidth; let offsetY = wmap.clientHeight + 800; let animationId = null; const centerX = 350; const centerY = 350; // 初始化背景位置 updateBackgroundPosition(); wmap.addEventListener('mousedown', (e) => { // 计算速度:距离中心点越远,速度越快 const speedX = -(e.offsetX - centerX) * 0.01; const speedY = -(e.offsetY - centerY) * 0.01; // 取消上一次动画,避免速度叠加 if (animationId) { cancelAnimationFrame(animationId); } // 启动动画循环 function animate() { offsetX += speedX; offsetY += speedY; updateBackgroundPosition(); animationId = requestAnimationFrame(animate); } animate(); }); // 统一更新位置:用transform替代background-position function updateBackgroundPosition() { wmap.style.transform = `translate(${offsetX}px, ${offsetY}px)`; // 若需移动背景图而非元素本身,可替换为: // wmap.style.backgroundPosition = `${offsetX}px ${offsetY}px`; } } flight();
关键修改说明
解决速度叠加问题
- 每次启动新动画前,通过
cancelAnimationFrame取消上一次的动画帧,确保同一时间只有一个动画在运行 - 完全移除
setInterval,改用requestAnimationFrame天然避免定时器叠加
- 每次启动新动画前,通过
requestAnimationFrame应用
- 自动同步浏览器刷新帧率(通常60fps),动画更流畅无卡顿
- 用
animationId追踪动画帧,方便随时终止动画
transform替代background-position
transform由GPU加速,仅触发合成操作,不会引发重排,性能远优于background-position- 封装
updateBackgroundPosition函数,统一处理位置更新逻辑,便于后续维护
其他细节优化
- 直接固定div中心点(原代码中为固定350),移除冗余的
mouseover事件 - 使用
const声明常量,提升代码可读性与稳定性
- 直接固定div中心点(原代码中为固定350),移除冗余的
内容的提问来源于stack exchange,提问作者Спиридон
相关产品推荐
相关产品推荐

