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

如何在Forge Viewer中实现绑定模型的闪烁标记?

解决模型查看器中标记随相机视角偏移的问题

当前实现的核心问题是:闪烁标记作为独立2D DOM元素存在,未与模型的3D空间位置绑定。相机视角变化时,模型的屏幕投影坐标更新,但标记位置未同步,导致偏移。要解决这个问题,必须让标记跟随模型上的目标3D点,同步其屏幕投影位置。

方案一:使用模型查看器内置标注功能(推荐)

如果使用Google的<model-viewer>组件,它内置的标注系统可以自动将标记绑定到模型3D坐标,无需手动处理视角同步。

实现步骤

  1. 在<model-viewer>内部添加<annotation>元素,通过position属性指定模型上目标点的3D坐标(格式为X Y Z)。
  2. 将原有的SVG闪烁标记作为<annotation>的内容,保留动画逻辑。

代码示例

<!-- 基础模型查看器结构 -->
<model-viewer id="myModelViewer" src="your-model.glb" camera-controls></model-viewer>

<script>
const randomId = "your-unique-id";
// 创建标注元素
const annotation = document.createElement('annotation');
annotation.setAttribute('position', '0 1.5 0'); // 替换为模型目标点的3D坐标
annotation.setAttribute('id', `mymk${randomId}`);

// 创建SVG容器
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg.setAttribute('id', `mysvg${randomId}`);
svg.style.width = '50px';
annotation.appendChild(svg);

// 复用原有的Snap.svg动画逻辑
const size = 300;
const s = Snap(svg);
s.attr({viewBox: `0 0 ${size} ${size}`});
const userPath = s.path("M500,10C229.4,10,10,229.4,10,500c0,270.6,219.4,490,490,490c270.6,0,490-219.4,490-490S770.6,10,500,10z M496.2,255c70,0,126.7,56.7,126.7,126.7s-56.7,126.7-126.7,126.7s-126.7-56.7-126.7-126.7C369.5,311.7,426.3,255,496.2,255z M629.1,745h-266c-25.8,0-78.2-21.1-78.2-46.8v0c0-85.8,70.4-156,156.4-156h109.5c86,0,156.4,70.2,156.4,156C707.4,723.9,654.9,745,629.1,745z")
    .attr({fill: "#029e02"});
const userBox = userPath.getBBox();
const circleBg = s.circle(userBox.cx, userBox.cy, userBox.width / 2)
    .attr({fill: "#029e02", stroke: "#029e02", strokeWidth: 800});
const user = s.group(circleBg, userPath);

const userScaleFactor = 0.09;
const userMtx = new Snap.Matrix();
userMtx.translate(size/2 - userBox.width*userScaleFactor / 2, size/2 - userBox.height*userScaleFactor/2);
userMtx.scale(userScaleFactor);
user.attr({transform: userMtx, cursor: "pointer"});
const smallUserMtx = userMtx.clone().scale(0.9, 0.9, userBox.cx, userBox.cy);
setInterval(blink, 3000);

function blink(){
    user.animate({transform: smallUserMtx}, 200, mina.easein, () => user.animate({transform: userMtx}, 200));
    const newCircle = s.circle(size/2, size/2, 40);
    user.before(newCircle);
    newCircle.attr({fill: "rgb(244, 203, 217)", strokeWidth: "20", stroke: "#015401"});

    newCircle.animate({r: size/2, opacity: 0}, 2000, mina.easeout, () => newCircle.remove());
};

user.attr({
    pointerEvents: "auto",
    cursor: "pointer"
});

// 将标注添加到模型查看器
document.getElementById('myModelViewer').appendChild(annotation);
</script>

方案二:手动跟踪3D点投影(自定义模型查看器)

如果使用自定义模型查看器(如基于Three.js的实现),需要手动将模型3D坐标转换为屏幕坐标,并实时更新标记位置。

实现步骤

  1. 获取模型目标点的局部3D坐标(可通过Blender等编辑器导出顶点坐标)。
  2. 监听相机视角变化事件,在回调中完成3D坐标到屏幕坐标的转换。
  3. 更新SVG标记的位置,使其与目标点的屏幕坐标对齐。

代码示例(基于Three.js)

// 假设已初始化scene、camera、model对象
const targetPoint = new THREE.Vector3(0, 0, 0); // 模型目标点的局部坐标
const svgElement = $(`#mysvg${randomId}`);

function updateMarkerPosition() {
    // 将局部坐标转换为世界坐标
    const worldPoint = targetPoint.clone().applyMatrix4(model.matrixWorld);
    // 将世界坐标转换为屏幕坐标
    const screenPoint = worldPoint.clone().project(camera);
    
    // 转换为DOM像素坐标
    const x = (screenPoint.x + 1) * window.innerWidth / 2;
    const y = (-screenPoint.y + 1) * window.innerHeight / 2;
    
    // 调整偏移量,让SVG中心对准目标点
    svgElement.css({
        position: 'absolute',
        left: `${x - 25}px`, // SVG宽度50px,减去一半实现中心对齐
        top: `${y - 25}px`
    });
}

// 绑定相机变化事件
document.getElementById('your-model-viewer').addEventListener('camera-change', updateMarkerPosition);
// 或在渲染循环中持续更新
function renderLoop() {
    requestAnimationFrame(renderLoop);
    updateMarkerPosition();
    // 其他渲染逻辑
}
renderLoop();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 18:55:35