如何在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
相关产品推荐
相关产品推荐

