# 使让绘制目标与指针命中测试使用同一套坐标映射

> 将指针位置转换为游戏世界坐标，以便可见目标和可点击的点击区域在缩放后保持对齐。

- URL: https://oneshotgems.ai/zh-Hans/topics/hit-testing-canvas-coordinates
- 类别: 游戏开发者指南
- 类型: 指南
- 更新日期: 2026年10月5日

画布按钮可能看起来位于指针下方的中心，但仍然会错过，因为事件是以视口像素来测量的，而游戏是以逻辑世界单位绘制的。选择一个坐标系进行命中测试，然后通过用于绘制游戏区域的相同显示变换来转换每个指针位置。本指南重点关注这种转换。它通过跟踪从页面到逻辑目标的单个指针（包括固定大小游戏周围的黑边区域（letterboxing））来补充响应式布局规划。

## 减去画布原点并缩放点

从事件的 clientX 和 clientY 以及 canvas.getBoundingClientRect() 返回的矩形开始。该矩形相对于视口定位，因此在缩放之前减去其左侧和顶部。如果逻辑游戏是 800 x 450 并且显示的矩形是 400 x 225，则将局部 x 和 y 乘以 2。然后，无论页面的滚动位置如何，显示中心的指针都会映射到逻辑 (400, 225)。

使用实际的内容矩形，而不是基于窗口宽度的假设。考虑画布外部的 CSS 边框或填充，并在调整大小或方向更改后刷新映射。如果游戏使用摄像机偏移、信箱或其他世界变换，请在将该点与游戏的命中区域进行比较之前以相反的顺序反转这些操作。

## 测试整个表面，包括死角

在转换后的指针位置放置一个临时十字准线，并测试画布的所有四个角、中心和目标的每个边缘。一个简单的校准检查是单击绘制的圆的中心并确认报告的世界点位于圆的中心附近。然后在其外部单击以检查命中边界是否与预期的容错裕度相符。 MDN 将 clientX 记录为相对于视口的元素边界，并将 getBoundingClientRect() 记录为返回相对于视口的元素边界；将这些测量配对可以避免混合坐标空间。

## 保持渲染和点击区域链接

存储目标的世界位置和尺寸一次，然后使用该数据来绘制它并针对它测试指针。避免为可见图标和单击区域维护单独的手动输入屏幕坐标。更改画布比例、CSS 大小、设备像素比或相机偏移后重新测试。如果坐标探针正确但目标仍然未命中，请检查其形状数学和输入顺序，而不是添加任意像素偏移。

## 常见问题

**我应该使用 offsetX 和 offsetY 来进行画布点击吗？** 它们对于简单的未转换画布来说很方便，但显式的客户端坐标、元素边界和游戏转换使布局或相机缩放发生变化时每个转换步骤更加清晰。

**devicePixelRatio 属于指针转换吗？** 仅当您的指针指向并命中区域使用后备存储像素时。一种常见的方法是将视口坐标映射到逻辑游戏单元，在渲染变换中保持设备像素缩放。

## 跟随好奇心探索

- [使用指针事件进行浏览器游戏输入](https://oneshotgems.ai/zh-Hans/topics/pointer-events-for-games): 通过指针事件对鼠标、笔和触摸进行建模，同时在游戏循环中保留捕获、设备标识和兼容性行为。
- [为浏览器游戏构建响应式布局](https://oneshotgems.ai/zh-Hans/topics/responsive-game-layouts): 使游戏表面适应其容器，而不将模拟状态与屏幕尺寸联系起来，并在不断变化的视口中测试布局。

## 延伸阅读

- [MDN 客户端X](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/clientX)
- [MDN getBoundingClientRect](https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect)

---
规范页面: https://oneshotgems.ai/zh-Hans/topics/hit-testing-canvas-coordinates
