Vue中mousemove事件控制div transform位移出现反向偏移跳变问题
问题排查与解决方法
核心问题根源
- 事件冒泡导致坐标取值不稳定:mousemove事件绑定在父容器上,但子元素.door会冒泡触发该事件,
e.offsetX/e.offsetY是相对于事件触发源的坐标,鼠标滑到door上时坐标相对于door计算,滑到父容器空白区域时相对于父容器计算,因此出现交替的异常值和正常值。 - 位移计算逻辑错误:
getBoundingClientRect()返回的是元素应用transform后的实时位置,你在计算时反复叠加该实时位置,再取负赋值transform,相当于每次位移都基于上一次偏移后的结果计算,逻辑完全不符合元素跟随的需求。
修复方案
第一步:稳定鼠标坐标取值
两种方案二选一即可:
- 禁止子元素响应鼠标事件(door不需要交互时推荐,改造成本最低)
给.door加CSS属性:
.door { pointer-events: none; }
- 基于clientX计算相对于父容器的稳定坐标(door需要保留交互时使用)
直接用鼠标相对于视口的坐标减去父容器的偏移量,不受事件冒泡影响:
const containerRect = this.$refs['test-container'].getBoundingClientRect() // 拿到的是鼠标相对于父容器左上角的稳定坐标 const mouseX = e.clientX - containerRect.left const mouseY = e.clientY - containerRect.top
第二步:修正位移计算逻辑
你要实现元素跟随鼠标的效果,直接计算目标偏移量即可,不要叠加元素当前的实时位置,示例代码(0.1是跟随灵敏度,可自行调整,数值越小跟随越平缓):
moveDoors(e) { const containerRect = this.$refs['test-container'].getBoundingClientRect() const mouseX = e.clientX - containerRect.left const mouseY = e.clientY - containerRect.top const currentDoor = this.$refs[`door-1`] const doorRect = currentDoor.getBoundingClientRect() // 计算让door中心跟随鼠标的偏移量,乘以灵敏度系数实现缓动视差效果 const x = (mouseX - doorRect.width / 2) * 0.1 const y = (mouseY - doorRect.height / 2) * 0.1 currentDoor.style.transform = `translate(${x}px, ${y}px)` }
如果需要更平滑的动画效果,还可以给door加CSS过渡:
.door { transition: transform 0.1s ease-out; }
内容的提问来源于stack exchange,提问作者Cat Named Dog
相关产品推荐
相关产品推荐

