You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用JavaScript检测DOM中环绕动画元素与固定元素的触碰

嘿,我来帮你搞定这个碰撞检测的需求!你已经搞定了圆形排列的stations和token的环绕动画,接下来要做的就是实时检测两者的碰撞并触发操作,下面是完整的解决方案:

1. 先补全你的圆形排列代码(你之前的代码没写完)

首先把stations排列成圆形的代码补全,确保每个station的位置都正确计算:

$(document).ready(function() {
  // 把.station元素排列成圆形
  const stations = $("#rotator .station").get();
  const totalStations = stations.length;
  const angleIncrement = (Math.PI * 2) / totalStations;
  const orbitRadius = 150; // 根据你的布局调整这个半径值
  const rotatorCenterX = $("#rotator").width() / 2;
  const rotatorCenterY = $("#rotator").height() / 2;

  stations.forEach((station, index) => {
    const currentAngle = angleIncrement * index;
    // 计算每个station的位置,减去自身宽高的一半让元素居中
    const xPos = rotatorCenterX + orbitRadius * Math.cos(currentAngle) - $(station).width() / 2;
    const yPos = rotatorCenterY + orbitRadius * Math.sin(currentAngle) - $(station).height() / 2;
    $(station).css({
      position: "absolute",
      left: `${xPos}px`,
      top: `${yPos}px`
    });
  });
});

2. 核心碰撞检测函数

写一个通用的矩形碰撞检测函数,判断两个元素的边界是否重叠:

function isColliding(el1, el2) {
  const rect1 = el1.getBoundingClientRect();
  const rect2 = el2.getBoundingClientRect();

  // 四个方向都不重叠才不算碰撞,取反就是碰撞状态
  return !(
    rect1.top > rect2.bottom ||
    rect1.bottom < rect2.top ||
    rect1.left > rect2.right ||
    rect1.right < rect2.left
  );
}

3. 实时检测动画中的碰撞

因为#token是CSS动画驱动的,我们要用requestAnimationFrame来同步浏览器渲染帧,确保每帧都检测一次碰撞,这样不会错过任何碰撞瞬间:

$(document).ready(function() {
  // 先执行上面的圆形排列代码

  const token = document.getElementById('token');
  const stations = document.querySelectorAll('.station');
  let lastHitStation = null; // 记录上一次碰撞的元素,避免重复触发操作

  function runCollisionCheck() {
    stations.forEach(station => {
      if (isColliding(token, station)) {
        // 这里写你要执行的特定操作
        if (station !== lastHitStation) {
          console.log(`碰到了station: ${station.dataset.id || station.textContent}`);
          // 比如给碰撞的station加高亮样式
          $(station).addClass('hit');
          lastHitStation = station;
        }
      } else {
        // 离开碰撞状态时移除样式(可选)
        $(station).removeClass('hit');
      }
    });

    // 持续检测下一帧
    requestAnimationFrame(runCollisionCheck);
  }

  // 启动检测
  runCollisionCheck();
});

4. 一些优化和注意事项

  • 避免重复触发:用lastHitStation记录上一次碰撞的元素,防止同一station在动画过程中被连续触发N次操作。
  • 适配CSS动画:不管你的#token是用transform还是top/left做动画,getBoundingClientRect()都会正确计算元素的实时位置,所以不用额外处理。
  • 性能友好:requestAnimationFrame只会在浏览器准备渲染的时候执行,比setInterval更高效,不会造成不必要的性能损耗。

举个例子,如果你的#token CSS动画是这样的:

@keyframes orbit {
  from {
    transform: rotate(0deg) translateX(150px) rotate(0deg);
  }
  to {
    transform: rotate(360deg) translateX(150px) rotate(-360deg);
  }
}

#token {
  position: absolute;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background-color: #ff4444;
  animation: orbit 8s linear infinite;
}

上面的JS检测代码完全能适配这种动画。

内容的提问来源于stack exchange,提问作者shrouk mansour

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 11:03:29