Skip to content

fix: 修正缩放容器内的画布输入坐标 - #2299

Open
Geequlim wants to merge 1 commit into
layabox:LayaAir_3.4from
tinyaxis:fix-canvas-input
Open

fix: 修正缩放容器内的画布输入坐标#2299
Geequlim wants to merge 1 commit into
layabox:LayaAir_3.4from
tinyaxis:fix-canvas-input

Conversation

@Geequlim

Copy link
Copy Markdown
Contributor

改动说明

修正 LayaAir canvas 放在被 CSS 缩放或偏移的容器中时,鼠标和触摸输入坐标可能偏移的问题。

此前 InputManager 直接使用原生事件的页面/视口坐标,再进入现有的 _canvasTransform 流程。当 canvas 外层容器被移动或缩放时,例如开发工具内嵌预览面板,命中测试
坐标会和实际显示位置不一致。

本次改动会先把原生 clientX/clientY 换算到主画布父容器的本地坐标系,再继续沿用现有的 _canvasTransformclientScale 处理流程。

改动内容

  • 鼠标和触摸输入统一使用 clientX/clientY
  • 基于主画布父容器的 getBoundingClientRect() 换算输入坐标
  • 保持现有 Stage transform、缩放和事件派发流程不变

测试

  • 已通过 LayaAir 引擎构建验证
  • 已在实际项目中测试使用
image

@xiaoguzhu

Copy link
Copy Markdown
Member

结论:建议暂缓合并,标记 Request changes。发现两个坐标换算问题。
[P1] 默认 layaContainer 会直接绕过本次修复。
默认 canvas 是 position:absolute,父容器没有设置高度,因此父容器通常 clientHeight === 0。!rect.height 会直接返回原始视口坐标,导致默认容器或其祖先被缩放、偏移时,原问题仍然存在。默认 DOM 创建方式可见 BrowserAdapter.createMainCanvas()。建议基于实际 DOM transform 做逆变换,或改用具有有效布局尺寸的坐标参考元素。

[P2] 混用了 border box 与 client box。
getBoundingClientRect() 返回包含边框的尺寸,而 clientWidth/clientHeight 不包含边框。容器存在边框时,计算出的缩放比例和原点都会偏移。例如 1000px 宽、10px 边框、缩放 0.5 的容器,canvas 左边缘会被换算到约 9.8px,而不是 0。编辑器预览面板存在边框是很常见的场景。

另外,PR #2299 目前只有构建和实际项目手工验证,没有自动化状态检查。建议补充以下回归场景:默认零高度容器、scale + translate、带边框容器,并分别覆盖鼠标和触摸输入。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants