requestAnimationFrame 不负责碰撞检测,需在回调中用 getBoundingClientRect 获取实时坐标并手动实现 AABB 判断;示例中通过比较 left/right/top/bottom 判断矩形是否重叠。

requestAnimationFrame 本身不负责碰撞检测,它只是驱动动画循环的工具;碰撞检测需要你手动在每一帧中计算元素位置并判断是否相交。关键在于把检测逻辑放进 rAF 回调里,配合元素实时坐标(如 getBoundingClientRect)做几何判断。
在 rAF 循环中持续获取元素位置
每次回调中调用 getBoundingClientRect() 获取元素当前视口坐标,这是最可靠的方式——它自动包含 transform、滚动偏移和缩放影响,比单纯读取 left/top 或 getComputedStyle 更准确。
示例:
function animate() {
const rectA = elA.getBoundingClientRect();
const rectB = elB.getBoundingClientRect();
// 后续用 rectA 和 rectB 做碰撞判断
if (isColliding(rectA, rectB)) {
console.log('撞上了');
}
requestAnimationFrame(animate);
}
animate();
实现矩形碰撞判断(轴对齐包围盒,AABB)
对大多数 DOM 元素(非旋转)来说,用 AABB 是高效又准确的选择。只需判断两个矩形在 x 和 y 轴上是否同时重叠:
- 水平方向重叠:rectA.left
- 垂直方向重叠:rectA.top
- 两者同时成立 → 发生碰撞
封装成函数更清晰:
function isColliding(r1, r2) {
return r1.left < r2.right &&
r2.left < r1.right &&
r1.top < r2.bottom &&
r2.top < r1.bottom;
}
处理 transform 位移或动态尺寸变化
如果元素靠 CSS transform(如 translateX/Y)移动,getBoundingClientRect 仍能正确返回视觉位置,无需额外解析 matrix。但要注意:若元素宽高由 JS 动态修改(比如 resize),需确保在调用 getBoundingClientRect 前 DOM 已完成重排(rAF 自然满足该条件,无需强制 reflow)。
避免踩坑:
- 不要用 offsetLeft/offsetTop —— 它们不响应 transform,也不含父容器 scroll 偏移
- 不要在 rAF 外缓存 rect 对象 —— 每帧必须重新获取,否则坐标过期
- 高频动画中,可考虑节流碰撞检测(如每 2–3 帧检测一次),降低 CPU 压力
结合动画状态做响应式处理
检测到碰撞后,常见操作包括暂停、反弹、触发事件或切换 class。建议用标志位或状态机控制行为,避免重复触发:
- 加一个 isCollidingNow 标志,只在“刚进入碰撞”时执行一次逻辑
- 碰撞后修改样式或属性(如改变 background-color),再让 rAF 继续驱动下一帧渲染
- 如需物理效果(如弹跳),应在 rAF 中更新速度/位置,并在下帧再次检测


















