大于 800×600 的视口档位中,面板和控制栏的点击 / 悬停坐标没加栏位偏移,栏内格子和按钮点偏 #542

Closed
opened 2026-10-02 03:54:00 +00:00 by troytt · 0 comments
Owner

现象

在大于 800×600 的视口档位里(main 上是 1024×768;本地分支 feat/viewport-formula-resolutions 新增的 1068×600、1280×720 也一样),左右栏和底部控制栏画的位置是对的,点击拦截也对(点在栏上不会让角色走路),但栏内格子和按钮的命中位置偏了:点了没反应,或者点中旁边的格子 / 按钮。鼠标悬停的高亮和 tooltip 也偏。800×600 不受影响。

舞台按档位比例撑满时(marginW = 0)的偏移:

档位 右栏(物品栏 / 技能树) 左栏(人物、任务、仓库、方块、小站、商店等) 控制栏(红蓝球、腰带、技能热键、小面板按钮、跑 / 走)
1024×768 x 偏 224、y 偏 84 y 偏 84 x 偏 112、y 偏 168
1068×600 x 偏 268 无 x 偏 134
1280×720 x 偏 480、y 偏 60 y 偏 60 x 偏 240、y 偏 120

代码现状(main 33b1b0a,src/client/ui/hud-manager.ts)

绘制和拦截用的是正确的偏移:

  • render() 1865–1870:左栏 translate(deltaLeft, panelOffsetY)(1900、1926),右栏 translate(deltaRight, panelOffsetY)(1955、1973,1024×768 下 deltaRight = 224),控制栏 translate(barOffsetX, barOffsetY)(1989)。
  • isPointInterceptedByHud() 的宽屏分支(1132–1153)也按 barOffsetX/Y、panelOffsetY 和右栏的实际位置判断。

三条鼠标输入路径只用了 ±marginW:没减 panelOffsetY 和 barOffsetX/Y,右栏也没减 rightDockX − 400。

  1. handleMouseMove() 627–654(程序化点击 handleClick() 656–667 走第 3 条):控制栏组件 631–634 直接用原始坐标;右栏 639–645 用 deltaRight = marginW;左栏 652 用 deltaLeft = -marginW。
  2. window 的 mousemove 1291–1346:同上(1295–1299、1305–1320);悬停物品 tooltip 回写坐标(1310–1337)也只加了 ±marginW,y 没加。
  3. handleHudMouseDown() 1367 起:腰带、红蓝球、热键、控制栏 1449–1483 用原始坐标;左右栏 1485–1542 用 ±marginW,y 都没减 panelOffsetY。

belt.ts、globes.ts、hotkeys.ts、control-bar.ts、inventory.ts、skill-tree-panel.ts、world-panels.ts、character-sheet.ts 都按原生 800×600 坐标做命中测试,不知道视口档位,所以只能在 HudManager 里换算。

期望修复

  • 在 HudManager 里加一组"逻辑坐标 → 区域本地坐标"的换算,和 render() 用同一组 docking 量:
    • 左栏:(x − leftDockX, y − panelOffsetY)
    • 右栏:(x − (rightDockX − 400), y − panelOffsetY)
    • 控制栏:(x − barOffsetX, y − barOffsetY)
  • 三条输入路径都改用这组换算;悬停 tooltip 回写时反向加回(x 和 y 都要)。
  • 800×600 下这组量正好等于现在的 -marginW、+marginW、0,行为不变。
  • 不要在各组件里分别加偏移,避免再和 render() 不一致。

验证

  • 单测:800×600、1024×768、1068×600、1280×720 四档,各用按档位尺寸的 mock canvas 构造 HudManager(可参考 tests/client/viewport-formula-profiles.test.ts 里的 createHudAt),在画面上的实际位置点击:跑 / 走切换、小面板按钮、腰带格、物品栏格子、人物加点、仓库格子、技能树,断言对应动作触发;悬停断言 tooltip 位置和绘制位置一致。
  • 浏览器:在 play.html 切到 1024×768、1068×600、1280×720,实际点一遍并截图存档。

相关

  • feat/viewport-formula-resolutions(748f6ba,待合入 main):按公式生成视口档位(barOffsetX = (W − 800) / 2、barOffsetY = H − 600、panelOffsetY = (H − 600) / 2),新增 1068×600、1280×720。只改了绘制和点击拦截,没动输入路径,所以同样有本问题。
  • handleHudMouseDown() 的腰带 / 左栏点击附近目前还有未提交的改动,修复前先等它合入 main,再在其基础上改,避免冲突。
## 现象 在大于 800×600 的视口档位里(main 上是 1024×768;本地分支 `feat/viewport-formula-resolutions` 新增的 1068×600、1280×720 也一样),左右栏和底部控制栏**画的位置是对的,点击拦截也对**(点在栏上不会让角色走路),但栏内格子和按钮的命中位置偏了:点了没反应,或者点中旁边的格子 / 按钮。鼠标悬停的高亮和 tooltip 也偏。800×600 不受影响。 舞台按档位比例撑满时(`marginW = 0`)的偏移: | 档位 | 右栏(物品栏 / 技能树) | 左栏(人物、任务、仓库、方块、小站、商店等) | 控制栏(红蓝球、腰带、技能热键、小面板按钮、跑 / 走) | |---|---|---|---| | 1024×768 | x 偏 224、y 偏 84 | y 偏 84 | x 偏 112、y 偏 168 | | 1068×600 | x 偏 268 | 无 | x 偏 134 | | 1280×720 | x 偏 480、y 偏 60 | y 偏 60 | x 偏 240、y 偏 120 | ## 代码现状(main `33b1b0a`,`src/client/ui/hud-manager.ts`) 绘制和拦截用的是正确的偏移: - `render()` 1865–1870:左栏 `translate(deltaLeft, panelOffsetY)`(1900、1926),右栏 `translate(deltaRight, panelOffsetY)`(1955、1973,1024×768 下 `deltaRight = 224`),控制栏 `translate(barOffsetX, barOffsetY)`(1989)。 - `isPointInterceptedByHud()` 的宽屏分支(1132–1153)也按 `barOffsetX/Y`、`panelOffsetY` 和右栏的实际位置判断。 三条鼠标输入路径只用了 `±marginW`:没减 `panelOffsetY` 和 `barOffsetX/Y`,右栏也没减 `rightDockX − 400`。 1. `handleMouseMove()` 627–654(程序化点击 `handleClick()` 656–667 走第 3 条):控制栏组件 631–634 直接用原始坐标;右栏 639–645 用 `deltaRight = marginW`;左栏 652 用 `deltaLeft = -marginW`。 2. `window` 的 `mousemove` 1291–1346:同上(1295–1299、1305–1320);悬停物品 tooltip 回写坐标(1310–1337)也只加了 `±marginW`,y 没加。 3. `handleHudMouseDown()` 1367 起:腰带、红蓝球、热键、控制栏 1449–1483 用原始坐标;左右栏 1485–1542 用 `±marginW`,y 都没减 `panelOffsetY`。 `belt.ts`、`globes.ts`、`hotkeys.ts`、`control-bar.ts`、`inventory.ts`、`skill-tree-panel.ts`、`world-panels.ts`、`character-sheet.ts` 都按原生 800×600 坐标做命中测试,不知道视口档位,所以只能在 `HudManager` 里换算。 ## 期望修复 - 在 `HudManager` 里加一组"逻辑坐标 → 区域本地坐标"的换算,和 `render()` 用同一组 docking 量: - 左栏:`(x − leftDockX, y − panelOffsetY)` - 右栏:`(x − (rightDockX − 400), y − panelOffsetY)` - 控制栏:`(x − barOffsetX, y − barOffsetY)` - 三条输入路径都改用这组换算;悬停 tooltip 回写时反向加回(x 和 y 都要)。 - 800×600 下这组量正好等于现在的 `-marginW`、`+marginW`、`0`,行为不变。 - 不要在各组件里分别加偏移,避免再和 `render()` 不一致。 ## 验证 - 单测:800×600、1024×768、1068×600、1280×720 四档,各用按档位尺寸的 mock canvas 构造 `HudManager`(可参考 `tests/client/viewport-formula-profiles.test.ts` 里的 `createHudAt`),在**画面上的实际位置**点击:跑 / 走切换、小面板按钮、腰带格、物品栏格子、人物加点、仓库格子、技能树,断言对应动作触发;悬停断言 tooltip 位置和绘制位置一致。 - 浏览器:在 `play.html` 切到 1024×768、1068×600、1280×720,实际点一遍并截图存档。 ## 相关 - `feat/viewport-formula-resolutions`(`748f6ba`,待合入 main):按公式生成视口档位(`barOffsetX = (W − 800) / 2`、`barOffsetY = H − 600`、`panelOffsetY = (H − 600) / 2`),新增 1068×600、1280×720。只改了绘制和点击拦截,没动输入路径,所以同样有本问题。 - `handleHudMouseDown()` 的腰带 / 左栏点击附近目前还有未提交的改动,修复前先等它合入 main,再在其基础上改,避免冲突。
Sign in to join this conversation.
No Label
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: troytt/diablo2-web#542
No description provided.