唯杰地图 logo唯杰地图
VJMAP
EN

SVG 导入

vjmapext/references/entity/svg-import.md 3.6 KB63 行
原文

本文回答:把 SVG 图形导入为 CAD 实体 —— svgToEntities / createBlockDefFromSvg / createBlockRefFromSvg / SvgParseOptions。

vjmapext 内置 SVG → CAD 实体解析器,三个导出函数(vjmapext 顶层,非 MapCadLayer 方法):

函数 返回 用途
svgToEntities(svgString, options?) SvgParseResult 解析为散实体数组,自行 addEntity
createBlockDefFromSvg(svgString, blockName, basePoint, blocks, options?) BlockDef 直接生成块定义
createBlockRefFromSvg(svgString, blockName, blocks, insertionPoint, basePoint?, scaleFactor?, rotation?, options?) BlockRefEnt 一步生成可插入的块引用
interface SvgParseResult {
  entities: EntityBase[];   // 已实例化的实体(LineEnt/PolylineEnt/...)
  width: number;            // SVG 画布宽(px 单位原值)
  height: number;
}
interface SvgParseOptions {
  flipY?: boolean;          // 默认 true:SVG 的 y 轴向下 → CAD 向上翻转
  tolerance?: number;       // 曲线离散容差,默认 0.5
  enableFill?: boolean;     // 默认 true:填充区转 Hatch
  defaultColor?: number;    // 无 stroke/fill 元素的颜色,默认 0xffffff
}

最小代码

const svg = '<svg xmlns="http://www.w3.org/2000/svg" width="100" height="80">' +
            '<line x1="0" y1="0" x2="100" y2="80" stroke="#f00"/></svg>';

const { entities, width, height } = vjmapext.svgToEntities(svg, { flipY: true });
entities.forEach(e => mapcadLayer.addEntity(e));   // 逐实体入图(进 undo 栈)

块引用一步式(适合做图符库):

const ref = vjmapext.createBlockRefFromSvg(
  svg, '灯具', mapcadLayer.blocks,
  [300, 300],   // insertionPoint
  [0, 0],       // basePoint:仅存为 BlockDef 元数据,不影响锚点(见坑 6)
  1, 0,         // scaleFactor, rotation
  { flipY: true }
);
mapcadLayer.addEntity(ref);

坑

  1. flipY 默认已是 true:SVG 坐标系 y 向下、CAD 向上,解析器默认已做翻转(y → height - y);只有要保留 SVG 原始朝向时才显式传 flipY: false。(tolerance 默认 0.5、enableFill 默认 true。)
  2. 返回的是 CAD 坐标系像素值:width/height 是 SVG 原始尺寸,实体坐标也未按地图比例缩放——SVG 设计稿通常要自己再 scale 到 CAD 单位。
  3. 不支持的元素静默跳过:image/foreignObject/渐变滤镜/defs/clipPath/mask 等不产出实体,检查 entities.length 是否符合预期;非法输入(非 XML、无 svg 根)不抛错,返回 {entities: [], width: 0, height: 0}。
  4. svgToEntities 不自动入图:只返回数组,必须逐个 addEntity;createBlockRefFromSvg 同理(返回 ref,仍需 addEntity)。
  5. createBlockRefFromSvg 的 blockName 是显示名:生成的 BlockDef/ref.blockId 是随机 id(如 ruaoiion 这类),查块引用别拿 blockId === '灯具' 判断。
  6. basePoint 不会平移块内实体:createBlockDefFromSvg/createBlockRefFromSvg 只把它存进 BlockDef.basePoint,块内实体仍是 SVG 原坐标,BlockRefEnt 渲染时也不减基点——插入点对齐的是解析后坐标的原点(默认 flipY 时即 SVG 画布左下角)。要以某点为锚:先 svgToEntities,对每个实体 e.move(基点, [0, 0]),再自建 BlockDef 逐个 addEntity 后 blocks.add(见 block-reference 基点一节)。

相关