!!!###!!!title=VChart SVG 插件源码分析——VisActor/VChart 社区贡献者文档!!!###!!!!!!###!!!description=---title: 14.8.2 vchart-svg-plugin 源码详解 key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM--- !!!###!!!

转换入口 (convert.ts)

入口文件 covert.ts 提供了核心方法 convertVChartToSvg,该方法主要承担以下几个重要职责:

  • 获取**stage**信息:通过传入的 vchart 实例对象,调用 getStage 方法获取到 vrender 的图形场景树 stage,这是后续操作的基础。

  • 设置视口属性:从 stage 中提取视窗信息 viewBox,并基于此生成 svg 视窗属性。这些属性定义了 svg 图形的显示区域和大小,确保图形在 svg 环境中能够正确呈现。

  • 处理背景:检查 stage 的背景信息 background,若存在背景,则调用 convertCommonStyle 方法将其转换为 svg 所需的矩形元素样式。

  • 生成 SVG 标签:将处理好的背景矩形元素和 stage 子节点转换后的 svg 元素组合起来,生成完整的 svg 标签字符串并返回。

export const convertVChartToSvg = (vchart: any): string => {
  // 1. 获取舞台信息
  const stage = vchart.getStage();
  
  // 2. 设置视口属性
  const viewBox = stage.viewBox;
  const attrs = {
    width: `${width}px`,
    height: `${height}px`,
    viewBox: `${x} ${y} ${width} ${height}`,
  };
  // 3. 处理背景
  const background = stage.background;
  let backgroundRect = "";
  if (background) {
    const style = convertCommonStyle({ fill: background }, stage);
    // ...
  }
  // 4. 生成SVG标签
  return `<svg version="1.1" xmlns="http://www.w3.org/2000/svg" ...>
    ${backgroundRect}
    ${stage.children.map((child: any) => parseGroup(child)).join("")}
  </svg>`;
};    

图形转换核心 (graphic.ts)

graphic.ts 作为 SVG 转换模块中的核心图形处理文件,肩负着将各种图形元素转换为 SVG 节点的重任。该模块支持多种图形类型的转换,涵盖基础图形(如路径、矩形、圆弧等)和复杂图形group。

组合图形处理

parseGroup 是解析图形的主要入口函数,它通过递归处理子节点类型,逐步生成 svg 元素。具体实现步骤如下:

  • 基础检查:首先检查传入的 group 对象是否有效,若 group 不存在或无效,则直接返回空字符串。需要说明的是,stage本身也是一种特殊的group

  • 属性合并:将 group 的主题样式 theme?.combinedTheme?.[group.type] 和自身属性 group.attribute 进行合并,确保图形能够继承正确的样式。

  • 根据类型处理:当 group 的类型为 group 时,表明这是一个组合图形。此时,先调用 convertCommonStyle 方法生成通用样式,然后对 group 的子元素进行排序,排序依据是子元素的 zIndex 属性(若不存在 zIndex,则默认为 0)。排序完成后,递归调用 parseGroup 方法处理每个子元素,并将结果组合起来,生成最终的组合图形 svg 元素。

  • 处理其他类型:若 group 不是组合图形类型,也就是简单图元,则调用 parseSimpleGraphic 方法处理其他类型的图形。

export const parseGroup = (group: any): string => {
  // 1. 基础检查
  if (!group ||!group.isValid()) {
    return "";
  }
  // 2. 属性合并
  const attribute = { 
    ...group.theme?.combinedTheme?.[group.type], 
    ...group.attribute 
  };
  // 3. 根据类型处理
  if (group.type === "group") {
    // 处理组合图形
    const commonStyle = convertCommonStyle(attribute, group);
    const children = group.children;
    
    // 排序子元素
    children.sort((a: any, b: any) => {
      return (a.attribute.zIndex ?? 0) - (b.attribute.zIndex ?? 0);
    });
    // 生成组合内容
    return `<g class="${name}" ${/*...*/}>
      ${children.map(child => parseGroup(child)).join("")}
    </g>`;
  } 
  
  // 4. 处理其他类型
  return parseSimpleGraphic(attribute, group);
};    

组合图形处理具备以下几个关键特性:

  • 支持主题样式继承:确保组合图形能够继承正确的主题样式,保持整体风格的一致性。

  • 维护子元素渲染顺序:通过 zIndex 属性对子元素进行排序,保证图形在渲染时的顺序正确,避免出现遮挡等问题。

  • 递归处理嵌套结构:能够处理复杂的嵌套组合图形,确保每一层子元素都能正确转换为 svg 元素。

SVG 节点生成器

export const generateSvgNode = (
  graphic: any,
  type: string,
  style: any,
  defs: { shadow?: string; pattern?: string; gradient?: string }
): string => {
  const name = graphic.name;
  
  // 处理样式类名
  if (name) {
    style.class = name;
  }
  
  // 生成定义内容
  const defContent = generateDefs(defs);
  // 生成节点字符串
  let nodeStr = `${defContent}<${type} 
    ${convertStyleToString(style)} 
    ${defs.shadow? 'filter="url(#' + generateShadowId(graphic) + ')"' : ""} 
  />`;
  // 处理图案填充
  if (defs.pattern) {
    // ...处理 pattern 相关逻辑
  }
  return nodeStr;
};    

这个函数是图形节点生成的核心,主要具备以下功能:

  • 处理图形名称和样式:将图形的名称应用到样式的类名中,方便在样式表中进行针对性的样式设置。

  • 生成渐变、阴影等定义:根据传入的 defs 对象,生成渐变、阴影等 SVG 定义内容,为图形添加丰富的视觉效果。

  • 支持图案填充:若存在图案填充相关的配置 defs.pattern,则进行相应的处理,使图形能够实现图案填充效果。

基础图形转换

export const parseSimpleGraphic = (attribute: any, group: any) => {
  // 1. 处理通用样式
  const commonStyle = convertCommonStyle(attribute, group);
  
  // 2. 生成定义内容
  const defs = {
    gradient: generateGradient(attribute, group),
    pattern: generatePattern(attribute, group),
    shadow: generateShadow(attribute, group),
  };
  // 3. 根据图形类型分发处理
  if (group.type === "arc") {
    return generateSvgNode(/*...*/);
  }
  
  if (group.type === "polygon") {
    return generateSvgNode(/*...*/);
  }
  
  // ... 其他图形类型处理
};    

该函数负责处理基础图形的转换工作,支持多种基础图形类型,具体包括:

  • 圆弧 (arc)

  • 多边形 (polygon)

  • 路径 (path)

  • 符号 (symbol)

  • 文本 (text)

  • 富文本 (richtext)

  • 线条 (line)

  • 区域 (area)

  • 矩形 (rect)

通过以上各个部分的协同工作,vchart-svg-plugin 实现了将 vchart 渲染内容高效、准确地转换为 svg 字符串的功能。

本文档由以下人员修正整理

玄魂