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

如何判断模型是否超出查看器容器可视范围,isNodeVisible始终返回true如何解决

你遇到的isNodeVisible始终返回true的核心原因是:绝大多数3D场景查看器的isNodeVisible方法仅判断节点本身的「显式可见属性」,也就是你是否手动调用过接口将节点设置为隐藏状态,不会判断节点是否在当前视口范围内、是否被其他模型遮挡。你旋转视角让模型移出屏幕/被遮挡时,节点本身的可见属性没有变更,所以方法始终返回true。

解决方法

你需要结合「世界坐标转屏幕坐标的范围判断」+ 可选的「遮挡射线检测」来实现需求,修改后的代码如下:

updateInfoCard() {
  if (this.infoCard && this.posModel) {
    const pos = this.viewer.worldToClient(this.posModel);
    // 先获取viewer画布的实际宽高,不同SDK获取画布的方法可能有差异,根据实际调整
    const viewerCanvas = this.viewer.canvas;
    const viewerWidth = viewerCanvas.clientWidth;
    const viewerHeight = viewerCanvas.clientHeight;

    // 第一步:判断节点是否在屏幕可视范围内
    const isInViewport = pos.x >= 0 && pos.x <= viewerWidth && pos.y >= 0 && pos.y <= viewerHeight;
    if (!isInViewport) {
      this.infoCard.style.display = 'none';
      return;
    }

    // 第二步(可选,需要判断遮挡时开启):射线检测判断是否被其他模型遮挡
    const id = this.infoCard.dataset.id;
    // 不同SDK射线检测方法名、传参可能有差异,根据对应文档调整
    const rayResult = this.viewer.raycast({x: pos.x, y: pos.y});
    const isNotBlocked = rayResult && rayResult[0]?.nodeId === id;

    // 卡片位置更新
    this.infoCard.style.left = `${Math.floor(
      50 + pos.x - this.infoCard.offsetWidth / 2
    )}px`;
    // 注意原代码这里误用了offsetWidth计算top,已修正为offsetHeight
    this.infoCard.style.top = `${Math.floor(
      50 + pos.y - this.infoCard.offsetHeight / 2
    )}px`;

    // 最终显隐判断
    this.infoCard.style.display = isInViewport && isNotBlocked ? "block" : "none";
  }
}

注意事项

  • 如果不需要判断模型被其他物体遮挡的场景,直接删除射线检测相关逻辑,仅用isInViewport判断即可
  • 射线检测的方法名、返回值格式根据你使用的3D查看器SDK不同会有差异,请参考对应官方文档调整参数

内容的提问来源于stack exchange,提问作者surya kumara

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 01:15:07