访问与修改 3D 对象的视图属性
加载完成后从 viewer.doc 取得 Document。节点状态位于 mainStore 的 nodes.present.byId:
const doc = viewer.doc;
const state = doc.mainStore.getState();
const node = state.nodes.present.byId[nodeId];
console.log(node.name, node.visible, node.material, node.matrix, node.renderType);
修改可见性
SET_NODES_VISIBLE 的 payload 是 { [nodeId]: boolean },支持一次修改多个节点:
import { types } from "@tuo/document";
doc.dispatch({
type: types.SET_NODES_VISIBLE,
payload: { [nodeId]: false },
});
doc.dispatch({
type: types.SET_NODES_VISIBLE,
payload: { [nodeId]: true, [anotherNodeId]: false },
});
也可以使用 Document 的便捷方法:
doc.setVisibleByName("housing", false);
doc.setVisibleByIndex(0, true);
修改面、线和点的材质
材质分为 face、line 和 point 三类。SET_NODES_MATERIAL 可以只修改部分字段,未提供的旧字段会保留:
doc.dispatch({
type: types.SET_NODES_MATERIAL,
payload: {
[nodeId]: {
face: {
color: 0xff0000,
transparent: true,
opacity: 0.45,
vertexColors: false,
side: "front",
},
line: { color: 0x222222 },
},
},
});
常用属性:
| 属性 | 作用 |
|---|---|
color | 十六进制颜色值 |
transparent | 是否启用透明渲染 |
opacity | 透明度,通常为 0 到 1 |
side | front、back 或 double |
vertexColors | 是否使用顶点颜色 |
metalness / roughness | PBR 材质属性 |
按名称或索引修改:
doc.setMaterialById(nodeId, { face: { color: 0x3366ff, opacity: 0.7 } });
doc.setMaterialByName("housing", { line: { color: 0xffffff } });
doc.setMaterialByIndex(0, { face: { color: 0xff8800 } });
如果要替换而不是合并旧材质,可在 dispatch payload 中使用 reomveOld: true(该字段名称与当前源码保持一致):
doc.dispatch({
type: types.SET_NODES_MATERIAL,
reomveOld: true,
payload: { [nodeId]: { face: { color: 0xffffff } } },
});
切换渲染方式和内外侧
使用 SET_NODES_RENDERTYPE 修改节点的渲染类型;使用材质的 side 控制内外侧:
doc.dispatch({
type: types.SET_NODES_RENDERTYPE,
payload: { [nodeId]: "wire" },
});
doc.dispatch({
type: types.SET_NODES_MATERIAL,
payload: { [nodeId]: { face: { side: "back" } } },
});
实际可用的渲染类型以当前 Viewer/Document 版本为准,生产项目应在目标版本中验证。
修改变换矩阵
节点的 matrix 是 16 个数字组成的矩阵。可以直接提交矩阵,也可以进入 transform 模式让用户交互调整:
doc.dispatch({
type: types.SET_NODES_MATRIX,
payload: {
[nodeId]: [1, 0, 0, 10, 0, 1, 0, 0, 0, 0, 1, 5, 0, 0, 0, 1],
},
});
交互变换流程:
doc.dispatch({ type: types.START_PROCESS, payload: { type: "transform", config: {} } });
doc.dispatch({ type: types.SET_PROCESS, payload: { transformType: "translate" } });
// 或 transformType: "rotate"
doc.dispatch({ type: types.APPLY_PROCESS });
doc.dispatch({ type: types.QUIT_PROCESS });
变换模式下的操作在调用 APPLY_PROCESS 前不会正式写入节点。
读取和批量处理
const nodes = doc.mainStore.getState().nodes.present.byId;
const objectNodes = Object.values(nodes).filter((item) => item.type === "object");
const payload = Object.fromEntries(objectNodes.map((item) => [item.clientId, { face: { color: 0x6688aa } }]));
doc.dispatch({ type: types.SET_NODES_MATERIAL, payload });
建议保存业务对象 ID 与 Document 节点 ID 的映射,不要保存底层 Three.js 对象或 entityCache 引用。可见性、材质和矩阵修改默认作用于当前 Document;需要持久化时保存操作参数或重新生成模型数据。