!!!###!!!title=Primitive Basic Concepts——VisActor/VChart Contributing Documents!!!###!!!!!!###!!!description=---title: 6.1 Basic Concepts of Marks key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM---!!!###!!!

Basic Concepts

In VChart, Marks are the basic drawing units that make up a chart, representing the basic visual elements in a chart, such as points, lines, rectangles, polygons, etc. Generally, the users of marks mainly include:

  • Series: The part of the chart used to display data. Different types of series are composed of different types of marks. For example, a line chart is composed of point marks (endpoints) and line marks, while a pie chart is mainly composed of arc marks and area marks... At this time, the types of marks contained in the series are determined by the type of series.

  • Component: Chart elements that provide auxiliary capabilities in the chart, helping with chart reading and interaction, such as axes, legends, annotations, etc. These components are also composed of marks. Thus, marks are not only used to display data but also serve as the basic units that make up various elements in a chart.

Functions of Marks

Overall, the functions of marks can be summarized as:

  • Constituting Charts
  • Composing various components of a chart, for example, a legend item is composed of symbol marks and text marks.
  • Displaying Data
  • Data Mapping: Marks map data into visual elements, making abstract data intuitive and understandable.

  • Information Conveyance: Through different types and styles of marks, convey the characteristics and trends of data.

  • Interaction Support: Marks support user interaction with the chart, such as hover, click, etc., enhancing the explorability of data.

Overview of Mark Types

VChart defines various basic and composite mark types, including but not limited to:

Basic Marks:

  • Symbol: Used to represent basic shapes of data points, such as points in a scatter plot.

  • Rectangle (rect): Used to draw bars in a bar chart, etc.

  • Line: Used to connect data points, commonly seen in line charts.

  • Rule: Draws a straight line at a specific position, can be used to indicate thresholds, etc.

  • Arc: Used to draw arcs, such as sectors in a pie chart.

  • Area: Represents filled areas, commonly used in area charts.

  • Text: Adds text annotations in the chart.

  • Path: Draws paths of arbitrary shapes.

  • Image: Embeds images in the chart.

  • 3D Rectangle (rect3d): Used to draw 3D bar charts, etc.

  • 3D Arc (arc3d): Used to draw sectors of 3D pie charts, etc.

  • Polygon: Draws polygonal areas.

Custom Marks: See details

Code Structure

The core code entry for implementing marks is packages/vchart/src/mark. This section provides a brief description of the code structure and functionality. For the specific logic of marks, see .

The mark module can be divided into the following core modules:

Among them:

  • All specific Marks inherit from BaseMark and bridge with vgrammar through CompilableMark

  • All Marks implement the IMarkRaw interface, and for the style system, the IVisualSpecStyle interface needs to be implemented

The inheritance chain where the graphic element is located:

  • Basic Module (base/)
  • Core file: base-mark.ts

  • Function overview: The base class for all graphic elements, containing common attributes and operations of the elements. Key attributes include:

  // 存储图元的样式状态,包括 normal、hover、selected 等状态的样式配置。
  declare stateStyle: IMarkStateStyle<T>;
  
  // 图元的初始化选项,包含上下文、全局缩放、模型等信息。
  protected declare _option: IMarkOption;

  // 图元的属性上下文,通常与图元的使用者(如 series 或 component)相关。
  protected _attributeContext: IModelMarkAttributeContext;

  // 扩展通道,用于在计算通道时添加默认通道以确保更新有效。
  _extensionChannel: {
    [key: string | number | symbol]: string[];
  } = {};
  
  // 扩展计算通道,用于在计算属性时添加额外的计算逻辑。
  _computeExChannel: {
    [key: string | number | symbol]: ExChannelCall;
  } = {};    

The key interfaces provided externally are:

// *根据 spec 初始化 style*
initStyleWithSpec(spec: IMarkSpec<T>, key?: string);

// 设置图元style
setStyle<U extends keyof T>(style: Partial<IMarkStyle<T>>,state: StateValueType = 'normal',level: number = 0,stateStyle = this.stateStyle);

// 获取style
getStyle(key: string, state: StateValueType = 'normal'): any {return this.stateStyle[state][key]?.style;};

// 计算属性值 这些属性值最终会被传递给底层渲染引擎(如 VGrammar)进行绘制
getAttribute<U extends keyof T>(key: U, datum: Datum, state: StateValueType = 'normal', opt?: IAttributeOpt);

// 设置属性值
setAttribute<U extends keyof T>(attr: U,style: MarkInputStyle<T[U]>,state: StateValueType = 'normal',level: number = 0,stateStyle = this.stateStyle);    

  • Interface Definition (interface/)
  • Core File: common.ts

  • Key Interfaces:

// IMarkRaw 
export interface IMarkRaw<T extends ICommonSpec> extends ICompilableMark {
  // 图元状态样式(例如:hover,selected分别是什么样式)
  readonly stateStyle: IMarkStateStyle<T>;
  // 图元属性
  getAttribute: <U extends keyof T>(key: U, datum: any, state?: StateValueType, opt?: any) => unknown;
  setAttribute: <U extends keyof T>(attr: U, style: StyleConvert<T[U]>, state?: StateValueType, level?: number) => void;
  // 图元样式
  setStyle: (style: Partial<IMarkStyle<T>>, state?: StateValueType, level?: number) => void;
  initStyleWithSpec: (spec: any, key?: string) => void;
}

// IMarkOption 用于初始化和管理图元的上下文、全局映射等信息。
export interface IMarkOption extends ICompilableMarkOption {
  model: IModel;
  map: Map<StringOrNumber, IModel | IMark>;
  // 全局映射
  globalScale: IGlobalScale;
  // 关联系列编号
  seriesId?: number;
  // 组件图元具体类型
  componentType?: string;
  attributeContext?: IModelMarkAttributeContext;
}
    

  • Specific Primitive Implementation:
  • Representative files: line.ts / symbol.ts / arc-3d.ts, etc.

  • Define additional configurations and operations for each type of primitive, generally need to implement:

protected _getDefaultStyle() {
  const defaultStyle: IMarkStyle<IGroupMarkSpec> = {
    ...super._getDefaultStyle()
    // 图元特有的配置
  };
  return defaultStyle;
}    

For example, for the line element, the _getIgnoreAttributes method has been added to obtain the ignored attributes:

protected _getIgnoreAttributes(): string[] {
  if (this.model?.type === SeriesTypeEnum.radar && this.model?.coordinate === *'polar'*) {
    return [];
  }
  return [*'fill'*, *'fillOpacity'*];
}    

  • Primitive Set Management (mark-set)
  • Core file: index.ts

  • Main functions:

  • Provides unified management of multiple primitive instances, supporting add, delete, search, and update operations;

  • Supports searching primitives by name, type, ID, additional information, and other dimensions;

  • Stores metadata associated with Mark (IMarkInfo), used for style control and business logic judgment

export class MarkSet {
  protected _children: IMark[] = [];  // 存储所有 Mark 实例
  protected _markNameMap: Record<string, IMark> = {}; // 名称索引
  protected readonly _infoMap = new Map<IMark, IMarkInfo>(); // Mark 附加信息
  // 添加 Mark 并关联信息
  addMark(mark?: IMark, markInfo?: IMarkInfo) {
    this._children.push(mark);
    this._markNameMap[mark.name] = mark;
    this._infoMap.set(mark, merge({}, MarkSet.defaultMarkInfo, markInfo));
  }
  // 按类型过滤 Mark
  getMarksInType(type: string | string[]): IMark[] {
    const types = array(type);
    return this._children.filter(m => types.includes(m.type));
  }
  // 按自定义信息查找 Mark
  getMarkWithInfo(info: Partial<IMarkInfo>) {
    return this._children.find(mark => {
      return Object.keys(info).every(key => info[key] === this._infoMap.get(mark)[key]);
    });
  }
  // 其他核心方法
  removeMark() { /* 删除逻辑 */ }
  clear() { /* 清空集合 */ }
  get() { /* 多方式获取 Mark */ }
}    

This document was revised and organized by the following person

玄魂