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

如何在Autodesk Forge Viewer中添加输入控件并实现选中对象坐标的显示与修改?

在Autodesk Forge Viewer中添加输入控件并同步对象坐标

我来帮你搞定这个需求,直接上可落地的代码和步骤,不用找示例源码啦!

第一步:添加HTML输入控件到Viewer界面

Forge Viewer本质是嵌入在网页中的WebGL应用,咱们可以直接创建HTML元素作为控制面板,然后把它挂载到Viewer容器旁边或者内部。比如创建一个包含文本框、滑块的面板:

<!-- 先在页面里加个控制面板容器 -->
<div id="control-panel" style="position: absolute; top: 20px; right: 20px; background: white; padding: 15px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); z-index: 1000;">
  <h4>对象坐标控制</h4>
  <div style="margin: 10px 0;">
    <label>X坐标:</label>
    <input type="number" id="coord-x" step="0.1" style="width: 80px; margin-left: 5px;">
    <input type="range" id="slider-x" min="-100" max="100" step="0.1" style="width: 120px; margin-left: 5px;">
  </div>
  <div style="margin: 10px 0;">
    <label>Y坐标:</label>
    <input type="number" id="coord-y" step="0.1" style="width: 80px; margin-left: 5px;">
    <input type="range" id="slider-y" min="-100" max="100" step="0.1" style="width: 120px; margin-left: 5px;">
  </div>
  <div style="margin: 10px 0;">
    <label>Z坐标:</label>
    <input type="number" id="coord-z" step="0.1" style="width: 80px; margin-left: 5px;">
    <input type="range" id="slider-z" min="-100" max="100" step="0.1" style="width: 120px; margin-left: 5px;">
  </div>
  <button id="apply-coords" style="margin-top: 10px; padding: 5px 10px;">应用坐标</button>
</div>

这段代码会在Viewer右上角生成一个带输入框、滑块和按钮的控制面板,样式可以根据你的需求调整。

第二步:监听对象选中事件,同步坐标到控件

接下来咱们要监听Viewer的选中事件,当用户选中某个对象时,自动获取它的当前XYZ坐标并填充到输入控件里:

let selectedDbId = null;

// 监听Viewer的选中事件
viewer.addEventListener(Autodesk.Viewing.SELECTION_CHANGED_EVENT, (event) => {
  if (event.dbIdArray.length === 1) {
    selectedDbId = event.dbIdArray[0];
    // 获取选中对象的世界坐标
    const fragList = viewer.model.getFragmentList();
    const node = viewer.model.getData().instanceTree.getNode(selectedDbId);
    let worldMatrix = new THREE.Matrix4();
    
    // 如果是实例化的对象,获取实例矩阵;否则获取节点矩阵
    if (node.fragments) {
      fragList.getWorldMatrix(node.fragments[0], worldMatrix);
    } else {
      worldMatrix.copy(node.matrixWorld);
    }
    
    // 从矩阵中提取平移分量(XYZ坐标)
    const position = new THREE.Vector3();
    position.setFromMatrixPosition(worldMatrix);
    
    // 更新输入控件的值
    document.getElementById('coord-x').value = position.x.toFixed(1);
    document.getElementById('slider-x').value = position.x.toFixed(1);
    document.getElementById('coord-y').value = position.y.toFixed(1);
    document.getElementById('slider-y').value = position.y.toFixed(1);
    document.getElementById('coord-z').value = position.z.toFixed(1);
    document.getElementById('slider-z').value = position.z.toFixed(1);
  } else {
    selectedDbId = null;
    // 未选中对象时清空控件
    document.getElementById('coord-x').value = '';
    document.getElementById('slider-x').value = '0';
    document.getElementById('coord-y').value = '';
    document.getElementById('slider-y').value = '0';
    document.getElementById('coord-z').value = '';
    document.getElementById('slider-z').value = '0';
  }
});

// 同步滑块和输入框的值(拖动滑块时更新输入框,输入框修改时更新滑块)
['x', 'y', 'z'].forEach(axis => {
  const input = document.getElementById(`coord-${axis}`);
  const slider = document.getElementById(`slider-${axis}`);
  
  input.addEventListener('input', () => {
    slider.value = input.value;
  });
  
  slider.addEventListener('input', () => {
    input.value = slider.value;
  });
});

这段代码里,我们通过SELECTION_CHANGED_EVENT监听选中状态,然后从对象的世界矩阵中提取平移坐标,同步到输入框和滑块上,同时让滑块和输入框的值双向绑定。

第三步:通过控件修改对象坐标

最后实现点击“应用坐标”按钮,或者直接修改输入框/滑块后,更新选中对象的位置:

document.getElementById('apply-coords').addEventListener('click', () => {
  if (!selectedDbId) return;
  
  // 获取输入的坐标值
  const x = parseFloat(document.getElementById('coord-x').value) || 0;
  const y = parseFloat(document.getElementById('coord-y').value) || 0;
  const z = parseFloat(document.getElementById('coord-z').value) || 0;
  
  // 获取对象当前的变换矩阵
  const fragList = viewer.model.getFragmentList();
  const node = viewer.model.getData().instanceTree.getNode(selectedDbId);
  let currentMatrix = new THREE.Matrix4();
  
  if (node.fragments) {
    fragList.getWorldMatrix(node.fragments[0], currentMatrix);
  } else {
    currentMatrix.copy(node.matrixWorld);
  }
  
  // 创建新的平移矩阵,保持旋转和缩放不变
  const newPosition = new THREE.Vector3(x, y, z);
  currentMatrix.setPosition(newPosition);
  
  // 更新对象的变换矩阵
  viewer.model.setNodeTransform(selectedDbId, currentMatrix);
  
  // 刷新Viewer显示
  viewer.impl.sceneUpdated(true);
});

这里我们获取输入的坐标,在保持对象原有旋转和缩放的前提下,修改其平移位置,然后通过setNodeTransform方法更新对象,最后刷新Viewer界面。

额外优化:同步Transform工具的移动操作

如果你用Transform工具移动对象后,希望输入控件也自动更新坐标,可以监听TRANSFORM_CHANGED_EVENT:

// 监听Transform工具的变换事件,同步坐标
viewer.addEventListener(Autodesk.Viewing.TRANSFORM_CHANGED_EVENT, (event) => {
  if (selectedDbId && event.dbIdArray.includes(selectedDbId)) {
    // 重新获取坐标并更新控件,和SELECTION_CHANGED_EVENT里的逻辑一致
    const fragList = viewer.model.getFragmentList();
    const node = viewer.model.getData().instanceTree.getNode(selectedDbId);
    let worldMatrix = new THREE.Matrix4();
    
    if (node.fragments) {
      fragList.getWorldMatrix(node.fragments[0], worldMatrix);
    } else {
      worldMatrix.copy(node.matrixWorld);
    }
    
    const position = new THREE.Vector3();
    position.setFromMatrixPosition(worldMatrix);
    
    document.getElementById('coord-x').value = position.x.toFixed(1);
    document.getElementById('slider-x').value = position.x.toFixed(1);
    document.getElementById('coord-y').value = position.y.toFixed(1);
    document.getElementById('slider-y').value = position.y.toFixed(1);
    document.getElementById('coord-z').value = position.z.toFixed(1);
    document.getElementById('slider-z').value = position.z.toFixed(1);
  }
});

这样用户用Transform工具移动对象后,输入控件里的坐标也会自动同步啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 09:07:35