Skip to content

可视化编辑器

目的与范围

可视化编辑器是一个基于浏览器的 3D 场景创建和操作工具,为构建 Three.js 场景提供完整的图形界面。它允许用户无需编写代码即可创建、导入、编辑和导出 3D 内容,具有实时渲染、可视化属性编辑和全面的撤销/重做功能。

有关展示 Three.js 功能的示例系统的信息,请参阅 示例浏览器。有关渲染架构详情,请参阅 WebGL 渲染管线

架构概览

SVG
100%

编辑器遵循中心辐射架构,Editor 类充当中央状态管理器,通过基于信号的事件系统协调 UI 组件。UI 组件(ViewportSidebarMenubarToolbar)与 Editor 实例交互,但不直接相互通信。

编辑器核心类

Editor 类管理场景状态、对象层次结构,并通过基于信号的发布-订阅系统协调所有编辑器子系统。

信号系统

SVG
100%

Editor 类在其构造函数中初始化 40+ 个信号 editor/js/Editor.js19-96。这些信号实现子系统间的解耦通信。例如,当对象被修改时,signals.objectChanged.dispatch(object) 通知所有注册的监听器,无需紧密耦合。

状态管理

属性类型用途
sceneTHREE.Scene主场景图
sceneHelpersTHREE.Scene辅助对象(网格、光源辅助器)
cameraTHREE.PerspectiveCamera默认编辑器相机
viewportCameraTHREE.Camera活动视口相机
selectedObject3D当前选中对象
geometriesObject几何体 UUID → 几何体映射
materialsObject材质 UUID → 材质映射
texturesObject纹理 UUID → 纹理映射
scriptsObject对象 UUID → 脚本数组映射
helpersObject对象 ID → 辅助器映射
camerasObject相机 UUID → 相机映射
materialsRefCounterMap跟踪材质使用计数

Editor 维护所有场景资源的字典,按 UUID 索引,支持高效查找和引用跟踪。materialsRefCounter 跟踪每个材质的对象使用数量,防止过早释放 editor/js/Editor.js123

JSON 序列化

SVG
100%

toJSON() 方法 editor/js/Editor.js703-741 序列化整个编辑器状态,包括场景层次结构、脚本、历史和项目配置。fromJSON() 方法 editor/js/Editor.js668-701 使用 THREE.ObjectLoader 重建场景,保留 UUID 和关系。

UI 组件层次结构

编辑器界面由五个主要 UI 组件组成,围绕中央视口排列。

SVG
100%

视口组件

Viewport 类管理 3D 渲染表面和对象操作控件。

SVG
100%

Viewport 组件管理三个渲染通道:

  1. 主场景渲染 editor/js/Viewport.js891
  2. 网格辅助器渲染(如果可见)editor/js/Viewport.js896
  3. 场景辅助器渲染(光源、相机、骨骼)editor/js/Viewport.js897

当对象被操作时,TransformControls 发出事件 editor/js/Viewport.js78-144,视口创建相应的命令对象以实现撤销/重做功能。

视口着色模式

模式实现用途
solid默认渲染标准材质显示
normalsscene.overrideMaterial = MeshNormalMaterial可视化表面法线
wireframescene.overrideMaterial = MeshBasicMaterial({wireframe: true})显示网格拓扑
realisticViewportPathtracer + three-gpu-pathtracer物理精确渲染

来源: editor/js/Viewport.js678-704

侧边栏组件

Sidebar 使用带四个主要标签页的标签面板结构。

SVG
100%

UIOutliner 组件 editor/js/Sidebar.Scene.js132 将场景层次结构显示为可折叠树,支持拖放重新排序。每个节点显示类型图标和相关资源(几何体、材质、脚本)editor/js/Sidebar.Scene.js100-128

菜单栏组件

SVG
100%

MenubarFile 组件使用导出器模块的动态导入提供导出功能 editor/js/Menubar.File.js250-445,在保持初始包体积小的同时支持多种导出格式。

撤销/重做的命令模式

编辑器通过 History 类和命令对象实现命令模式,启用完整的撤销/重做功能。

SVG
100%

命令类

命令类用途关键方法
AddObjectCommand向场景添加对象execute(): 添加对象, undo(): 移除对象
RemoveObjectCommand从场景移除对象AddObjectCommand 的逆操作
SetPositionCommand更改对象位置存储旧/新位置
SetRotationCommand更改对象旋转存储旧/新旋转
SetScaleCommand更改对象缩放存储旧/新缩放
SetGeometryCommand替换对象几何体交换几何体引用
SetMaterialCommand替换对象材质交换材质引用
SetValueCommand更改任意属性通用属性设置器
MultiCmdsCommand执行多个命令复合命令模式

命令可以通过 update() 方法与先前命令合并 editor/js/Command.js27-31,防止连续值变化(例如拖动滑块)导致历史记录泛滥。

历史持久化

SVG
100%

当配置中启用 settings/history editor/js/Config.js24 时,历史记录会与项目一起序列化并在会话间持久化 editor/js/History.js80-150。这允许用户在关闭并重新打开编辑器后仍能撤销更改。

文件加载系统

Loader 类通过动态模块加载支持导入 30+ 文件格式。

SVG
100%

动态导入策略

加载器使用动态 import() 按需加载格式特定的解析器 editor/js/Loader.js89-959,减少初始包体积:

// 示例:GLTF 加载
case 'glb':
    reader.addEventListener('load', async function(event) {
        const { GLTFLoader } = await import('three/addons/loaders/GLTFLoader.js');
        const loader = await createGLTFLoader();
        loader.parse(contents, '', function(result) {
            const scene = result.scene;
            scene.animations.push(...result.animations);
            editor.execute(new AddObjectCommand(editor, scene));
        });
    });

GLTF 加载器配置

createGLTFLoader() 函数 editor/js/Loader.js954-976 配置 GLTFLoader,包含:

KTX2 加载器通过 signals.rendererDetectKTX2Support 与渲染器能力同步 editor/js/Loader.js967

ZIP 档案支持

加载器可以提取和处理 ZIP 档案 editor/js/Loader.js747-760,自动检测 Poly 资产(model.obj + materials.mtl)或档案内的单个文件 editor/js/Loader.js842-951

存储与持久化

编辑器为配置和项目数据实现两层存储系统。

SVG
100%

自动保存实现

自动保存机制监听 10+ 个信号 editor/index.html163-173,并在 1000ms 无活动后触发防抖保存 editor/index.html145-157。防抖防止快速更改期间的过度写入:

let timeout;
function saveState() {
    if (editor.config.getKey('autosave') === false) return;
    clearTimeout(timeout);
    timeout = setTimeout(function() {
        editor.signals.savingStarted.dispatch();
        timeout = setTimeout(function() {
            editor.storage.set(editor.toJSON());
            editor.signals.savingFinished.dispatch();
        }, 100);
    }, 1000);
}

IndexedDB 模式

Storageeditor/js/Storage.js1-92 使用带单个对象存储的 IndexedDB:

数据库对象存储
threejs-editorstates0 (固定)完整项目 JSON

服务工作者与离线支持

编辑器注册服务工作者以实现离线功能和跨域隔离。

SVG
100%

服务工作者实现网络优先缓存策略 editor/sw.js284-323,该策略:

  1. 尝试从网络获取
  2. 为编辑器页面注入 COEP/COOP 头 editor/sw.js290-297
  3. 成功获取时更新缓存
  4. 网络失败时回退到缓存版本

这使 Draco、Rhino3dm 和 Basis Universal WASM 解码器能够使用 SharedArrayBuffer 获得更好性能。

国际化

Strings 类为 UI 文本提供多语言支持。

SVG
100%

字符串字典使用分层键(例如 menubar/file/opensidebar/object/positioneditor/js/Strings.js417-571。语言从 navigator.language 自动检测,但可在设置中更改 editor/js/Config.js5-7