Appearance
viewer.views — ViewsManager
设计意图
viewer.views 管视图——一个可复现的场景结果态。它做两件事:把当前场景读成一份可序列化的 ViewState(capture),以及把这样一份状态重新套回场景(apply)。一份视图涵盖相机位姿与投影、显示模式、隐藏集、逐件变换覆盖、逐件与逐面外观(颜色 / 金属度粗糙度 / 材质预设)、序号标签及其样式——也就是「上次看到的那一眼」需要的全部信息。
在此之上,本域还持有一份视图信封(.fmbview.json,类型 ViewDocument)做视图集导航:list / activate / next / prev 把多个视图串成一条可翻页的序列,isDirty 告诉宿主「用户已经把当前视图看歪了」,resetToCurrent 一步复位。信封通常在 model.load() 的 view-on-load 里自动装载(见加载时应用视图),也可以由宿主经 loadDocument() 手动喂(拖入 sidecar 文件)。
apply 走的是不记录 undo 的批量还原原语——切视图是导航,不是编辑,不会污染 viewer.history 的撤销栈。
何时用它:分享链接里带的初始视角、装配讲解的分步视图翻页、「回到这一步」的复位按钮。逐条捕获 / 应用的语义细节见视图集导航。
典型用法
捕获当前场景并存盘,之后原样复现:
ts
const state = viewer.views.capture(); // 纯 JSON,可直接 JSON.stringify
localStorage.setItem("last-view", JSON.stringify(state));
// ……下次加载完模型后
viewer.views.apply(JSON.parse(localStorage.getItem("last-view")!), { animate: false });视图集翻页(Share 形态的视图导航器就是这么接的):
ts
const views = viewer.views.list(); // readonly ViewDocumentView[]
nextBtn.onclick = () => viewer.views.next(); // 到尾不循环,返回 false
prevBtn.onclick = () => viewer.views.prev();
viewer.views.activate("爆炸图"); // 按 id、name 或整数索引切订阅 view-changed 驱动导航器 UI(切视图、装载 / 清空信封、偏离翻转都发这一个事件):
ts
viewer.on("view-changed", (e) => {
navLabel.textContent = e.count ? `${e.index + 1} / ${e.count} · ${e.name}` : "";
resetBtn.hidden = !e.dirty; // 用户动过场景才显示「复位」
});
resetBtn.onclick = () => viewer.views.resetToCurrent();宿主手动装载 sidecar(拖入 .fmbview.json):
ts
const ok = viewer.views.loadDocument(await file.text()); // 解析/签名/空信封失败返回 false
if (!ok) toast("这份视图文件与当前模型不匹配");注意事项
apply默认带动画({ animate: true }):相机 400ms 补间,外观走材质渐变,变换走位置补间。首帧复现视图时传{ animate: false },否则会看到一段「飞入」。apply不入撤销栈,capture/apply都不产生history步;但apply会发visibility-changed/appearance-changed/transform-changed等状态事件,订阅方按常规刷新即可。isDirty只看四个通道:相机(位移超过场景半径的 0.5%)、可见性、变换覆盖、爆炸导致的包围球外扩。改颜色不翻 dirty。activate/loadDocument失败返回false而不抛:未命中 selector、信封为空、签名(nodeCount)与当前模型不符,都是「不改变现状 + 返回 false」。- 换模型自动清空信封:
model-disposed时clearDocument()自动执行,hasDocument转 false、currentIndex回 -1。 displayMode的"xray"是 UI 概念,引擎没有对应渲染档——apply遇到"xray"保持当前显示模式不变;capture不传opts.displayMode时由引擎renderMode反推,永远不会产出"xray"。ViewState是纯 JSON(裸number节点 id、{x,y,z}相机),可以直接落盘 / 走网络,不含任何引擎对象引用。
完整签名与延伸
ViewsManager— 全部方法与属性的精确签名。ViewState/ViewDocument/ViewDocumentView— 视图与信封的数据形状。CaptureViewOptions/ApplyViewOptions— 捕获与应用选项。- 指南:视图集导航 — 翻页、偏离与复位的完整接法;加载时应用视图 — 让首帧就落在正确视角。
- 概念:事件系统 —
view-changed/view-applied事件参考。