SVG 导入
大约 4 分钟
SVG 导入
将 SVG 矢量图形导入到 WebCAD 中,转换为 CAD 实体。
概览
| 方式 | 说明 |
|---|---|
IMPORTSVG 命令 | 打开对话框,可视化配置导入选项 |
parseSvgToWebcad() API | 程序化解析 SVG 内容 |
命令方式
IMPORTSVG 命令
await Engine.editor.executerWithOp('IMPORTSVG');命令会打开导入对话框,支持以下功能:
输入方式
- 选择本地 SVG 文件
- 直接粘贴 SVG 内容
显示设置
- 显示线宽
- 启用填充
- 线宽缩放比例
颜色处理
- 白色处理方式
- 黑色处理方式
插入选项
- 允许缩放
- 允许旋转
实时预览
- SVG 原始效果
- WebCAD 转换效果
API 方式
完整流程
const {
Engine, Point2D,
getWebCadCoreService, CadDocument, regen
} = vjcad;
// 1. SVG 内容
const svgContent = `
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200">
<rect x="20" y="20" width="60" height="40" fill="none" stroke="#ff0000" stroke-width="2"/>
<circle cx="150" cy="50" r="30" fill="none" stroke="#00ff00" stroke-width="2"/>
<line x1="20" y1="100" x2="180" y2="100" stroke="#0000ff" stroke-width="2"/>
</svg>
`;
// 2. 初始化 WASM 服务
const wasmService = getWebCadCoreService();
await wasmService.initWasm();
// 3. 解析 SVG 为 WebCAD 数据
const webcadData = await wasmService.parseSvgToWebcad(
svgContent,
0, // whiteColorProcessing
0, // blackColorProcessing
0, // enableFill
1, // displayLineWeight
1.0 // lineWeightScale
);
if (!webcadData) {
throw new Error("SVG 解析失败");
}
// 4. 解析 WebCAD 数据
const parsedData = JSON.parse(webcadData);
const entities = parsedData.entities || [];
// 5. 计算边界和基点
let basePoint = [0, 0];
if (parsedData.bounds && parsedData.bounds.length === 4) {
const [minX, minY, maxX, maxY] = parsedData.bounds;
basePoint = [(minX + maxX) / 2, (minY + maxY) / 2];
}
// 6. 构建临时文档数据
const docData = {
appName: "WebCAD SVG Import",
docVer: 0.3,
dbBlocks: {
"*Model": {
blockId: "*Model",
name: "*Model",
isLayout: false,
basePoint: [0, 0],
lookPt: [0, 0],
twistAngle: 0,
zoom: 1,
UCSXANG: 0,
UCSORG: [0, 0],
items: entities
}
},
dbLayers: [{
name: "0",
layerId: "0",
layerOn: true,
color: 7,
lineType: "Continuous",
lineWeight: -3,
plottable: true
}],
dbTextStyles: [],
dbLayouts: [{
layoutId: 0,
name: "Model",
spaceName: "*Model"
}]
};
// 7. 创建临时文档
const symbolDoc = new CadDocument();
await symbolDoc.fromDb(docData);
// 8. 合并实体到当前文档
const insertPoint = new Point2D(0, 0);
const basePt = new Point2D(basePoint[0], basePoint[1]);
const modelBlock = symbolDoc.blocks.itemByName("*Model");
for (const entity of modelBlock.items) {
if (!entity.isAlive) continue;
const cloned = entity.clone();
cloned.move(basePt, insertPoint);
Engine.addEntities(cloned);
}
// 9. 刷新视图
regen();
Engine.zoomExtents();parseSvgToWebcad 参数
wasmService.parseSvgToWebcad(
svgContent, // SVG 内容字符串
whiteColorProcessing, // 白色处理方式
blackColorProcessing, // 黑色处理方式
enableFill, // 是否启用填充
displayLineWeight, // 是否显示线宽
lineWeightScale // 线宽缩放比例
);颜色处理方式
| 值 | 说明 |
|---|---|
| 0 | 原样保留 |
| 1 | 自动反色(白变黑,黑变白) |
| 2 | 过滤排除(不导入该颜色) |
填充和线宽
| 参数 | 值 | 说明 |
|---|---|---|
enableFill | 0 | 不启用填充 |
enableFill | 1 | 启用填充 |
displayLineWeight | 0 | 不显示线宽 |
displayLineWeight | 1 | 显示线宽 |
lineWeightScale | 1.0 | 线宽 1:1 |
lineWeightScale | 2.0 | 线宽放大 2 倍 |
支持的 SVG 元素
| 元素 | 转换为 |
|---|---|
<line> | LineEnt |
<rect> | PolylineEnt |
<circle> | CircleEnt |
<ellipse> | EllipseEnt |
<polyline> | PolylineEnt |
<polygon> | PolylineEnt (闭合) |
<path> | PolylineEnt / SplineEnt |
<text> | TextEnt |
返回数据格式
parseSvgToWebcad() 返回 JSON 字符串,解析后包含:
{
entities: [...], // 实体数组
bounds: [minX, minY, maxX, maxY] // 边界范围
}简化封装示例
const { Engine, Point2D, getWebCadCoreService, CadDocument, regen } = vjcad;
/**
* 导入 SVG 内容到当前文档
* @param svgContent SVG 内容字符串
* @param insertPoint 插入点(可选,默认原点)
* @param options 导入选项
*/
async function importSvg(svgContent, insertPoint = new Point2D(0, 0), options = {}) {
const {
whiteColorProcessing = 0,
blackColorProcessing = 0,
enableFill = 0,
displayLineWeight = 1,
lineWeightScale = 1.0
} = options;
// 初始化 WASM
const wasmService = getWebCadCoreService();
await wasmService.initWasm();
// 解析 SVG
const webcadData = await wasmService.parseSvgToWebcad(
svgContent,
whiteColorProcessing,
blackColorProcessing,
enableFill,
displayLineWeight,
lineWeightScale
);
if (!webcadData) {
throw new Error("SVG 解析失败");
}
const parsedData = JSON.parse(webcadData);
const entities = parsedData.entities || [];
if (entities.length === 0) {
throw new Error("没有解析到任何实体");
}
// 计算基点
let basePoint = [0, 0];
if (parsedData.bounds?.length === 4) {
const [minX, minY, maxX, maxY] = parsedData.bounds;
basePoint = [(minX + maxX) / 2, (minY + maxY) / 2];
}
// 构建临时文档
const docData = {
appName: "WebCAD SVG Import",
docVer: 0.3,
dbBlocks: {
"*Model": {
blockId: "*Model",
name: "*Model",
isLayout: false,
basePoint: [0, 0],
lookPt: [0, 0],
twistAngle: 0,
zoom: 1,
UCSXANG: 0,
UCSORG: [0, 0],
items: entities
}
},
dbLayers: [{
name: "0", layerId: "0", layerOn: true,
color: 7, lineType: "Continuous", lineWeight: -3, plottable: true
}],
dbTextStyles: [],
dbLayouts: [{ layoutId: 0, name: "Model", spaceName: "*Model" }]
};
const symbolDoc = new CadDocument();
await symbolDoc.fromDb(docData);
// 合并实体
const modelBlock = symbolDoc.blocks.itemByName("*Model");
const basePt = new Point2D(basePoint[0], basePoint[1]);
const addedEntities = [];
for (const entity of modelBlock.items) {
if (!entity.isAlive) continue;
const cloned = entity.clone();
cloned.move(basePt, insertPoint);
Engine.addEntities(cloned);
addedEntities.push(cloned);
}
regen();
return addedEntities;
}
// 使用示例
const svgContent = `<svg>...</svg>`;
const entities = await importSvg(svgContent, new Point2D(100, 100), {
enableFill: 1,
lineWeightScale: 2.0
});
console.log(`导入了 ${entities.length} 个实体`);从文件导入
// 创建文件输入
const input = document.createElement('input');
input.type = 'file';
input.accept = '.svg';
input.onchange = async (e) => {
const file = e.target.files[0];
if (!file) return;
// 读取文件内容
const reader = new FileReader();
reader.onload = async (event) => {
const svgContent = event.target.result;
// 导入 SVG
const entities = await importSvg(svgContent);
console.log(`从 ${file.name} 导入了 ${entities.length} 个实体`);
Engine.zoomExtents();
};
reader.readAsText(file);
};
// 触发文件选择
input.click();注意事项
- WASM 初始化:首次调用需要初始化 WASM 服务
- 颜色映射:SVG 颜色会自动映射到 CAD 颜色索引
- 复杂路径:复杂的
<path>元素可能转换为多段线或样条曲线 - 文字处理:SVG 文字需要对应字体支持
- 渐变/滤镜:不支持 SVG 的渐变、滤镜等高级效果