!!!###!!!title=VChart SVG Plugin Source Code Analysis——VisActor/VChart Contributing Documents!!!###!!!!!!###!!!description=---title: 14.8.2 vchart-svg-plugin Source Code Explanation key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM--- !!!###!!!

Conversion Entry (convert.ts)

The entry file convert.ts provides the core method convertVChartToSvg, which mainly undertakes the following important responsibilities:

  • Obtain **stage** information: By passing in the vchart instance object, the getStage method is called to obtain the vrender's graphic scene tree stage, which is the basis for subsequent operations.

  • Set viewport attributes: Extract viewport information viewBox from stage, and based on this, generate svg viewport attributes. These attributes define the display area and size of the svg graphic, ensuring that the graphic can be correctly presented in the svg environment.

  • Handle background: Check the background information background of stage, and if there is a background, call the convertCommonStyle method to convert it into the rectangle element style required by svg.

  • Generate SVG tags: Combine the processed background rectangle elements and the converted svg elements of stage child nodes to generate a complete svg tag string and return it.

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 Transformation Core (graphic.ts)

graphic.ts serves as the core graphic processing file in the SVG transformation module, responsible for converting various graphic elements into SVG nodes. This module supports the conversion of multiple graphic types, covering basic graphics (such as paths, rectangles, arcs, etc.) and complex graphic groups.

Composite Graphic Processing

parseGroup is the main entry function for parsing graphics. It recursively processes child node types to gradually generate SVG elements. The specific implementation steps are as follows:

  • Basic Check: First, check whether the passed group object is valid. If group does not exist or is invalid, return an empty string directly. It should be noted that stage itself is also a special kind of group.

  • Attribute Merging: Merge the theme style theme?.combinedTheme?.[group.type] of the group with its own attributes group.attribute to ensure that the graphics can inherit the correct style.

  • Processing by Type: When the type of group is group, it indicates a composite graphic. At this point, first call the convertCommonStyle method to generate common styles, then sort the child elements of the group. The sorting basis is the zIndex attribute of the child elements (if zIndex does not exist, it defaults to 0). After sorting, recursively call the parseGroup method to process each child element and combine the results to generate the final composite graphic SVG element.

  • Processing Other Types: If group is not a composite graphic type, that is, a simple graphic element, call the parseSimpleGraphic method to process other types of graphics.

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);
};    

Composite graphics processing has the following key features:

  • Support for theme style inheritance: Ensures that composite graphics can inherit the correct theme style, maintaining consistency in overall style.

  • Maintain rendering order of sub-elements: Sorts sub-elements using the zIndex attribute to ensure the correct order during rendering, avoiding issues such as occlusion.

  • Recursive handling of nested structures: Capable of handling complex nested composite graphics, ensuring that each layer of sub-elements can be correctly converted into SVG elements.

SVG Node Generator

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;
};    

This function is the core of graphic node generation, mainly featuring the following functions:

  • Handle graphic names and styles: Apply the graphic's name to the class name of the style, making it convenient for targeted style settings in the stylesheet.

  • Generate definitions for gradients, shadows, etc.: Based on the passed defs object, generate SVG definition content for gradients, shadows, etc., to add rich visual effects to the graphics.

  • Support pattern fills: If there is a configuration related to pattern fills defs.pattern, perform the corresponding processing to enable the graphics to achieve pattern fill effects.

Basic Graphic Transformation

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(/*...*/);
  }
  
  // ... 其他图形类型处理
};    

The function is responsible for handling the transformation of basic graphics, supporting various types of basic graphics, specifically including:

  • Arc (arc)

  • Polygon (polygon)

  • Path (path)

  • Symbol (symbol)

  • Text (text)

  • Richtext (richtext)

  • Line (line)

  • Area (area)

  • Rectangle (rect)

Through the collaboration of the above parts, the vchart-svg-plugin efficiently and accurately converts vchart rendering content into an SVG string.

This document was revised and organized by the following personnel

玄魂