Chrome下经3D变换的canvas的mouseout事件触发受窗口大小影响求助
3D变换Canvas在Chrome下mouseout事件异常解决方案
问题根因
这是Chrome内核长期存在的已知bug:对应用了复杂3D变换的元素,原生鼠标事件的碰撞检测会受窗口尺寸、滚动位置、元素本身尺寸影响,出现坐标计算精度偏差,导致mouseout、mouseover等事件提前/延迟触发,Edge和Firefox的变换元素碰撞检测逻辑没有这个问题。
可行解决方案
方案1:手动实现鼠标进出判定(最稳定,完全绕开内核bug)
放弃原生mouseout事件,通过全局mousemove事件结合元素实际边界判定进出状态,代码示例:
let isMouseInCanvas = false const canvas = document.querySelector('.dynamic-drawing-canvas') document.addEventListener('mousemove', e => { const rect = canvas.getBoundingClientRect() const {clientX, clientY} = e // 判定鼠标是否在canvas实际渲染范围内 const currentIn = clientX >= rect.left && clientX <= rect.right && clientY >= rect.top && clientY <= rect.bottom // 从进入变为离开,触发原mouseout逻辑 if(isMouseInCanvas && !currentIn) { console.log('鼠标离开canvas', clientX, clientY) } isMouseInCanvas = currentIn })
该方案不受窗口大小、滚动位置、变换类型影响,所有浏览器表现一致。
方案2:强制Chrome开启高精度变换渲染
给应用了3D变换的canvas添加will-change: transformCSS属性,强制Chrome为该元素分配独立的合成层,提升碰撞检测精度:
.dynamic-drawing-canvas { pointer-events: auto; background-color: blue; will-change: transform; /* 新增这行 */ }
该方案改造成本极低,对大部分3D变换场景都有效。
方案3:替换为等效2D变换
如果当前使用的matrix3d没有用到z轴透视、3D旋转等特性,可以转换为等效的2Dmatrix变换,Chrome对2D变换的碰撞检测逻辑没有精度问题。
内容的提问来源于stack exchange,提问作者wuiwuiwui
相关产品推荐
相关产品推荐

