如何判断模型是否超出查看器容器可视范围,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
相关产品推荐
相关产品推荐

