web worker 通过纯数学计算实现碰撞检测,不访问 dom 或 canvas。它使用轻量几何模型(如圆-圆、aabb)、扁平数据结构、空间分区与粗筛精算结合策略,并返回带 id 和类型标识的结构化结果,确保高效与解耦。

Web Worker 本身不能访问 DOM 或 Canvas,所以它不“检测图形是否重叠”,而是在纯数学空间里判断几何对象之间的位置关系。核心思路是:把碰撞逻辑完全抽象为坐标、半径、顶点、法向量等数值计算,Worker 只负责算出“哪些对象发生了碰撞”,主线程再据此做视觉反馈或物理响应。
碰撞类型要选对,别硬算所有情况
不是所有几何组合都需要高精度检测。根据实际需求选择轻量但够用的模型:
- 圆与圆:直接算圆心距平方 vs 半径和平方,一行代码搞定
- 轴对齐矩形(AABB)与圆:用 clamp 求矩形上离圆心最近的点,再算距离平方
-
AABB 与 AABB:检查 x 和 y 方向投影是否重叠(
rect1.x ) - 线段与圆 / 线段与线段:仅在必要时用向量叉积+点积解交点,避免开方和除零
- 多边形之间:小游戏尽量避免;若必须,可用分离轴定理(SAT),但只针对凸多边形且顶点数 ≤8
⚠️ 不推荐在 Worker 中实时跑像素级轮廓比对、贝塞尔曲线精确交点或任意复杂形状的布尔运算——这些开销大、难收敛,也不适合 Web Worker 的无状态批量处理模式。
数据结构要扁平,别传对象树
Worker 接收的输入必须是可序列化或可 transferable 的原始数据。例如:
// ✅ 好:扁平数组,支持 transferable
const particles = new Float32Array([
x1, y1, r1, vx1, vy1,
x2, y2, r2, vx2, vy2,
// ...
]);
// ❌ 避免:嵌套对象、函数、DOM 引用
{
circles: [{x:10,y:20,r:5}, {x:30,y:40,r:8}],
obstacles: [new Path2D("M0,0 L100,0")]
}
主线程用 postMessage(particles, [particles.buffer]) 把内存所有权移交给 Worker,避免拷贝延迟。
碰撞检测要有层级,先粗筛再精算
粒子或对象一多,O(n²) 全对检测立刻卡住。Worker 内应实现两级策略:
空间分区(如网格哈希)
将画布划分为若干格子(比如 32×32 像素一格),每帧把每个对象映射到对应格子索引,只检查同一格及相邻 8 格内的对象对。距离粗筛 + 类型分支
对候选对象对,先快速排除:dx*dx + dy*dy > (r1 + r2) * (r1 + r2)→ 跳过
满足后再按类型走具体逻辑(圆-圆?矩形-圆?)
这样几百个对象也能保持 60fps 计算节奏。
结果返回要结构化,带上下文标识
Worker 不该只返回“true/false”,而应输出可直接用于渲染或响应的结构化结果:
postMessage({
type: 'collision',
pairs: [
{ idA: 5, idB: 12, type: 'circle-circle', depth: 0.7 },
{ idA: 3, idB: 8, type: 'aabb-circle', normal: [0.9, -0.4] }
],
timestamp: performance.now()
});
主线程收到后,可:
- 触发 Canvas 爆炸动画(idA 和 idB 位置)
- 修改物理速度(用 normal 做反射)
- 高亮 DOM 元素(如果 id 对应真实节点)
只要 ID 映射一致,前后端逻辑就完全解耦。
不复杂但容易忽略:每次计算前,确保所有输入坐标已归一化或统一到同一参考系(比如全转成 canvas 坐标),否则看似算对了,实际位置错位。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











