如何构建一个基于WebGL的富文本编辑器?

302 阅读4分钟

在使用 THREE.js 开发 3D Web 应用时,将可编辑文本集成到 3D 场景中是一项具有挑战性的任务。传统的富文本编辑器依赖 HTML 和 CSS 来渲染内容,而这与 WebGL 渲染流程不兼容。为了解决这个问题,我们构建了一个 WebGL 原生的富文本编辑器,结合了 TinyMCE 的编辑能力与 THREE.js 的 3D 渲染能力,借助 @mlightcad/mtext-renderer 库完成文本渲染工作。

为什么要基于 WebGL 的文本编辑器?

大多数 Web 富文本编辑器依赖于 DOM 渲染机制,这在传统文档中很好用,但在 3D 场景中就行不通了。我们的解决方案:

  • 使用 THREE.js 将文本作为几何体在 WebGL 场景中渲染
  • 支持丰富的文本样式,包括加粗、斜体、下划线、列表等
  • 支持将编辑内容转换为 CAD 使用的 MText 格式,便于集成和导出

系统架构

我们的编辑器整合了以下核心技术:

  • TinyMCE:功能强大的富文本编辑器,负责文字输入与格式化。
  • AutoCAD MText:一种结构化的文本格式,广泛用于 CAD 场景中的复杂文本表示。
  • @mlightcad/mtext-renderer:一个基于 THREE.js 的渲染器,用于在 3D 场景中渲染 MText 文本。

这种架构使用户可以在熟悉的界面中编辑文本,并将其实时呈现在 3D WebGL 场景中。

主要功能

WebGL 原生文本渲染

所有文本内容都被转化为几何体并由 WebGL 渲染,完全不依赖 HTML/CSS。

使用 TinyMCE 提供完整的格式支持

支持以下富文本样式:

  • 字体样式:字体、字号、加粗、斜体、下划线、上划线、删除线
  • 高级排版:下标、上标、分数
  • 字符控制:字间距、字宽
  • 对齐方式:左对齐、居中、右对齐、两端对齐
  • 列表:项目符号和编号列表

实时场景更新

用户在 TinyMCE 中编辑的内容会实时同步到 3D 场景中,无需手动刷新。

支持 AutoCAD MText 格式

所有格式化文本会被转换为 AutoCAD 使用的 MText 格式,便于在 CAD 工作流程中使用。

字体加载与缓存机制

通过 IndexedDB 本地缓存字体数据,提高加载速度,支持缺字替代和默认字体降级处理。

从 TinyMCE 到 AutoCAD MText 的转换

为了在 THREE.js 中渲染富文本内容,我们需要将 TinyMCE 的内容模型转换为 AutoCAD 的 MText 字符串。

转换流程

转换过程分为两个主要步骤:

  1. 解析 TinyMCE 的数据模型

    TinyMCE 使用树状结构描述内容和样式。转换器会遍历每个节点,提取如加粗、字体、颜色、字号、间距等样式信息。

  2. 生成 MText 格式指令

    提取到的样式被转换为 MText 指令,例如:

    • \f 表示字体(如:\fArial|b1|i0;
    • \C\c 表示颜色(ACI 颜色和 RGB 颜色)
    • \H\W\T 表示字号、字宽、字距
    • \L\O\K 表示下划线、上划线、删除线
    • \S 用于上标、下标和分数
    • \P 表示段落换行,\px...; 表示段落格式属性

若节点具有样式,转换器会用 {} 将其包装,从而支持嵌套样式与局部格式控制。

在线演示

您可以通过以下链接在线体验该编辑器:

屏幕截图 2025-06-30 161407.png

MText 渲染器架构概览

@mlightcad/mtext-renderer 是一个模块化的 MText 渲染库,核心组件包括:

  • FontManager:管理字体加载、缓存和字符轮廓提取。
  • FontLoader:从 JSON 或自定义源加载字体信息。
  • FontCacheManager:通过 IndexedDB 缓存字体数据。
  • FontFactory:根据字体类型(SHX 或网格字体)创建实例。
  • BaseFont / BaseTextShape:字体与字符图形的抽象基类。
  • MText:主类,用于组织和渲染富文本块。

类结构图(简化版)

classDiagram
    MText --> FontManager
    MText --> StyleManager
    FontManager --> FontFactory
    FontManager --> FontCacheManager
    FontManager --> BaseFont
    DefaultFontLoader ..|> FontLoader
    BaseFont <|-- MeshFont
    BaseFont <|-- ShxFont
    BaseTextShape <|-- MeshTextShape
    BaseTextShape <|-- ShxTextShape

使用示例

import * as THREE from 'three';
import { DefaultFontLoader, FontManager, MText, StyleManager } from '@mlightcad/mtext-renderer';

const fontManager = FontManager.instance;
const styleManager = new StyleManager();
const fontLoader = new DefaultFontLoader();

await fontLoader.load(['simsun']); // 加载字体

const content = {
  text: '{\fArial|b0|i0|c0|p34;Hello World}',
  height: 0.1,
  width: 0,
  position: new THREE.Vector3(0, 0, 0),
};

const style = {
  name: 'Standard',
  fixedTextHeight: 0.1,
  widthFactor: 1,
  font: 'Standard',
  color: 0xffffff,
  obliqueAngle: 0,
  textGenerationFlag: 0,
  lastHeight: 0.1,
  bigFont: '',
  standardFlag: 0,
};

const mtext = new MText(content, style, styleManager, fontManager);
scene.add(mtext);

应用场景

  • 3D 标注工具
  • 技术文档可视化
  • CAD 阅读器中的文本编辑功能
  • 教育类三维内容展示
  • 富文本 UI 控件

总结

这款基于 WebGL 的富文本编辑器,将传统 WYSIWYG 编辑体验扩展到 3D 场景中。通过结合 TinyMCE 编辑器、AutoCAD 的 MText 格式以及基于 THREE.js 的渲染器,开发者可以在 WebGL 中实现复杂的文本排版与渲染,满足技术、设计、教育等多种场景的需求。

无论是构建 CAD 浏览器、教育仿真平台还是创意设计工具,本项目都能让用户在 3D 空间中自由编辑并展现高保真富文本内容。