创建符号(本地 / 服务端)
示例:
vjcad/example/insert/symbol/01createlocal.js— IndexedDB 本地符号vjcad/example/insert/symbol/02createserver.js— 服务端符号
vjcad 把"符号"理解为一组实体 + 基点 + 缩略图打包。可以保存到 本地 IndexedDB 或 服务端,两条路径对应两个 service。
1. 通用步骤
flowchart LR
A[准备实体数组<br/>line/circle/...] --> B[buildSymbolVcadData<br/>(entities, false)]
A --> C[generateThumbnailFromEntities<br/>(entities, 128, 128)]
B --> D{保存目标}
D -->|本地| E[localService.saveLocalSymbol]
D -->|服务端| F[compressSymbolData → uint8ArrayToBase64<br/>→ service.createSymbol]
vcadData 是符号几何的序列化字符串;缩略图是完整的 Data URL(data:image/png;base64,...,128×128),可直接当 <img src>,不要再拼 data: 前缀。
2. 保存到本地(IndexedDB)
const localService = getLocalStorageService();
// 2.1 找/建分类
const categories = await localService.getLocalSymbolCategories();
let cat = categories.find(c => c.name === "示例符号");
if (!cat) cat = await localService.createLocalSymbolCategory("示例符号");
// 2.2 准备实体(必须先 setDefaults)
const line1 = new LineEnt([-10, 0], [10, 0]);
const line2 = new LineEnt([0, -10], [0, 10]);
const circle = new CircleEnt([0, 0], 8);
[line1, line2, circle].forEach(e => e.setDefaults());
Engine.addEntities([line1, line2, circle]); // 可选:在画布预览
// 2.3 打包数据 + 生成缩略图
const entities = [line1, line2, circle];
const vcadData = await buildSymbolVcadData(entities, /* clearSourceInfo */ false);
const thumbnail = await generateThumbnailFromEntities(entities, 128, 128);
// 2.4 保存
const symbol = await localService.saveLocalSymbol({
categoryId: cat.id,
name: "十字圆符号",
basePoint: [0, 0],
thumbnail,
vcadData,
});
完整代码:
vjcad/example/insert/symbol/01createlocal.js
3. 保存到服务端
服务端要求 vcadData 经过 gzip 压缩 + base64 编码:
let service;
try {
service = Engine.service; // 未配置 serviceUrl 时 getter 直接抛错,不会返回空
} catch (e) {
throw new Error("服务不可用:未配置 serviceUrl");
}
// 3.1 找/建分类
const categories = await service.getSymbolCategories();
let cat = categories.find(c => c.name === "用户自定义");
if (!cat) cat = await service.createSymbolCategory("用户自定义");
// 3.2 实体 → vcadData → 压缩 → base64
const vcadData = await buildSymbolVcadData(entities, false);
const thumbnail = await generateThumbnailFromEntities(entities, 128, 128);
const compressedData = await compressSymbolData(vcadData, /* level */ 6);
const base64Data = uint8ArrayToBase64(compressedData);
// 3.3 上传
const sym = await service.createSymbol({
categoryId: cat.id,
name: "箭头符号_" + Date.now(),
basePoint: [0, 0],
thumbnail,
data: base64Data,
});
完整代码:
vjcad/example/insert/symbol/02createserver.js
4. API 速查
| API | 来源 | 作用 |
|---|---|---|
buildSymbolVcadData(entities, clearSourceInfo?) |
vjcad 顶层 | 实体 → vcad 字符串 |
generateThumbnailFromEntities(entities, w, h) |
vjcad 顶层 | 缩略图 PNG Data URL(data:image/png;base64,...) |
compressSymbolData(data, level?) / uint8ArrayToBase64(arr) |
vjcad 顶层 | 服务端上传前压缩 |
getLocalStorageService() |
vjcad 顶层 | IndexedDB 服务实例 |
localService.getLocalSymbolCategories() / createLocalSymbolCategory(name) |
LocalStorageService | 分类 |
localService.saveLocalSymbol({ categoryId, name, basePoint, thumbnail, vcadData }) |
LocalStorageService | 保存 |
Engine.service.getSymbolCategories() / createSymbolCategory(name) |
service | 服务端分类 |
Engine.service.createSymbol({ categoryId, name, basePoint, thumbnail, data }) |
service | 服务端创建符号 |
红旗
buildSymbolVcadData(entities, clearSourceInfo)第二参数是是否清除来源信息(非压缩);压缩是服务端路径单独用compressSymbolData(vcadData, level)完成,本地保存直接存 vcad 字符串generateThumbnailFromEntities是 async,必须await- 服务端创建分类需要后台权限,匿名 / 只读账号会失败,需要 try/catch
- 保存前的实体一定要
setDefaults(),否则色 / 图层信息丢失 - 重名符号会创建多份,建议加时间戳后缀避免冲突
参考(官方文档 MCP)
- 示例:
vjcad/example/insert/symbol/01createlocal.js— IndexedDB 本地符号vjcad/example/insert/symbol/02createserver.js— 服务端符号