From e466a5028070b8884a951658cd66fd7ba8976bca Mon Sep 17 00:00:00 2001
From: xuanhun <717532978@qq.com>
Date: Wed, 21 May 2025 18:24:47 +0800
Subject: [PATCH] docs: add source code doc
---
.../en/sourcecode/0-vchart-engineering.md | 196 ++
.../sourcecode/1-vchart-basic-principles.md | 439 +++
.../10.1-animation-concepts-and-types.md | 1012 +++++++
.../10.2-global-morphing-animation.md | 556 ++++
.../sourcecode/10.3-state-change-animation.md | 472 ++++
.../sourcecode/10.4-data-update-animation.md | 608 +++++
.../10.5-animation-orchestration.md | 2413 +++++++++++++++++
.../11.1-theme-configuration-parsing-logic.md | 436 +++
.../11.2-theme-update-source-code-analysis.md | 300 ++
.../12.1-vchart-plugin-mechanism.md | 136 +
...art-plugin-feature-source-code-analysis.md | 103 +
...13.1-vchart-on-demand-loading-mechanism.md | 147 +
...-on-demand-loading-source-code-analysis.md | 191 ++
.../14.1.1-react-vchart-introduction.md | 134 +
...4.1.2-react-vchart-source-code-analysis.md | 466 ++++
.../14.2.1-taro-vchart-introduction.md | 104 +
...14.2.2-taro-vchart-source-code-analysis.md | 189 ++
.../14.3.1-lark-vchart-introduction.md | 39 +
...14.3.2-lark-vchart-source-code-analysis.md | 55 +
.../14.4.1-tt-vchart-introduction.md | 35 +
.../14.4.2-tt-vchart-source-code-analysis.md | 55 +
.../14.5.1-wx-vchart-introduction.md | 33 +
.../14.5.2-wx-vchart-source-code-analysis.md | 53 +
.../14.6.1-openinula-vchart-introduction.md | 109 +
...2-openinula-vchart-source-code-analysis.md | 699 +++++
.../14.7.1-harmony-vchart-introduction.md | 31 +
...7.2-harmony-vchart-source-code-analysis.md | 69 +
.../14.8.1-vchart-svg-plugin-introduction.md | 53 +
...-vchart-svg-plugin-source-code-analysis.md | 191 ++
.../sourcecode/3-how-to-assemble-a-vchart.md | 1158 ++++++++
.../6.1-primitive-basic-concepts.md | 237 ++
.../sourcecode/6.2-visual-channel-mapping.md | 414 +++
...rimitive-interaction-and-state-handling.md | 383 +++
.../en/sourcecode/6.4-custom-primitives.md | 487 ++++
.../9.1-vchart-layout-basic-concepts.md | 197 ++
.../9.2-vchart-layout-source-code-analysis.md | 468 ++++
docs/assets/contributing/menu.json | 261 ++
.../zh/sourcesode/0-vchart-engineering.md | 193 ++
.../sourcesode/1-vchart-basic-principles.md | 437 +++
.../10.1-animation-concepts-and-types.md | 1011 +++++++
.../10.2-global-morphing-animation.md | 558 ++++
.../sourcesode/10.3-state-change-animation.md | 457 ++++
.../sourcesode/10.4-data-update-animation.md | 592 ++++
.../10.5-animation-orchestration.md | 2363 ++++++++++++++++
.../11.1-theme-configuration-parsing-logic.md | 436 +++
.../11.2-theme-update-source-code-analysis.md | 308 +++
.../12.1-vchart-plugin-mechanism.md | 135 +
...art-plugin-feature-source-code-analysis.md | 101 +
...13.1-vchart-on-demand-loading-mechanism.md | 145 +
...-on-demand-loading-source-code-analysis.md | 188 ++
.../14.1.1-react-vchart-introduction.md | 133 +
...4.1.2-react-vchart-source-code-analysis.md | 461 ++++
.../14.2.1-taro-vchart-introduction.md | 103 +
...14.2.2-taro-vchart-source-code-analysis.md | 197 ++
.../14.3.1-lark-vchart-introduction.md | 39 +
...14.3.2-lark-vchart-source-code-analysis.md | 55 +
.../14.4.1-tt-vchart-introduction.md | 33 +
.../14.4.2-tt-vchart-source-code-analysis.md | 55 +
.../14.5.1-wx-vchart-introduction.md | 33 +
.../14.5.2-wx-vchart-source-code-analysis.md | 53 +
.../14.6.1-openinula-vchart-introduction.md | 107 +
...2-openinula-vchart-source-code-analysis.md | 685 +++++
.../14.7.1-harmony-vchart-introduction.md | 31 +
...7.2-harmony-vchart-source-code-analysis.md | 68 +
.../14.8.1-vchart-svg-plugin-introduction.md | 53 +
...-vchart-svg-plugin-source-code-analysis.md | 191 ++
.../sourcesode/3-how-to-assemble-a-vchart.md | 1140 ++++++++
.../6.1-primitive-basic-concepts.md | 240 ++
.../sourcesode/6.2-visual-channel-mapping.md | 408 +++
...rimitive-interaction-and-state-handling.md | 381 +++
.../zh/sourcesode/6.4-custom-primitives.md | 513 ++++
.../9.1-vchart-layout-basic-concepts.md | 195 ++
.../9.2-vchart-layout-source-code-analysis.md | 464 ++++
73 files changed, 25491 insertions(+)
create mode 100644 docs/assets/contributing/en/sourcecode/0-vchart-engineering.md
create mode 100644 docs/assets/contributing/en/sourcecode/1-vchart-basic-principles.md
create mode 100644 docs/assets/contributing/en/sourcecode/10.1-animation-concepts-and-types.md
create mode 100644 docs/assets/contributing/en/sourcecode/10.2-global-morphing-animation.md
create mode 100644 docs/assets/contributing/en/sourcecode/10.3-state-change-animation.md
create mode 100644 docs/assets/contributing/en/sourcecode/10.4-data-update-animation.md
create mode 100644 docs/assets/contributing/en/sourcecode/10.5-animation-orchestration.md
create mode 100644 docs/assets/contributing/en/sourcecode/11.1-theme-configuration-parsing-logic.md
create mode 100644 docs/assets/contributing/en/sourcecode/11.2-theme-update-source-code-analysis.md
create mode 100644 docs/assets/contributing/en/sourcecode/12.1-vchart-plugin-mechanism.md
create mode 100644 docs/assets/contributing/en/sourcecode/12.2-vchart-plugin-feature-source-code-analysis.md
create mode 100644 docs/assets/contributing/en/sourcecode/13.1-vchart-on-demand-loading-mechanism.md
create mode 100644 docs/assets/contributing/en/sourcecode/13.2-vchart-on-demand-loading-source-code-analysis.md
create mode 100644 docs/assets/contributing/en/sourcecode/14.1.1-react-vchart-introduction.md
create mode 100644 docs/assets/contributing/en/sourcecode/14.1.2-react-vchart-source-code-analysis.md
create mode 100644 docs/assets/contributing/en/sourcecode/14.2.1-taro-vchart-introduction.md
create mode 100644 docs/assets/contributing/en/sourcecode/14.2.2-taro-vchart-source-code-analysis.md
create mode 100644 docs/assets/contributing/en/sourcecode/14.3.1-lark-vchart-introduction.md
create mode 100644 docs/assets/contributing/en/sourcecode/14.3.2-lark-vchart-source-code-analysis.md
create mode 100644 docs/assets/contributing/en/sourcecode/14.4.1-tt-vchart-introduction.md
create mode 100644 docs/assets/contributing/en/sourcecode/14.4.2-tt-vchart-source-code-analysis.md
create mode 100644 docs/assets/contributing/en/sourcecode/14.5.1-wx-vchart-introduction.md
create mode 100644 docs/assets/contributing/en/sourcecode/14.5.2-wx-vchart-source-code-analysis.md
create mode 100644 docs/assets/contributing/en/sourcecode/14.6.1-openinula-vchart-introduction.md
create mode 100644 docs/assets/contributing/en/sourcecode/14.6.2-openinula-vchart-source-code-analysis.md
create mode 100644 docs/assets/contributing/en/sourcecode/14.7.1-harmony-vchart-introduction.md
create mode 100644 docs/assets/contributing/en/sourcecode/14.7.2-harmony-vchart-source-code-analysis.md
create mode 100644 docs/assets/contributing/en/sourcecode/14.8.1-vchart-svg-plugin-introduction.md
create mode 100644 docs/assets/contributing/en/sourcecode/14.8.2-vchart-svg-plugin-source-code-analysis.md
create mode 100644 docs/assets/contributing/en/sourcecode/3-how-to-assemble-a-vchart.md
create mode 100644 docs/assets/contributing/en/sourcecode/6.1-primitive-basic-concepts.md
create mode 100644 docs/assets/contributing/en/sourcecode/6.2-visual-channel-mapping.md
create mode 100644 docs/assets/contributing/en/sourcecode/6.3-primitive-interaction-and-state-handling.md
create mode 100644 docs/assets/contributing/en/sourcecode/6.4-custom-primitives.md
create mode 100644 docs/assets/contributing/en/sourcecode/9.1-vchart-layout-basic-concepts.md
create mode 100644 docs/assets/contributing/en/sourcecode/9.2-vchart-layout-source-code-analysis.md
create mode 100644 docs/assets/contributing/zh/sourcesode/0-vchart-engineering.md
create mode 100644 docs/assets/contributing/zh/sourcesode/1-vchart-basic-principles.md
create mode 100644 docs/assets/contributing/zh/sourcesode/10.1-animation-concepts-and-types.md
create mode 100644 docs/assets/contributing/zh/sourcesode/10.2-global-morphing-animation.md
create mode 100644 docs/assets/contributing/zh/sourcesode/10.3-state-change-animation.md
create mode 100644 docs/assets/contributing/zh/sourcesode/10.4-data-update-animation.md
create mode 100644 docs/assets/contributing/zh/sourcesode/10.5-animation-orchestration.md
create mode 100644 docs/assets/contributing/zh/sourcesode/11.1-theme-configuration-parsing-logic.md
create mode 100644 docs/assets/contributing/zh/sourcesode/11.2-theme-update-source-code-analysis.md
create mode 100644 docs/assets/contributing/zh/sourcesode/12.1-vchart-plugin-mechanism.md
create mode 100644 docs/assets/contributing/zh/sourcesode/12.2-vchart-plugin-feature-source-code-analysis.md
create mode 100644 docs/assets/contributing/zh/sourcesode/13.1-vchart-on-demand-loading-mechanism.md
create mode 100644 docs/assets/contributing/zh/sourcesode/13.2-vchart-on-demand-loading-source-code-analysis.md
create mode 100644 docs/assets/contributing/zh/sourcesode/14.1.1-react-vchart-introduction.md
create mode 100644 docs/assets/contributing/zh/sourcesode/14.1.2-react-vchart-source-code-analysis.md
create mode 100644 docs/assets/contributing/zh/sourcesode/14.2.1-taro-vchart-introduction.md
create mode 100644 docs/assets/contributing/zh/sourcesode/14.2.2-taro-vchart-source-code-analysis.md
create mode 100644 docs/assets/contributing/zh/sourcesode/14.3.1-lark-vchart-introduction.md
create mode 100644 docs/assets/contributing/zh/sourcesode/14.3.2-lark-vchart-source-code-analysis.md
create mode 100644 docs/assets/contributing/zh/sourcesode/14.4.1-tt-vchart-introduction.md
create mode 100644 docs/assets/contributing/zh/sourcesode/14.4.2-tt-vchart-source-code-analysis.md
create mode 100644 docs/assets/contributing/zh/sourcesode/14.5.1-wx-vchart-introduction.md
create mode 100644 docs/assets/contributing/zh/sourcesode/14.5.2-wx-vchart-source-code-analysis.md
create mode 100644 docs/assets/contributing/zh/sourcesode/14.6.1-openinula-vchart-introduction.md
create mode 100644 docs/assets/contributing/zh/sourcesode/14.6.2-openinula-vchart-source-code-analysis.md
create mode 100644 docs/assets/contributing/zh/sourcesode/14.7.1-harmony-vchart-introduction.md
create mode 100644 docs/assets/contributing/zh/sourcesode/14.7.2-harmony-vchart-source-code-analysis.md
create mode 100644 docs/assets/contributing/zh/sourcesode/14.8.1-vchart-svg-plugin-introduction.md
create mode 100644 docs/assets/contributing/zh/sourcesode/14.8.2-vchart-svg-plugin-source-code-analysis.md
create mode 100644 docs/assets/contributing/zh/sourcesode/3-how-to-assemble-a-vchart.md
create mode 100644 docs/assets/contributing/zh/sourcesode/6.1-primitive-basic-concepts.md
create mode 100644 docs/assets/contributing/zh/sourcesode/6.2-visual-channel-mapping.md
create mode 100644 docs/assets/contributing/zh/sourcesode/6.3-primitive-interaction-and-state-handling.md
create mode 100644 docs/assets/contributing/zh/sourcesode/6.4-custom-primitives.md
create mode 100644 docs/assets/contributing/zh/sourcesode/9.1-vchart-layout-basic-concepts.md
create mode 100644 docs/assets/contributing/zh/sourcesode/9.2-vchart-layout-source-code-analysis.md
diff --git a/docs/assets/contributing/en/sourcecode/0-vchart-engineering.md b/docs/assets/contributing/en/sourcecode/0-vchart-engineering.md
new file mode 100644
index 0000000000..63c60f1153
--- /dev/null
+++ b/docs/assets/contributing/en/sourcecode/0-vchart-engineering.md
@@ -0,0 +1,196 @@
+---
+title: 0 VChart Engineering
+
+key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM
+---
+# 0.1 Start demo
+
+## 0.1.1 Fork the project
+
+On Github, you need to Fork the VChart project.
+
+
+
+
+## 0.1.2 Clone the Project
+
+In the repository you forked, click the `Code` button to copy the project address. Then use the git clone command to clone the project locally. For example:
+
+```bash
+git clone https://github.com/your-username/VChart.git
+
+```
+After cloning, you need to add the remote address of VChart.
+
+```bash
+git remote add upstream https://github.com/VisActor/VChart.git
+
+```
+This way, you can get the latest source code from the remote address of VChart.
+
+```bash
+git pull upstream develop
+
+```
+## 0.1.3 Start demo
+
+We use [@microsoft/rush](https://rushjs.io/) to manage the monorepo. So, first install rush.
+
+
+```bash
+npm install -g @microsoft/rush
+
+```
+Next, execute the command to start the demo.
+
+```typescript
+*安装依赖*
+$ rush update
+*启动 vchart 的demo页*
+$ rush start
+*启动 react-vchart 的demo页*
+$ rush react
+*启动本地文档站点*
+$ rush docs
+
+```
+## 0.1.4 What happens when starting the demo?
+
+When you run `rush start`, it will launch the demo page of vchart. But what exactly happens?
+
+First, we configured the `start` command in `command-line.json`:
+
+
+```json
+{"commandKind": "global","name": "start","summary": "Start the development server","description": "Run this command to start vchart development server","shellCommand": "rush run -p @visactor/vchart -s start"},
+
+```
+So we know that the start command will execute the `rush run -p @visactor/vchart -s start` command.
+
+Let me explain the `rush run -p @visactor/vchart -s start` command in detail:
+
+This is a command from the Rush tool, which can be broken down into the following parts:
+
+1. `rush run`: A subcommand of Rush, used to run specific project npm scripts in a monorepo
+
+1. `-p @visactor/vchart`: The `-p` or `--project` parameter specifies the project name for which the script is to be run, here it specifies the @visactor/vchart project
+
+1. `-s start`: The `-s` or `--script` parameter specifies the npm script name to be run, here the start script is to be run
+
+According to the codebase, we can see that this command will eventually execute the start script defined in the package.json of the @visactor/vchart package:
+
+```bash
+ts-node __tests__/runtime/browser/scripts/initVite.ts && vite serve __tests__/runtime/browser
+
+```
+The first part of this command runs the initialization script `initVite.ts`, which mainly generates the local version files `vite.config.local.ts` and `index.page.local.ts`. These files are ignored by git and are used for local development configuration, which will be explained in detail later.
+
+The second part of the script `vite serve __tests__/runtime/browser` is to launch the demo webpage.
+
+## 0.1.5 How to use `index.page.local.ts`
+
+The default content of this file is
+
+
+```xml
+import './test-page/area';
+
+```
+Generally speaking, it can be used to specify launching different chart pages. In fact, it runs the VChart table generation code of different files to achieve the effect of launching different chart pages on the web. So you just need to import different files to launch different chart pages.
+
+## 0.1.6 How to use `vite.config.local.ts`
+
+This file is mainly used to configure ports and local packages. For example, the following configuration:
+
+```xml
+export default {
+ *// 启动端口*port: 4000,
+ resolve: {
+ alias: {
+ '@visactor/vgrammar-core': '/path/to/visactor/VGrammar/packages/vgrammar-core/src/index.ts',
+ '@visactor/vgrammar-util': '/path/to/visactor/VGrammar/packages/vgrammar-util/src/index.ts',
+ '@visactor/vgrammar-wordcloud': '/path/to/visactor/VGrammar/packages/vgrammar-wordcloud/src/index.ts',
+ '@visactor/vgrammar-wordcloud-shape': '/path/to/visactor/VGrammar/packages/vgrammar-wordcloud-shape/src/index.ts',
+ '@visactor/vgrammar-sankey': '/path/to/visactor/VGrammar/packages/vgrammar-sankey/src/index.ts',
+ '@visactor/vgrammar-hierarchy': '/path/to/visactor/VGrammar/packages/vgrammar-hierarchy/src/index.ts',
+ '@visactor/vgrammar-projection': '/path/to/visactor/VGrammar/packages/vgrammar-projection/src/index.ts',
+ '@visactor/vgrammar-coordinate': '/path/to/visactor/VGrammar/packages/vgrammar-coordinate/src/index.ts',
+ '@visactor/vgrammar-venn': '/path/to/visactor/VGrammar/packages/vgrammar-venn/src/index.ts',
+ '@visactor/vscale': '/path/to/visactor/VUtil/packages/vscale/src/index.ts',
+ '@visactor/vdataset': '/path/to/visactor/VUtil/packages/vdataset/src/index.ts',
+ '@visactor/vutils': '/path/to/visactor/VUtil/packages/vutils/src/index.ts',
+ '@visactor/vrender-core': '/path/to/visactor/VRender/packages/vrender-core/src/index.ts',
+ '@visactor/vrender-kits': '/path/to/visactor/VRender/packages/vrender-kits/src/index.ts',
+ '@visactor/vrender-components': '/path/to/visactor/VRender/packages/vrender-components/src/index.ts'
+ }
+ }
+};
+
+```
+它把启动端口配置为 4000,并且配置了一系列的本地包,这样你的 VChart 在调试时会依赖这些本地包,你对上游本地包的改动会实时生效,方便调试一些和上游有关的 bug,如果你不需要这个功能,去掉这些配置即可。
+
+# 0.2 Detailed Explanation of VChart Engineering
+
+## 0.2.1 Project Structure
+
+VChart is a monorepo project managed using Rush, mainly consisting of the following parts:
+
+Core Packages:
+
+1. @visactor/vchart - Core chart library
+
+1. @visactor/react-vchart - React wrapper
+
+1. @visactor/openinula-vchart - OpenInula wrapper
+
+1. @visactor/taro-vchart - Taro wrapper
+
+1. @visactor/lark-vchart - Lark wrapper
+
+1. @visactor/wx-vchart - WeChat Mini Program wrapper
+
+1. @visactor/vchart-schema - Chart configuration schema
+
+1. @visactor/vchart-types - TypeScript type definitions
+
+1. @visactor/vutils-extension - Utility function extensions
+
+1. @visactor/tt-vchart - ByteDance Mini Program wrapper
+
+Tool Packages:
+
+1. @internal/bundler - Bundling tool
+
+1. @internal/typescript-json-schema - TypeScript type definition generation tool
+
+1. @internal/story-player - Story player
+
+1. @internal/bugserver-trigger - Bug service trigger
+
+## 0.2.2 Documentation System
+
+The content of the documentation is stored in the `docs/assets` folder, including:
+
+* API documentation
+
+* Example code
+
+* Tutorial documentation
+
+* Configuration documentation
+
+* Theme documentation
+
+## 0.2.3 Development Commands
+
+* rush update - Install dependencies
+
+* rush start - Start the vchart development service
+
+* rush react - Start the react-vchart development service
+
+* rush docs - Start the documentation development service
+
+
+ # This document was revised and organized by the following personnel
+ [玄魂](https://github.com/xuanhun)
\ No newline at end of file
diff --git a/docs/assets/contributing/en/sourcecode/1-vchart-basic-principles.md b/docs/assets/contributing/en/sourcecode/1-vchart-basic-principles.md
new file mode 100644
index 0000000000..03d59a244e
--- /dev/null
+++ b/docs/assets/contributing/en/sourcecode/1-vchart-basic-principles.md
@@ -0,0 +1,439 @@
+---
+title: 1 VChart Basic Principles
+
+key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM
+---
+# 1.1 Chart Composition
+
+## Terminology
+
+1. Mark: Basic graphic elements (basic primitives), such as lines, points, rectangles, etc.
+
+1. Series: Responsible for the visual representation of specific types of data, including a set of primitives and their corresponding chart logic, such as a series of lines in a line chart
+
+1. Region: Defines the spatial area of the chart, associates one or more series, handles interaction and animation, provides coordinate systems
+
+1. Component: Elements that assist in reading and interacting with the chart, such as legends, axes, tips, etc.
+
+1. Layout: Manages the layout of the chart, including the position and size of regions and components
+
+1. Chart: The abstract concept of the entire chart, including elements on the view such as layout, components, and regions, as well as data and all elements needed to form a table
+
+## Structural Relationships
+
+
+
+
+## Simple Chart Example
+
+
+
+## Combination Chart Example
+
+### Same Region
+
+
+
+The above image is a combination chart, which simply means there are multiple series groups, with bar and line being the two series above.
+
+1. If we do not configure specifically, all series will be associated with one region, so they will overlap and share certain coordinates.
+
+1. Each series can have its own data source, or the data source can be configured directly on the chart, with the series associated through `fromDataId` or `fromDataIndex`. In the current example, we choose to configure it on the chart.
+
+### Different Region
+
+
+
+In this example, it is also a combination chart, but its two series appear in different regions. As mentioned above, we use layout to manage the layout of regions. In this example, we used the following code:
+
+```Typescript
+ layout: {
+ type: 'grid',
+ col: 4,
+ row: 3,
+ elements: [
+ {
+ modelId: 'legend',
+ col: 0,
+ colSpan: 4,
+ row: 0
+ },
+ {
+ modelId: 'pie-region',
+ col: 0,
+ colSpan: 2,
+ row: 1
+ },
+ {
+ modelId: 'axis-left',
+ col: 2,
+ row: 1
+ },
+ {
+ modelId: 'bar-region',
+ col: 3,
+ row: 1
+ },
+ {
+ modelId: 'axis-bottom',
+ col: 3,
+ row: 2
+ }
+ ]
+ },
+
+```
+The above uses a grid-like method to manage the layout of regions and components. We use these `modelId` to associate the configuration of the corresponding region and component:
+
+
+```Typescript
+ region: [
+ {
+ id: 'pie-region'
+ },
+ {
+ id: 'bar-region'
+ }
+ ],
+ axes: [
+ {
+ id: 'axis-left',
+ regionId: 'bar-region',
+ orient: 'left'
+ },
+ {
+ id: 'axis-bottom',
+ regionId: 'bar-region',
+ orient: 'bottom'
+ }
+ ]
+
+```
+# 1.2 VChart Architecture and Source Code Structure
+
+## 1.2.1 Relationship between VChart, VGrammar, and VRender
+
+These three are the core components of the VisActor visualization system, and their relationship is hierarchical, from bottom to top:
+
+### VRender (Bottom Layer)
+
+VRender is a low-level visualization rendering engine responsible for the most basic graphic drawing and rendering tasks:
+
+* It provides rich visualization rendering features, including custom animations, element combinations, and narrative arrangements
+
+* It is the foundation of the VisActor visualization system, providing rendering capabilities for upper-level libraries
+
+* VRender offers a plugin system for flexible extensions
+
+* It can seamlessly switch between 2D/3D effects
+
+* It handles low-level Canvas operations, graphic drawing, scene management, etc.
+
+### VGrammar (Middle Layer)
+
+VGrammar is a visualization grammar library based on VRender:
+
+* It uses declarative syntax to describe data visualization
+
+* VGrammar maps data to visual elements, handling data transformations, marks, scales, etc.
+
+* It provides more advanced APIs, simplifying the process of creating complex visualizations
+
+* VGrammar is responsible for chart syntax definition, data mapping, automatic layout, etc.
+
+* It is essentially a further encapsulation of VRender, adding more visualization grammar concepts
+
+### VChart (Top Layer)
+
+VChart is the top-level chart component library:
+
+* It is built on VGrammar, encapsulating common chart types (bar charts, pie charts, line charts, etc.)
+
+* VChart provides ready-to-use chart components, so users do not need to understand the underlying graphic syntax
+
+* It has cross-platform features, automatically adapting to desktop, H5, and various mini-program environments
+
+* VChart offers complete data narrative capabilities, including comprehensive annotations, animations, flow control, and narrative templates
+
+* It is aimed at end-users, providing the most user-friendly visualization interface and API
+
+### Summary of Relationships
+
+The architectural relationship of these three can be understood as:
+
+
+```Typescript
+VChart (图表组件库)
+ ↓
+VGrammar (可视化语法)
+ ↓
+VRender (渲染引擎)
+ ↓
+浏览器/Canvas/WebGL
+
+```
+From the code implementation perspective:
+
+* VChart uses VGrammar to define and build charts
+
+* VGrammar uses VRender for actual drawing and rendering
+
+* Finally, VRender controls the underlying Canvas/WebGL to draw graphics
+
+This layered architecture allows developers to choose different levels of tools as needed: if highly customized visualization is required, VRender or VGrammar can be used directly; if quick creation of standard charts is needed, VChart can be used.
+
+## 1.2.2 Relationship and Source Code Structure of Internal Components in VChart
+
+The overall architecture adopts a modular design, with the core divided into the following main parts:
+
+1. Core Engine (Core): The central controller of VChart, responsible for organizing the collaboration of various modules
+
+1. Chart: Specific implementations of various chart types
+
+1. Series: Responsible for mapping data to graphics in the chart
+
+1. Mark: Basic graphic elements
+
+1. Region: Defines the area for chart rendering
+
+1. Component: Additional components such as axes, legends, etc.
+
+1. Layout: Handles the position calculation of various elements in the chart
+
+1. Event: Handles user interactions
+
+1. Scale: Related to data mapping and scales
+
+1. Data Processing (Data): Data transformation and processing
+
+### Core Module
+
+#### VChart Core Class
+
+The VChart class is the entry point of the entire chart library, responsible for instantiating and managing the entire chart lifecycle.
+
+```Typescript
+// packages/vchart/src/core/vchart.ts
+export class VChart implements IVChart {
+ readonly id = createID();
+
+ // 用于注册图表、组件、系列等
+ static useRegisters(comps: (() => void)[]) { ... }
+ static useChart(charts: IChartConstructor[]) { ... }
+ static useSeries(series: ISeriesConstructor[]) { ... }
+
+ // 核心渲染流程
+ renderSync(morphConfig?: IMorphConfig) { ... }
+ async renderAsync(morphConfig?: IMorphConfig) { ... }
+
+ // 数据更新方法
+ updateData(id: StringOrNumber, data: DataView | Datum[] | string, ...) { ... }
+ updateSpec(spec: ISpec, forceMerge: boolean = false, ...) { ... }
+
+ // 状态管理
+ setSelected(datum: MaybeArray | null, ...) { ... }
+ setHovered(datum: MaybeArray | null, ...) { ... }
+}
+
+```
+The lifecycle of VChart mainly includes:
+
+1. Initialization of configuration and data
+
+1. Creating chart instance
+
+1. Layout calculation
+
+1. Rendering
+
+1. Interaction event handling
+
+1. Update and destruction
+
+#### Module Chart Class (Chart)
+
+The chart module implements various types of charts, such as bar charts, line charts, pie charts, etc., all inheriting from BaseChart.
+
+```Typescript
+// packages/vchart/src/chart/base/base-chart.ts
+export class BaseChart extends CompilableBase implements IChart {
+ readonly type: string = 'chart';
+ readonly seriesType: string;
+
+ protected _regions: IRegion[] = [];
+ protected _series: ISeries[] = [];
+ protected _components: IComponent[] = [];
+
+ protected _layoutFunc: LayoutCallBack;
+ protected _layoutRect: IRect = { ... };
+
+ layout(params: ILayoutParams): void { ... }
+ compile() { ... }
+}
+
+```
+For example, BarChart inherits from BaseChart
+
+```Typescript
+export class BarChart extends BaseChart {
+ static readonly type: string = ChartTypeEnum.bar;
+ static readonly seriesType: string = SeriesTypeEnum.bar;
+ static readonly transformerConstructor = BarChartSpecTransformer;
+ readonly transformerConstructor = BarChartSpecTransformer;
+ readonly type: string = ChartTypeEnum.bar;
+ readonly seriesType: string = SeriesTypeEnum.bar;
+}
+
+```
+The chart module is responsible for:
+
+* Determining the chart type and layout
+
+* Managing the contained areas, series, and components
+
+* Handling the overall mapping from data to visual elements
+
+#### Series Module (Series)
+
+The series module is the core mapping from data to visual representation, with different series types corresponding to different graphical representations.
+
+```Typescript
+// packages/vchart/src/series/base/base-series.ts
+export abstract class BaseSeries extends BaseModel implements ISeries {
+ readonly type: string = 'series';
+ readonly coordinate: CoordinateType = 'none';
+
+ protected _region: IRegion;
+ protected _rootMark: IGroupMark = null;
+ protected _seriesMark: Maybe = null;
+
+ protected _rawData!: DataView;
+ protected _data: SeriesData = null;
+
+ abstract initMark(): void;
+ abstract initMarkStyle(): void;
+ abstract dataToPosition(data: Datum, checkInViewData?: boolean): IPoint;
+}
+
+```
+The series module is responsible for:
+
+* Converting data to graphical marks
+
+* Handling data mapping for specific chart types
+
+* Managing the style and state of marks
+
+#### Mark Module
+
+Marks are the most basic visual elements, such as lines, rectangles, points, etc., which are the basic units that make up a chart. The corresponding code is implemented in the `packages/vchart/src/mark` directory.
+
+The mark is responsible for:
+
+* Implementing specific graphic rendering
+
+* Handling interaction states (such as highlighting, selection)
+
+* Binding with data
+
+#### Region Module
+
+A region defines the rendering position of a chart on the canvas and can contain multiple series. The corresponding code is in the `packages/vchart/src/region` directory.
+
+The region module is responsible for:
+
+* Determining the position and size of each sub-region in the chart
+
+* Managing the series contained within
+
+* Handling layout relationships between regions
+
+#### Component Module
+
+Components are auxiliary elements in the chart other than data graphics, such as axes, legends, titles, etc. Various component implementations are in the `packages/vchart/src/component` directory.
+
+The component module is responsible for:
+
+* Rendering various auxiliary elements
+
+* Interacting with users (such as legend clicks)
+
+* Collaborating with the main chart
+
+#### Layout Module
+
+The layout module is responsible for calculating the position and size of each element in the chart. The corresponding code is in the `packages/vchart/src/layout` directory, specifically including:
+
+* Calculating element positions
+
+* Adjusting to fit container size
+
+* Handling hierarchical relationships between elements
+
+#### Event Module
+
+The event module handles user interactions and internal events, specifically including:
+
+* Handling user interaction events (such as clicks, hover)
+
+* Distributing internal events
+
+* Triggering data updates and rendering updates
+
+#### Scale Module
+
+The scale module is responsible for mapping conversions from data to visual attributes, specifically including:
+
+* Handling the mapping of data to visual space
+
+* Managing various scales (linear, discrete, color, etc.)
+
+* Calculating the range and ticks of axes
+
+#### Data Module
+
+The data module handles the conversion and processing of raw data, specifically including:
+
+* Parsing and converting data
+
+* Statistical calculations
+
+* Handling missing and outlier values
+
+## Rendering Process
+
+The rendering process of VChart mainly includes the following steps:
+
+1. Initialization: Create a VChart instance through spec configuration
+
+1. Compilation: Parse the configuration, create various components and series
+
+1. Layout: Calculate the position and size of each element
+
+1. Data Processing: Process and convert data
+
+1. Rendering Preparation: Bind data to marks
+
+1. Actual Rendering: Draw marks on the canvas
+
+1. Interaction Binding: Bind various interaction events
+
+## Data Update Process
+
+When data or configuration changes:
+
+1. Call the updateData or updateSpec method
+
+1. Reprocess affected data
+
+1. Update related scales
+
+1. Relayout (if needed)
+
+1. Update affected marks
+
+1. Trigger re-rendering
+
+
+# This document was revised and organized by
+[玄魂](https://github.com/xuanhun)
\ No newline at end of file
diff --git a/docs/assets/contributing/en/sourcecode/10.1-animation-concepts-and-types.md b/docs/assets/contributing/en/sourcecode/10.1-animation-concepts-and-types.md
new file mode 100644
index 0000000000..e3486a4cb0
--- /dev/null
+++ b/docs/assets/contributing/en/sourcecode/10.1-animation-concepts-and-types.md
@@ -0,0 +1,1012 @@
+---
+title: 10.1 Concepts and Types of Animation
+
+key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM
+---
+> 10.1 Concepts and Types of Animation
+> Score: 4
+> 1. Concepts and Types of Animation:
+> 1. Other Reference Documents:
+> https://www.visactor.io/vchart/guide/tutorial_docs/Animation/Animation_Types
+>
+> [Magic Frame (Part 2): VChart Animation Programming Practice In this article, we will start with some common chart animations and introduce in detail the compilation in VChart - Juejin](https://juejin.cn/post/7314829865633595443)
+
+1. Code Entry: `packages/vchart/src/animation/`
+
+`packages/vchart/src/series/line/animation`
+
+`packages/vchart/src/core/vchart`
+
+`packages/vchart/src/core/interface`
+
+`packages/vchart/src/complie/mark`
+
+1. Key Points Interpretation:
+
+1. Animation Classification (by execution timing, by effect)
+
+1. Overall Design of the Animation System
+
+# Concept of Animation
+
+
+
+In VChart, animation refers to enhancing the dynamism and interactivity of data presentation through visual effects during the chart rendering process. The animation system allows developers to configure and control the transition effects of chart elements (such as bar charts, pie charts, line charts, etc.) in different states.
+
+In VisActor, animation is regarded as an embellishment of the rendering stage: animation configuration, together with the visual channels of the graphic elements obtained from the execution of the graphic grammar process, determines the result of the rendering stage. The performance of animation is the interpolation calculation or special calculation logic of the visual channel attributes of specific graphic elements within a certain time period, and the animation configuration describes the trigger timing and execution duration of this calculation.
+
+
+
+## Types of Animation
+
+#### Lifecycle Demonstration
+
+
+
+
+
+
+### Classified by Execution Timing
+
+Chart animations in VChart are categorized based on state scenarios (execution timing) into: **Chart Entrance Animation**, **Data Update Animation**, and **Chart Exit Animation**.
+
+1. **Chart Entrance Animation:** Refers to the animation effect when the chart is created.
+
+1. **Data Update Animation:** When we update the chart data, the attribute animation of the graphic elements is called data update animation. It is divided into: **New Element Animation**, **Element Update Animation**, and **Exit Element Animation, State Change Animation, Animation Triggered at Any Time**. Usually, you don't need to worry about how to control these three update animations, as VChart will identify the association between the new data and the previous data during data updates, thus correctly executing the update animation.
+
+1. **Chart Exit Animation:** In some scenarios, we may need to remove the chart. At this time, we can set an exit animation for the chart to provide a smooth transition animation effect before removal.
+
+
+
+https://visactor.io/vchart/guide/tutorial_docs/Animation/Animation_Types Animation tutorial documentation
+
+https://www.visactor.io/vchart/option/barChart#animationState Animation configuration documentation
+
+#### Chart **Entrance Animation (**`**animationAppear**`**)**:
+
+* The transition effect of elements from nothing to something when the chart is first rendered.
+
+* Example code: The `animationAppear` configuration item is used to define the chart entrance animation.
+
+
+
+```html
+
+
+
+
+
+```
+```xml
+animationAppear?: boolean | IStateAnimateSpec | IMarkAnimateSpec;
+
+```
+#### Data Update Animation
+
+When we update chart data, the attribute animation of the graphic elements is called update animation. In VChart, manually calling the `updateData` interface will trigger a chart data update. Additionally, clicking the legend also updates the chart data. Update animations are divided into three categories: new graphic element animation, graphic element update animation, and exit graphic element animation.
+
+1. **New Graphic Element Animation (**`**animationEnter**`**):
+
+* New graphic element animation refers to the animation effect of newly added data's graphic elements when the chart data is updated.
+
+* We can use the `animationEnter` configuration to set the new graphic element animation.
+
+```xml
+animationEnter?: boolean | ICommonStateAnimateSpec | IMarkAnimateSpec;
+
+```
+
+
+1. **Primitive Update Animation ( **`**animationUpdate**`**)**:
+
+* Primitive update animation refers to the update animation effect of the primitives corresponding to the original data when the chart data is updated.
+
+* We can use the `animationUpdate` configuration to set the primitive update animation.
+
+```xml
+animationUpdate?: boolean | ICommonStateAnimateSpec | IMarkAnimateSpec;
+
+```
+
+
+1. **Exit Element Animation (**`**animationExit**`** )**:
+
+* Exit element animation refers to the animation effect of elements corresponding to deleted data when the chart data is updated. We can use the `animationExit` configuration to set the exit element animation.
+
+```xml
+animationExit?: boolean | ICommonStateAnimateSpec | IMarkAnimateSpec;
+
+```
+
+
+1. Primitive **State Transition Animation (State)**:
+
+* The transition effect when the chart state changes.
+
+* Example code: The `animationState` configuration item is used to define state transition animations.
+
+```xml
+animationState?: boolean | IStateAnimationConfig;
+
+```
+
+
+1. Normal **Animation (Normal)**: Commonly used for loops
+
+* Used to define continuous animation effects.
+
+* Example code: `animationNormal` configuration item is used to define loop animation.
+
+```xml
+animationNormal?: IMarkAnimateSpec;
+
+```
+
+
+#### Chart **Exit Animation (**`**animationDisappear**`**)**:
+
+* The exit effect of elements when the chart is destroyed or hidden.
+
+
+```xml
+ animationDisappear?: boolean | ICommonStateAnimateSpec | IMarkAnimateSpec;
+
+```
+### Classified by Effect
+
+Type Primitive Atomization
+
+* Animation Effects: Animation effects describe how primitives execute rendering changes at a specific stage of animation. Animation effects include ordinary visual channel interpolation, such as changes in the color, width, and position of bars in a racing bar chart; animation effects also include some special changes, such as the deformation of primitives in the figure below.
+
+1. **FadeIn/FadeOut**:
+
+* The change in element opacity from 0 to 1 or from 1 to 0.
+
+* Example code: `Appear_FadeIn` and `Disappear_FadeOut`.
+
+```xml
+const Appear_FadeIn: IAnimationTypeConfig = {
+ type: 'fadeIn'
+};
+
+```
+
+
+1. **Grow**:
+
+* The element gradually grows from an initial size to a final size.
+
+* Example code: `barGrowOption` and `pieGrowOption`.
+
+```xml
+function barGrowOption(barParams: IBarAnimationParams, isOverall = true) {/***/}
+
+```
+
+
+1. **Clip**:
+
+* Display the gradual appearance or disappearance of elements by clipping the area.
+
+* Example code: `registerCartesianGroupClipAnimation`.
+
+```xml
+const registerCartesianGroupClipAnimation = () => {
+ Factory.registerAnimation('cartesianGroupClip', (params?: ICartesianGroupAnimationParams) => {/***/});
+};
+
+```
+
+
+1. **Wave**:
+
+* Special effects, such as wave effects in liquid graphics.
+
+* Example code: `Appear_Wave`.
+
+```xml
+const Appear_Wave: IAnimationTypeConfig = {
+ duration: 2000,
+ loop: true,
+ channel: {
+ wave: { from: 0, to: 1 }
+ }
+};
+
+```
+
+
+1. **Scale**:
+
+* The size of the element scales from one ratio to another.
+
+* Example code: `Appear_ScaleIn`.
+
+```xml
+const Appear_ScaleIn: IAnimationTypeConfig = {
+ type: 'growCenterIn'
+};
+
+```
+More animation effects attributes and configurations can be found at https://visactor.com/vchart/guide/tutorial_docs/Animation/Animation_Attributes_and_Settings
+
+## Design of the Animation System
+
+### Simple Bar Chart Animation Configuration
+
+
+
+Below is an example of creating a simple bar chart to illustrate how to use VChart's animation system to achieve basic animation effects.
+
+
+
+
+
+
+```html
+
+
+
+
+
+
+```
+> How to create a basic VChart can be referred to in the following documents
+> https://www.visactor.io/vchart/guide/tutorial_docs/Getting_Started Quick Start
+> https://www.visactor.io/vchart/guide/tutorial_docs/Basic/How_to_Import_VChart Import VChart
+> https://www.visactor.io/vchart/guide/tutorial_docs/Basic/A_Basic_Spec Basic Configuration
+> https://www.visactor.io/vchart/guide/tutorial_docs/Basic/DeepSeek_With_Cursor DeepSeek+Cursor Assistance
+
+
+In the `VChart` class, the `animation` configuration item in `spec` (chart configuration) is used to control the animation behavior of the chart. Specifically, the `animation` configuration item can define the animation effects of the chart in different states, such as entrance animation, update animation, exit animation, etc.
+
+#### The role of `animation` configuration
+
+1. **Define animation behavior**:
+
+* The `animation` configuration item can contain multiple sub-properties, such as `appear`, `enter`, `update`, `exit`, and `disappear`, corresponding to different animation scenarios.
+
+* Each sub-property can further configure parameters such as animation duration (`duration`), easing function (`easing`), whether to execute one by one (`oneByOne`), etc.
+
+1. **Control animation switch**:
+
+* If `animation` is set to `false`, all animation effects are disabled.
+
+* If set to `true` or a specific configuration object is provided, the corresponding animation effects are enabled.
+
+1. **Pass to underlying components**:
+
+* The `VChart` class will pass the `animation` configuration to the internal `Compiler` and `Chart` instances, which will decide whether and how to apply animations based on the configuration.
+
+### Example explanation of bar chart animation execution
+
+
+
+
#### 创建逻辑说明
+1. **Create Chart Configuration and Data**:
+1. **Create VChart Instance**:
+1. **Render Chart**:
+1. **Animation Entrance**:
+1. **Data Update (Add Elements)**:
+1. **Data Update (Update Elements)**:
+1. **Data Update (Remove Elements)**:
+1. **Use of Element State**:
+1. **Chart Exit**:
+
+
+* Defined an initial chart configuration `initialSpec`, which includes chart type, data, axis fields, and animation configuration.
+
+* The data section includes a dataset `barData`, initially containing sales data for 5 months.
+
+* Create a VChart instance using `initialSpec` and the DOM container `chart`.
+
+* Call the `renderAsync` method to asynchronously render the chart. Once the chart is rendered, the animation entrance effect is triggered.
+
+* After rendering, simulate the animation entrance using `setTimeout`. The actual animation effect is handled internally by VChart.
+
+* After 3 seconds, add two months of sales data using the `updateDataSync` method. The `reAnimate: true` parameter ensures an animation effect when adding data.
+
+* After 6 seconds, update all elements' data using the `updateDataSync` method. The `reAnimate: true` parameter ensures an animation effect when updating data.
+
+* After 9 seconds, remove two months of sales data using the `updateDataSync` method. The `reAnimate: true` parameter ensures an animation effect when removing data.
+
+* After 12 seconds, update the state of elements using the `updateState` method. Here, a `selected` state is set, changing the fill color of elements to red when their `sales` value is greater than 40.
+
+* After 15 seconds, destroy the chart instance using the `release` method, exiting the chart.
+
+---
+
+
+
#### Animation Flowchart
+
#### Process Description
+1. **Create Chart Configuration and Data**: Define initial chart configuration and data.
+1. **Create VChart Instance**: Create a VChart instance using the configuration and DOM container.
+1. **Render Chart**: Call the `renderAsync` method to render the chart, triggering the animation entrance effect.
+1. **Animation Entrance**: Automatically trigger entrance animation after the chart is rendered.
+1. **Data Update (Add Elements)**: Add data using the `updateDataSync` method, triggering add animation.
+1. **Data Update (Update Elements)**: Update data using the `updateDataSync` method, triggering update animation.
+1. **Data Update (Remove Elements)**: Remove data using the `updateDataSync` method, triggering exit animation.
+1. **Use of Element State**: Update element state using the `updateState` method, setting styles under specific conditions.
+1. **Chart Exit**: Destroy the chart instance using the `release` method, exiting the chart.
+
+
+### Source Code Implementation Process
+
+1. **Initialize VChart Instance**
+
+When you create a `VChart` instance and pass in `spec`, the constructor handles the `animation` configuration:
+
+File: `vchart.ts` Method: `constructor`
+
+```xml
+constructor(spec: ISpec, options: IInitOption) {
+ this._option = mergeOrigin(this._option, { animation: (spec as any).animation !== false }, options);
+ *// ...*
+}
+
+```
+This code ensures that if animation is not explicitly disabled in `spec` (i.e., `animation !== false`), then animation is enabled.
+
+1. Set a new spec and initialize the chart
+
+In the `VChart` class, the `_setNewSpec` method is used to set a new `spec` and convert it to a format used internally:
+
+File: `vchart.ts` Method: `_setNewSpec`
+
+```xml
+private _setNewSpec(spec: any, forceMerge?: boolean): boolean {
+ if (!spec) {
+ return false;
+ }
+ if (isString(spec)) {
+ spec = JSON.parse(spec);
+ }
+ if (forceMerge && this._originalSpec) {
+ spec = mergeSpec({}, this._originalSpec, spec);
+ }
+ this._originalSpec = spec;
+ this._spec = this._getSpecFromOriginalSpec();
+ return true;
+}
+
+```
+Next, the `initChartSpec` method initializes the chart specifications based on `spec`:
+
+File: `vchart.ts` Method: `initChartSpec`
+
+```xml
+private _initChartSpec(spec: any, actionSource: VChartRenderActionSource) {
+ *// 如果用户注册了函数,在配置中替换相应函数名为函数内容*
+ if (VChart.getFunctionList() && VChart.getFunctionList().length) {
+ spec = functionTransform(spec, VChart);
+ }
+ this._spec = spec;
+ if (!this._chartSpecTransformer) {
+ this._chartSpecTransformer = Factory.createChartSpecTransformer(
+ this._spec.type,
+ this._getChartOption(this._spec.type)
+ );
+ }
+ this._chartSpecTransformer?.transformSpec(this._spec);
+ *// 插件生命周期*
+ this._chartPluginApply('onAfterChartSpecTransform', this._spec, actionSource);
+ this._specInfo = this._chartSpecTransformer?.transformModelSpec(this._spec);
+ *// 插件生命周期*
+ this._chartPluginApply('onAfterModelSpecTransform', this._spec, this._specInfo, actionSource);
+}
+
+```
+1. Create and initialize Chart instance
+
+In the `_initChart` method, create and initialize the chart instance:
+
+File: `vchart.ts` Method: `_initChart`
+
+```xml
+private _initChart(spec: any) {
+ if (!this._compiler) {
+ this._option?.onError('compiler is not initialized');
+ return;
+ }
+ if (this._chart) {
+ this._option?.onError('chart is already initialized');
+ return;
+ }
+ const chart = Factory.createChart(spec.type, spec, this._getChartOption(spec.type));
+ if (!chart) {
+ this._option?.onError('init chart fail');
+ return;
+ }
+ this._chart = chart;
+ this._chart.setCanvasRect(this._currentSize.width, this._currentSize.height);
+ this._chart.created(this._chartSpecTransformer);
+ this._chart.init();
+ this._event.emit(ChartEvent.initialized, {
+ chart,
+ vchart: this
+ });
+}
+
+```
+1. Update Animation State
+
+When the chart needs to be re-rendered or updated, the `_updateAnimateState` method is called to update the animation state:
+
+File: `vchart.ts` Method: `_updateAnimateState`
+
+```xml
+private _updateAnimateState(initial?: boolean) {
+ if (this._option.animation) {
+ const animationState = initial ? AnimationStateEnum.appear : AnimationStateEnum.update;
+ this._chart?.getAllRegions().forEach(region => {
+ region.animate?.updateAnimateState(animationState, true);
+ });
+ this._chart?.getAllComponents().forEach(component => {
+ component.animate?.updateAnimateState(animationState, true);
+ });
+ }
+}
+
+```
+* **Initial State**: If `initial` is `true`, set the animation state to `AnimationStateEnum.appear` (entrance animation).
+
+* **Update State**: Otherwise, set it to `AnimationStateEnum.update` (update animation).
+
+1. Render the chart
+
+In the `renderSync` and `renderAsync` methods, the `animation` configuration is passed to the compiler for rendering:
+
+File: `vchart.ts` Method: `_renderSync`
+
+```xml
+protected _renderSync = (option: IVChartRenderOption = {}) => {
+ const self = this as unknown as IVChart;
+ if (!this._beforeRender(option)) {
+ return self;
+ }
+ *// 填充数据绘图*
+ this._compiler?.render(option.morphConfig);
+ this._afterRender();
+ return self;
+};
+
+```
+1. Update of Animation State
+
+In the `updateSpec` and `updateCustomConfigAndRerender` methods, the `reAnimate` flag is used to decide whether to re-trigger the animation:
+
+File: `vchart.ts` Methods: `updateSpec` and `updateCustomConfigAndRerender`
+
+```xml
+if (userUpdateOptions?.reAnimate) {
+ this.stopAnimation();
+ this._updateAnimateState(true);
+}
+
+```
+
+
+### Overview of Animation System Design
+
+
+
+The animation system design of VChart follows the principles of modularity, extensibility, and easy configuration, aiming to provide developers with a flexible and powerful tool to create rich animation effects. Below are the key components of the system and their working principles:
+
+### Principles
+
+#### 1. Animation Interface and Abstraction
+
+
+
+* **IAnimate Interface**: Defines the methods and properties that all animations must implement, including obtaining a unique ID, updating animation state, and getting the state signal name.
+
+*
+
+* **IAnimationSpec Interface**: Specifies the structure of animation configuration, covering various animation settings from entrance to exit.
+
+
+
+classDiagram
+
+ class AnimationStateEnum {
+
+ --Enum--
+
+ appear: AnimationStateEnum
+
+ disappear: AnimationStateEnum
+
+ enter: AnimationStateEnum
+
+ update: AnimationStateEnum
+
+ exit: AnimationStateEnum
+
+ state: AnimationStateEnum
+
+ normal: AnimationStateEnum
+
+ none: AnimationStateEnum
+
+ }
+
+
+
+ class IAnimate {
+
+ <>
+
+ +updateAnimateState(state: AnimationStateEnum, noRender?: boolean): void
+
+ +getAnimationStateSignalName(): string
+
+ +id: number
+
+ }
+
+
+
+ class ICartesianGroupAnimationParams {
+
+ <>
+
+ +direction(): "x" | "y"
+
+ +orient(): "positive" | "negative"
+
+ +width(): number
+
+ +height(): number
+
+ }
+
+
+
+ class AnimateManager {
+
+ --Attributes--
+
+ -_stateMap: IAnimateState & StateMap
+
+ +id: number
+
+ --Methods--
+
+ +updateAnimateState(state: AnimationStateEnum, noRender?: boolean): void
+
+ +getAnimationStateSignalName(): string
+
+ +constructor()
+
+ }
+
+
+
+ class MarkAnimationSpec {
+
+ --Attributes--
+
+ appear: IAnimationConfig
+
+ enter: IAnimationConfig
+
+ update: IAnimationConfig[]
+
+ exit: IAnimationConfig
+
+ disappear: IAnimationConfig
+
+ }
+
+
+
+ class IAnimationSpec {
+
+ --Attributes--
+
+ animationAppear: boolean | IStateAnimateSpec | IMarkAnimateSpec
+
+ animationEnter: boolean | ICommonStateAnimateSpec | IMarkAnimateSpec
+
+ animationUpdate: boolean | ICommonStateAnimateSpec | IMarkAnimateSpec
+
+ animationExit: boolean | ICommonStateAnimateSpec | IMarkAnimateSpec
+
+ animationDisappear: boolean | ICommonStateAnimateSpec | IMarkAnimateSpec
+
+ animationState: boolean | IStateAnimationConfig
+
+ animationNormal: IMarkAnimateSpec
+
+ }
+
+
+
+ class IStateAnimateSpec {
+
+ --Attributes--
+
+ duration?: number
+
+ delay?: number
+
+ easing?: EasingType
+
+ oneByOne?: boolean
+
+ preset?: Preset | false
+
+ }
+
+
+
+ class ICommonStateAnimateSpec {
+
+ --Attributes--
+
+ duration?: number
+
+ delay?: number
+
+ easing?: EasingType
+
+ oneByOne?: boolean
+
+ }
+
+
+
+ class IMorphSeriesSpec {
+
+ --Attributes--
+
+ enable?: boolean
+
+ morphKey?: string
+
+ morphElementKey?: string
+
+ }
+
+
+
+ class IAnimateState {
+
+ --Attributes--
+
+ animationState: { callback: (datum: any, element: IElement) => AnimationStateEnum }
+
+ }
+
+
+
+ class IAnimationConfig {
+
+ --Attributes--
+
+ type?: string
+
+ channel?: string
+
+ custom?: Function
+
+ customParameters?: Function
+
+ oneByOne?: boolean | number
+
+ duration?: number
+
+ easing?: EasingType
+
+ delay?: number
+
+ delayAfter?: number
+
+ }
+
+
+
+ % Relationships
+
+ AnimationStateEnum "1" --|> "many" AnimateManager: Uses
+
+ AnimateManager "1" --|> "1" IAnimate: Implements
+
+ AnimateManager "1" -- "1" ICartesianGroupAnimationParams: Depends
+
+ IAnimationSpec "1" -- "many" spec.ts: Defined in
+
+ MarkAnimationSpec "1" -- "1" config.ts: Used by config.ts
+
+ IAnimationConfig "1" -- "many" utils.ts: Processed by utils.ts
+
+ IStateAnimateSpec "1" -- "1" ICommonStateAnimateSpec: Inherits
+
+ IAnimationSpec "1" -- "1" IStateAnimateSpec: Associates
+
+ IAnimationSpec "1" -- "1" IMorphSeriesSpec: Associates
+
+ IAnimateState "1" -- "1" AnimateManager: Internally used
+
+ IAnimationConfig "1" -- "1" ICommonStateAnimateSpec: Inherits
+
+
+
+#### 2. Animation Manager
+
+
+
+* **AnimateManager Class**: Inherits from `StateManager` and implements the `IAnimate` interface, responsible for managing the state of animations and providing methods to update animations based on the incoming state. It handles the update and retrieval of animation states and updates animation states based on different states.
+
+
+
+#### 3. Factory Pattern
+
+
+
+* **Factory Class**: Used to register new animation types, allowing custom animation logic to be added to chart components. Through the static method `registerAnimation`, specific types of animations can be associated with their configurations for easy subsequent calls.
+
+
+
+#### 4. Animation Configuration Generation
+
+
+
+* **animationConfig Function**: Generates the final animation configuration based on default and user-provided configurations. This function traverses all animation states (such as appear, enter, update, etc.) and constructs a complete animation configuration object based on user or default configurations.
+
+
+
+#### 5. Animation Task Interface
+
+
+
+* **IAnimationTask Interface**: Defines the data structure of an animation task, which is crucial for understanding complex animation sequences. Each task contains time offsets, action queues, and successor task lists, forming a chain-like animation execution mechanism.
+
+
+
+#### 6. Specific Implementation of Animation
+
+
+
+* Each specific chart series (such as bar chart, pie chart, scatter plot, etc.) has its own animation implementation files, which contain preset animation functions for that series. For example, a bar chart may have growth animations, fade-in animations, etc.; a pie chart may have sector expansion animations, etc.
+
+
+
+
+Through the above steps, we have completed a simple yet complete animation process creation. In this process, we utilized the modular design of the VChart animation system to handle chart configuration, animation registration, chart instantiation, data updates, and animation state management separately. This design not only makes the code clearer and more readable but also enhances the system's flexibility and maintainability. Developers can easily customize different types of animation effects according to actual needs, thereby enhancing user experience.
+
+
+
+To better understand and interpret these source files, it is recommended to read them in the following order:
+
+1. `**interface.ts**`
+
+* **Reason**: This file defines the core types and interfaces in the animation module, such as `AnimationStateEnum`, `IAnimateState`, and `IAnimate`. Understanding these types and interfaces is the foundation for subsequent code.
+
+* **Key Content**:
+
+* Animation state enumeration `AnimationStateEnum`
+
+* Animation state interface `IAnimateState`
+
+* Animation interface `IAnimate`
+
+1. `**spec.ts**`
+
+* **Reason**: This file defines the specifications for animation configuration, including `ICommonStateAnimateSpec`, `IStateAnimateSpec`, and `IAnimationSpec`. These specifications are used in actual animation configurations, so it is necessary to understand their structure first.
+
+* **Key Content**:
+
+* Common properties of animation configuration `ICommonStateAnimateSpec`
+
+* Animation state configuration `IStateAnimateSpec`
+
+* Animation specification `IAnimationSpec`
+
+1. `**config.ts**`
+
+* **Reason**: This file provides default animation configurations and some preset animation registration functions. Understanding these default configurations helps in understanding how to customize animation configurations.
+
+* **Key Content**:
+
+* Default animation configuration `DEFAULT_ANIMATION_CONFIG`
+
+* Preset animation registration functions (such as `registerScaleInOutAnimation`, `registerFadeInOutAnimation`, etc.)
+
+1. `**utils.ts**`
+
+* **Reason**: This file contains many utility functions for generating and processing animation configurations. Understanding how these functions work can help you better understand how animation configurations are applied.
+
+* **Key Content**:
+
+* Function to generate animation configuration `animationConfig`
+
+* Function to process user animation configuration `userAnimationConfig`
+
+* Utility functions (such as `produceOneByOne`, `shouldMarkDoMorph`, etc.)
+
+1. `**animate-manager.ts**`
+
+* **Reason**: This file implements the `AnimateManager` class, which is the core class for managing animations. Understanding the implementation of this class can let you know how animations are managed and updated.
+
+* **Key Content**:
+
+* Implementation of the `AnimateManager` class
+
+* Method to update animation state `updateAnimateState`
+
+* Method to get animation state signal name `getAnimationStateSignalName`
+
+### Summary
+
+Reading these files in the above order can gradually build an understanding of the entire animation module. Start from the basic types and interfaces, gradually delve into specific configurations and implementation details, and finally understand how animations are managed and applied.
+
+### Reading Order Summary
+
+* `**interface.ts**` Core types and interfaces
+
+* `**spec.ts**` Animation configuration specifications
+
+* `**config.ts**` Default configurations and preset animations
+
+* `**utils.ts**` Utility functions and configuration generation
+
+* `**animate-manager.ts**` Animation management class implementation
+
+ # This document was revised and organized by the following personnel
+ [玄魂](https://github.com/xuanhun)
\ No newline at end of file
diff --git a/docs/assets/contributing/en/sourcecode/10.2-global-morphing-animation.md b/docs/assets/contributing/en/sourcecode/10.2-global-morphing-animation.md
new file mode 100644
index 0000000000..faf75a122b
--- /dev/null
+++ b/docs/assets/contributing/en/sourcecode/10.2-global-morphing-animation.md
@@ -0,0 +1,556 @@
+---
+title: 10.2 Global Morphing Animation
+
+key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM
+---
+## 10.2 Global Morphing Animation
+
+Score: 8
+
+1. Global Animation:
+
+1. Code Entry: `packages/vchart/src/animation/`
+
+1. Key Points:
+
+1. Implementation of Global Animation
+
+1. Other Reference Documents:
+
+https://www.visactor.io/vchart/guide/tutorial_docs/Animation/Animation_Types
+
+https://www.visactor.io/vrender/guide/asd/Basic_Tutorial/Animate
+
+https://visactor.io/vgrammar/guide/guides/animation
+
+[Magic Frame (Part 1): The Principle of Animation Implementation in Front-end Chart Libraries - A vivid visualization work often involves animation. Whether it's various charts or narrative works, organizing the week - Juejin](https://juejin.cn/post/7275270809777520651)
+
+In 10.1, we initially learned about the design of the animation system in VChart and the creation examples of charts. This section continues to introduce the transition design when switching between different chart configurations in VChart.
+
+### Definition
+
+VChart provides morphing animations for switching between related series, which we call **global morphing animations**.
+
+When updating the chart configuration through `updateSpec`, VChart will detect whether the two related series of the old and new charts meet the conditions for morphing animation, thereby executing dynamic transitions between **one-to-one, one-to-many, or many-to-one graphics**. Global morphing animations allow users to have a better visual experience when the type of chart being displayed changes, avoiding the feeling of instantaneous change. After all, visual comfort is an important factor we should focus on in the process of displaying and analyzing data.
+
+> https://visactor.com/vchart/api/API/vchart Reference API Documentation
+>
+
+```Typescript
+updateSpec
+异步spec 更新,会自动渲染图表不需要再调用 renderAsync() 等渲染方法。
+/**
+ * spec 更新
+ * @param spec
+ * @param forceMerge 是否强制合并,默认为 false
+ * @param morphConfig morph 动画配置
+ * @returns
+ */
+updateSpec: (spec: ISpec, forceMerge?: boolean, morphConfig?: IMorphConfig) => Promise;
+
+```
+
+
+
+### Example of Effects
+
+Below are two example configurations to illustrate the effects of this type of transition animation:
+
+#### One-to-One Animation
+
+One-to-one animation refers to the transition animation between two different graphics. For example, in the example below, it shows the global animation when switching between a pie chart and a bar chart:
+
+
+
+
+
+```xml
+/**
+ * 自1.12.0后,全局形变动画需要手动注册才能生效
+ *
+ * import { registerMorph } from '@visactor/vchart';
+ *
+ * registerMorph();
+ */
+
+VCHART_MODULE.registerMorph();
+
+const pieSpec = {
+ type: 'pie',
+ data: [
+ {
+ values: [
+ { type: '1', value: Math.random() },
+ { type: '2', value: Math.random() },
+ { type: '3', value: Math.random() }
+ ]
+ }
+ ],
+ outerRadius: 0.8,
+ innerRadius: 0.6,
+ valueField: 'value',
+ categoryField: 'type',
+ tooltip: false
+};
+
+const barSpec = Object.assign({}, pieSpec, {
+ type: 'bar',
+ xField: 'type',
+ yField: 'value',
+ seriesField: 'type'
+});
+
+const specs = [pieSpec, barSpec];
+
+const vchart = new VChart(specs[0], { dom: CONTAINER_ID });
+
+vchart.renderSync();
+let count = 1;
+setInterval(() => {
+ vchart.updateSpec(specs[count % 2]);
+ count++;
+}, 2000);
+
+
+```
+
+#### One-to-Many Animation
+
+One-to-many animation refers to the transition of a single graphic element into multiple graphic elements. For example, in the example below, a global animation is shown when switching between a bar chart and a scatter plot, where the animation of splitting a large bar into multiple scatter points is a one-to-many animation.
+
+
+
+
+```javascript
+/**
+ * 自1.12.0后,全局形变动画需要手动注册才能生效
+ *
+ * import { registerMorph } from '@visactor/vchart';
+ *
+ * registerMorph();
+ */
+
+VCHART_MODULE.registerMorph();
+
+function calculateAverage(data, dim) {
+ let total = 0;
+ for (let i = 0; i < data.length; i++) {
+ total += data[i][dim];
+ }
+ return (total /= data.length);
+}
+
+function generateData(type) {
+ const data = [];
+ for (let i = 0; i < 10; i++) {
+ data.push({ x: i, y: Math.random(), type });
+ }
+ return data;
+}
+const DataA = generateData('A');
+
+const DataB = generateData('B');
+
+const barSpec = {
+ type: 'common',
+ series: [
+ {
+ type: 'bar',
+ data: { values: [{ value: calculateAverage(DataA, 'y'), type: 'A' }] },
+ xField: 'type',
+ yField: 'value',
+ morph: {
+ morphKey: 'A'
+ }
+ },
+ {
+ type: 'bar',
+ data: { values: [{ value: calculateAverage(DataB, 'y'), type: 'B' }] },
+ xField: 'type',
+ yField: 'value',
+ morph: {
+ morphKey: 'B'
+ }
+ }
+ ],
+ axes: [
+ { orient: 'left', type: 'linear', max: 1 },
+ { orient: 'bottom', type: 'band' }
+ ]
+};
+
+const scatterSpec = {
+ type: 'common',
+ series: [
+ {
+ type: 'scatter',
+ data: { values: DataA },
+ xField: 'x',
+ yField: 'y',
+ seriesField: 'type',
+ morph: {
+ morphKey: 'A',
+ morphElementKey: 'type'
+ }
+ },
+ {
+ type: 'scatter',
+ data: { values: DataB },
+ xField: 'x',
+ yField: 'y',
+ seriesField: 'type',
+ morph: {
+ morphKey: 'B',
+ morphElementKey: 'type'
+ }
+ }
+ ],
+ axes: [
+ { orient: 'left', type: 'linear', zero: false, max: 1 },
+ { orient: 'bottom', type: 'band' }
+ ]
+};
+
+const specs = [barSpec, scatterSpec];
+
+const vchart = new VChart(specs[0], { dom: CONTAINER_ID });
+
+vchart.renderSync();
+let count = 1;
+setInterval(() => {
+ vchart.updateSpec(specs[count % 2]);
+ count++;
+}, 3000);
+
+
+```
+#### Many-to-One Animation
+
+Many-to-one animation refers to multiple graphic elements transitioning into one element. For example, in the example above, we can have multiple points of a scatter series merge into one large column.
+
+### Interpretation of the Source Code Execution Process for Effect Implementation
+
+The transition between different charts can be explained by updating the configuration, and with morphing animation enabled, the transition effects of series elements are automatically recognized. Below is an explanation of the default effect settings.
+
+
+
+
+
+### Draft Interpretation of Global Animation Implementation
+
+Global animations refer to those animation effects that apply at the entire chart level. They can be applied to the overall entrance animation when the chart loads, the unified change animation when data updates, and the overall exit animation before the chart is destroyed. In VChart, the design and implementation of global animations rely on several core components and mechanisms, including the `Factory` class, `AnimateManager` class, `IAnimationSpec` interface, etc.
+
+
+
+#### 1. Animation Registration and Management
+
+
+
+**Factory Class**
+
+
+
+The `Factory` class is a key player in the animation system, responsible for managing and registering various types of animations. Through the static method `registerAnimation`, we can associate specific animation logic with a name for subsequent use.
+
+
+
+```xml
+class Factory {
+ static registerAnimation(key: string, animation: (params?: any, preset?: any) => MarkAnimationSpec) {
+ Factory._animations[key] = animation;
+ }
+}
+
+```
+
+
+When you need to add animation to a chart element, you can use `Factory.getAnimationInKey` to obtain a registered animation and apply it to the corresponding graphic or graphical element.
+
+
+
+#### 2. Animation Configuration Structure
+
+
+
+**IAnimationSpec Interface**
+
+
+
+The `IAnimationSpec` interface defines the basic structure of animation configuration, covering various states from entry (`animationAppear`) to exit (`animationDisappear`). Each state can accept a boolean value (enable/disable), a preset configuration object, or a custom configuration object as a parameter.
+
+
+
+```xml
+interface IAnimationSpec {
+ animationAppear?: boolean | IStateAnimateSpec | IMarkAnimateSpec;
+ animationEnter?: boolean | ICommonStateAnimateSpec | IMarkAnimateSpec;
+ animationUpdate?: boolean | ICommonStateAnimateSpec | IMarkAnimateSpec;
+ animationExit?: boolean | ICommonStateAnimateSpec | IMarkAnimateSpec;
+ animationDisappear?: boolean | ICommonStateAnimateSpec | IMarkAnimateSpec;
+ animationState?: boolean | IStateAnimationConfig;
+ animationNormal?: IMarkAnimateSpec;
+}
+
+```
+
+
+These configuration options allow developers to flexibly control the behavior of animations in different states, such as setting duration, easing functions, animation types, etc.
+
+
+
+#### 3. Animation State Management
+
+
+
+**AnimateManager Class**
+
+
+
+`AnimateManager` inherits from `StateManager` and implements the `IAnimate` interface, used to manage the state of animations. It provides methods to update animation states and trigger corresponding animation logic based on the current state.
+
+
+
+```xml
+class AnimateManager extends StateManager implements IAnimate {
+ updateAnimateState(state: AnimationStateEnum, noRender?: boolean) {
+ if (state === AnimationStateEnum.update) {
+ // 更新状态下的动画逻辑
+ } else if (state === AnimationStateEnum.appear) {
+ // 出现状态下的动画逻辑
+ } else {
+ // 其他状态下的动画逻辑
+ }
+ }
+}
+
+```
+
+
+In addition, `AnimateManager` is also responsible for generating unique identifiers (IDs) and signal names to ensure that each animation instance can be correctly identified and managed.
+
+
+
+#### 4. Animation Configuration Generation
+
+
+
+**animationConfig Function**
+
+
+
+To simplify the merging process between user configurations and default configurations, VChart provides a helper function called `animationConfig`. This function iterates through all possible animation states and constructs the final animation configuration object based on the user-provided configuration or the default configuration.
+
+
+
+```xml
+function animationConfig(
+ defaultConfig: MarkAnimationSpec = {},
+ userConfig?: Partial | IAnimationConfig | IAnimationConfig[]>>,
+ params?: { dataIndex: (datum: any, params: any) => number; dataCount: () => number; }
+): MarkAnimationSpec {
+ const config = {} as MarkAnimationSpec;
+
+ for (let i = 0; i < AnimationStates.length; i++) {
+ const state = AnimationStates[i];
+ const userStateConfig = userConfig ? userConfig[state] : undefined;
+
+ if (userStateConfig === false) continue;
+
+ if (state === 'normal') {
+ userStateConfig && (config.normal = userStateConfig as IAnimationTypeConfig);
+ continue;
+ }
+
+ let defaultStateConfig: IAnimationConfig[];
+ if (isArray(defaultConfig[state])) {
+ defaultStateConfig = defaultConfig[state] as IAnimationConfig[];
+ } else {
+ defaultStateConfig = [{ ...DEFAULT_ANIMATION_CONFIG[state], ...defaultConfig[state] } as any];
+ }
+
+ config[state] = defaultStateConfig;
+ }
+
+ return config;
+}
+
+```
+
+
+This function handles the merging of default configurations and user configurations, considering that certain states (such as `normal`) can directly use the user-provided configuration without additional processing.
+
+
+
+#### 5. Specific Implementation of Global Animation
+
+
+
+**Registration of Global Animation**
+
+
+
+Taking line charts or area charts as an example, the `registerVGrammarLineOrAreaAnimation` function demonstrates how to batch register a series of animation methods. These animations cover effects such as point growth, point movement, and clipping, and are applicable to both the X-axis and Y-axis directions.
+
+
+
+```xml
+const registerVGrammarLineOrAreaAnimation = () => {
+ View.useRegisters([
+ registerGrowPointsInAnimation,
+ registerGrowPointsOutAnimation,
+ registerGrowPointsXInAnimation,
+ registerGrowPointsXOutAnimation,
+ registerGrowPointsYInAnimation,
+ registerGrowPointsYOutAnimation,
+ registerClipInAnimation,
+ registerClipOutAnimation
+ ]);
+};
+
+```
+
+
+**Initialization of Global Animation**
+
+
+
+In the implementation files of specific series (such as bar charts, pie charts, etc.), the `initAnimation` method is usually called during the initialization phase to set up animation configurations. This method combines user-provided configurations with default configurations to generate the final animation configuration and applies it to the corresponding graphic elements or shapes.
+
+
+
+```xml
+initAnimation(): void {
+ const animationParams = getGroupAnimationParams(this);
+ const appearPreset = (this._spec?.animationAppear as IStateAnimateSpec)?.preset;
+ this._symbolMark.setAnimationConfig(
+ animationConfig(
+ Factory.getAnimationInKey('scatter')?.({}, appearPreset),
+ userAnimationConfig(SeriesMarkNameEnum.point, this._spec, this._markAttributeContext),
+ animationParams
+ )
+ );
+}
+
+```
+
+
+Here, the `animationConfig` function is used to merge default configurations and user configurations, while `userAnimationConfig` is responsible for extracting the animation configuration information provided by the user. Finally, the generated configuration is applied to specific graphic elements through the `setAnimationConfig` method.
+
+
+
+#### 6. Execution of Animation Tasks
+
+
+
+**IAnimationTask Interface**
+
+
+
+For complex animation sequences, VChart introduces the `IAnimationTask` interface to describe the data structure of animation tasks. Each task includes time offsets, action queues, and successor task lists, forming a chain-like animation execution mechanism.
+
+
+
+```xml
+interface IAnimationTask {
+ timeOffset: number;
+ actionList: Action[];
+ nextTaskList: IAnimationTask[];
+}
+
+```
+
+
+This design allows multiple animation tasks to be executed sequentially or concurrently, enabling more complex and delicate animation effects.
+
+
+
+#### 7. Example: Creating a Global Entrance Animation
+
+
+
+Suppose we want to add a global fade-in entrance animation to a newly created bar chart. Here are the detailed implementation steps:
+
+
+
+* **Define Animation Configuration**: First, specify `animationAppear` as `true` in the chart configuration to enable the entrance animation. Additionally, you can further customize the specific behavior of the animation, such as choosing a fade-in effect, setting the duration, and easing function.
+
+
+
+```xml
+const chartSpec = {
+ // ... 其他配置 ...
+ animationAppear: {
+ type: 'fadeIn',
+ duration: 1000,
+ easing: 'easeInOutQuad'
+ },
+ series: [
+ {
+ type: 'bar',
+ data: [/* 数据数组 */]
+ }
+ ]
+};
+
+```
+
+
+* **Register Fade-in Animation**: Next, we need to ensure that the fade-in animation has been correctly registered in the system. This step is usually completed at project startup or explicitly called where needed.
+
+
+
+```xml
+import { Factory } from '@visactor/vchart';
+import { Appear_FadeIn } from './series/bar/animation';
+
+Factory.registerAnimation('fadeIn', Appear_FadeIn);
+
+```
+
+
+* **Initialize the chart instance**: With the above configuration, we can initialize a `VChart` instance and pass the configuration to it. This will trigger the chart rendering process and apply the corresponding animation effects.
+
+
+
+```xml
+import { VChart } from '@visactor/vchart';
+
+const container = document.getElementById('chart-container');
+const chart = new VChart({
+ el: container,
+ spec: chartSpec,
+ options: {
+ animation: true, // 开启动画
+ theme: 'light' // 使用浅色主题
+ }
+});
+
+```
+
+
+* **Trigger Animation**: Once the chart is rendered, any changes in data will automatically trigger animations. For example, when the page first loads, all bars will gradually appear with a fade-in effect; when new data is added, new bars will enter in the same way.
+
+
+
+* **Manual Control of Animation**: If you need more precise control over the animation, such as pausing or resuming it, you can use the relevant methods provided by the `VChart` instance.
+
+
+
+```xml
+// 暂停所有正在进行的动画
+chart.pauseAnimation();
+
+// 恢复之前暂停的动画
+chart.resumeAnimation();
+
+```
+
+
+#### Summary
+
+
+
+Through the above steps, we have detailed the implementation principles of global animation in VChart. The animation system of VChart cleverly combines the factory pattern, state manager pattern, and modular animation configuration, providing not only a rich set of built-in animation effects but also supporting highly customizable needs. Developers can flexibly configure and combine different animations according to actual application scenarios to create visual effects that are both beautiful and practical.
+
+ # This document was revised and organized by the following personnel
+ [玄魂](https://github.com/xuanhun)
\ No newline at end of file
diff --git a/docs/assets/contributing/en/sourcecode/10.3-state-change-animation.md b/docs/assets/contributing/en/sourcecode/10.3-state-change-animation.md
new file mode 100644
index 0000000000..b501ef2702
--- /dev/null
+++ b/docs/assets/contributing/en/sourcecode/10.3-state-change-animation.md
@@ -0,0 +1,472 @@
+---
+title: 10.3 State Change Animation
+
+key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM
+---
+## 10.3 State Change Animation
+
+Score: 5
+
+1. State Animation:
+
+1. Code Entry: `packages/vchart/src/animation/`
+
+1. Key Points:
+
+1. Implementation of State Animation
+
+1. Other Reference Documents:
+
+https://www.visactor.io/vchart/guide/tutorial_docs/Animation/Animation_Types
+
+https://www.visactor.io/vrender/guide/asd/Basic_Tutorial/Animate
+
+https://visactor.io/vgrammar/guide/guides/animation
+
+[Magic Frame (Part 1): The Principle of Animation Implementation in Front-end Chart Libraries - A vivid visualization work often involves animation. Whether it's various charts or narrative works, organizing the week - Juejin](https://juejin.cn/post/7275270809777520651)
+
+Often when presenting charts, different graphical elements have their own meanings, and in information display, it is necessary to emphasize or compare certain elements. By switching the state of graphical elements to display data, this process also needs to focus on visual effects, providing a more natural visual experience when the state changes.
+
+### Interpretation of State Animation (including `normal` animation) Implementation
+
+state and normal
+
+
+
+**State Change Animation, Animation Triggered at Any Time**
+
+State animation refers to the animation effects triggered when chart elements change according to their current state. In VChart, the design of state animation allows developers to define specific animation behaviors for different states (such as enter, update, exit, etc.). Specifically, `normal` state animation refers to those animations that loop or persist, running continuously after the chart is rendered until explicitly stopped.
+
+
+
+#### 1. Animation Configuration Structure
+
+
+
+**IAnimationSpec Interface**
+
+
+
+The `IAnimationSpec` interface defines the basic structure of animation configuration, which includes animation settings for different states. For `normal` animations, it can be specified through the `animationNormal` property:
+
+
+
+
+```xml
+interface IAnimationSpec {
+ // ... 其他状态 ...
+ animationNormal?: IMarkAnimateSpec;
+}
+
+```
+
+
+Here, `IMarkAnimateSpec` is a generic interface used to describe the animation configuration of specific elements (such as each bar in a bar chart). In this way, developers can define personalized `normal` animation effects for each element.
+
+
+
+#### 2. Animation Manager
+
+
+
+**AnimateManager Class**
+
+
+
+The `AnimateManager` class is responsible for managing and coordinating the state of all animations. It implements the `IAnimate` interface and provides methods to update and retrieve animation states. For `normal` animations, the `AnimateManager` ensures that these animations automatically start after the chart rendering is complete and can be paused or resumed as needed.
+
+
+
+
+```xml
+class AnimateManager extends StateManager implements IAnimate {
+ updateAnimateState(state: AnimationStateEnum, noRender?: boolean) {
+ if (state === AnimationStateEnum.normal) {
+ this.updateState(
+ {
+ animationState: {
+ callback: (datum: any, element: IElement) => state
+ }
+ },
+ noRender
+ );
+ }
+ }
+}
+
+```
+
+
+When chart elements enter the `normal` state, the `updateAnimateState` method is called and the state is passed to the internal state management logic. This allows all eligible elements to perform the corresponding `normal` animation.
+
+
+
+#### 3. Animation Configuration Generation
+
+
+
+**animationConfig Function**
+
+
+
+To simplify the merging process between user configuration and default configuration, VChart provides a helper function called `animationConfig`. This function iterates over all possible animation states and constructs the final animation configuration object based on the user-provided configuration or the default configuration.
+
+
+
+
+```xml
+function animationConfig(
+ defaultConfig: MarkAnimationSpec = {},
+ userConfig?: Partial | IAnimationConfig | IAnimationConfig[]>>,
+ params?: { dataIndex: (datum: any, params: any) => number; dataCount: () => number; }
+): MarkAnimationSpec {
+ const config = {} as MarkAnimationSpec;
+
+ for (let i = 0; i < AnimationStates.length; i++) {
+ const state = AnimationStates[i];
+ const userStateConfig = userConfig ? userConfig[state] : undefined;
+
+ if (userStateConfig === false) continue;
+
+ if (state === 'normal') {
+ userStateConfig && (config.normal = userStateConfig as IAnimationTypeConfig);
+ continue;
+ }
+
+ let defaultStateConfig: IAnimationConfig[];
+ if (isArray(defaultConfig[state])) {
+ defaultStateConfig = defaultConfig[state] as IAnimationConfig[];
+ } else {
+ defaultStateConfig = [{ ...DEFAULT_ANIMATION_CONFIG[state], ...defaultConfig[state] } as any];
+ }
+
+ config[state] = defaultStateConfig;
+ }
+
+ return config;
+}
+
+```
+
+
+This function handles the animation configuration merging in the `normal` state, ensuring that the user-provided configuration can be correctly applied to specific graphic elements. If the user does not provide a custom `normal` animation configuration, the default configuration is used.
+
+
+
+#### 4. Specific Implementation of `normal` Animation
+
+
+
+Taking a scatter plot as an example, suppose we want to add a slight pulse effect to each data point as a `normal` animation. Here are the detailed implementation steps:
+
+
+
+* **Define Animation Configuration**: First, specify the `animationNormal` configuration for the scatter plot series in the chart configuration. Here we can choose the built-in `pulse` animation type and adjust its duration and easing function.
+
+
+
+
+```xml
+const chartSpec = {
+ series: [
+ {
+ type: 'scatter',
+ data: [/* 数据数组 */],
+ animationNormal: {
+ type: 'pulse', // 使用脉冲效果
+ duration: 800,
+ easing: 'easeInOutQuad'
+ }
+ }
+ ]
+};
+
+```
+
+
+* **Register Animation**: Next, we need to ensure that the `pulse` animation has been correctly registered in the system. This step is usually completed at project startup or explicitly called where needed.
+
+
+
+
+```xml
+import { Factory } from '@visactor/vchart';
+import { pulseAnimation } from './series/scatter/animation';
+
+Factory.registerAnimation('pulse', pulseAnimation);
+
+```
+
+
+ The `pulseAnimation` function here defines the specific logic of the pulse animation, such as how to change the transparency or size of graphic elements.
+
+
+
+* **Initialize the chart instance**: With the above configuration, we can initialize a `VChart` instance and pass the configuration to it. This will trigger the rendering process of the chart and apply the corresponding animation effects.
+
+
+
+
+```xml
+import { VChart } from '@visactor/vchart';
+
+const container = document.getElementById('chart-container');
+const chart = new VChart({
+ el: container,
+ spec: chartSpec,
+ options: {
+ animation: true, // 开启动画
+ theme: 'light' // 使用浅色主题
+ }
+});
+
+```
+
+
+* **Trigger Animation**: Once the chart is rendered, all data points will automatically start executing the `normal` animation. This animation will continuously loop while the chart exists, unless explicitly stopped.
+
+
+
+
+```xml
+// 如果需要暂停所有正在进行的 normal 动画
+chart.pauseAnimation();
+
+// 恢复之前暂停的 normal 动画
+chart.resumeAnimation();
+
+```
+
+
+#### 5. Execution of Animation Tasks
+
+
+
+**IAnimationTask Interface**
+
+
+
+For complex animation sequences, VChart introduces the `IAnimationTask` interface to describe the data structure of animation tasks. Each task includes a time offset, an action queue, and a list of successor tasks, forming a chain-like animation execution mechanism.
+
+
+
+
+```xml
+interface IAnimationTask {
+ timeOffset: number;
+ actionList: Action[];
+ nextTaskList: IAnimationTask[];
+}
+
+```
+
+
+This design allows multiple animation tasks to be executed sequentially or concurrently, achieving more complex and delicate animation effects. For `normal` animations, it can work as part of an independent task chain, collaborating with other animation tasks.
+
+
+
+#### 6. Example: Creating a Scatter Plot with `normal` Animation
+
+
+
+Below is an example of creating a scatter plot with `normal` animation, illustrating how to use VChart's state animation system to implement the basic process.
+
+
+
+##### Step 1: Define Animation Configuration
+
+
+
+First, we need to define the basic configuration of the scatter plot, including the data source and other visual attributes. At the same time, we will specify the `normal` animation configuration here to ensure that each data point can perform the pulse effect.
+
+
+
+
+```xml
+const chartSpec = {
+ series: [
+ {
+ type: 'scatter',
+ data: [
+ { x: 10, y: 20 },
+ { x: 20, y: 30 },
+ { x: 30, y: 40 }
+ ],
+ animationNormal: {
+ type: 'pulse',
+ duration: 800,
+ easing: 'easeInOutQuad'
+ }
+ }
+ ]
+};
+
+```
+
+
+##### Step 2: Register Animation
+
+
+
+Ensure that the required `pulse` animation has been correctly registered in the system. This step is usually completed at project startup or explicitly called where needed.
+
+
+
+
+```xml
+import { Factory } from '@visactor/vchart';
+import { pulseAnimation } from './series/scatter/animation';
+
+Factory.registerAnimation('pulse', pulseAnimation);
+
+```
+
+
+##### Step 3: Initialize the Chart Instance
+
+
+
+With the above configuration, we can initialize a `VChart` instance and pass the configuration to it. This step will trigger the chart rendering process and apply the corresponding animation effects.
+
+
+
+
+```xml
+import { VChart } from '@visactor/vchart';
+
+const container = document.getElementById('chart-container');
+const chart = new VChart({
+ el: container,
+ spec: chartSpec,
+ options: {
+ animation: true, // 开启动画
+ theme: 'light' // 使用浅色主题
+ }
+});
+
+```
+
+
+##### Step 4: Trigger `normal` Animation
+
+
+
+Once the chart is rendered, all data points will automatically start executing the `normal` animation. This animation will continue to loop as long as the chart exists, unless explicitly stopped.
+
+
+
+
+```xml
+// 如果需要暂停所有正在进行的 normal 动画
+chart.pauseAnimation();
+
+// 恢复之前暂停的 normal 动画
+chart.resumeAnimation();
+
+```
+
+
+##### Step 5: Dynamically Control Animation
+
+
+
+In some cases, you may want to dynamically control the behavior of the `normal` animation, such as changing the speed or style of the animation. VChart provides flexible methods to achieve this.
+
+
+
+
+```xml
+// 更新某个系列的 normal 动画配置
+chart.updateSeriesOptions(0, {
+ animationNormal: {
+ duration: 1200, // 更改持续时间
+ easing: 'linear' // 更改缓动函数
+ }
+});
+
+// 重新应用新的动画配置
+chart.render();
+
+```
+
+
+#### 7. Animation State Management
+
+
+
+**State Transition and Update**
+
+
+
+`AnimateManager` not only manages `normal` animations but also handles animation transitions in other states. For example, when new data is added, the animation in the `enter` state is triggered; when data is updated, the animation in the `update` state takes effect; and when data is removed, the animation in the `exit` state comes into play.
+
+
+
+
+```xml
+class AnimateManager extends StateManager implements IAnimate {
+ updateAnimateState(state: AnimationStateEnum, noRender?: boolean) {
+ if (state === AnimationStateEnum.update) {
+ // 更新状态下的动画逻辑
+ } else if (state === AnimationStateEnum.appear) {
+ // 出现状态下的动画逻辑
+ } else if (state === AnimationStateEnum.normal) {
+ // normal 状态下的动画逻辑
+ this.updateState(
+ {
+ animationState: {
+ callback: (datum: any, element: IElement) => state
+ }
+ },
+ noRender
+ );
+ }
+ }
+}
+
+```
+
+
+In this example, when the element enters the `normal` state, the `updateAnimateState` method will update the element's state and trigger the corresponding animation logic. This means that each data point will execute the animation according to the preset `normal` animation configuration until the state changes again.
+
+
+
+#### 8. Animation Lifecycle Management
+
+
+
+**Event Listeners and Hooks**
+
+
+
+To better manage the animation lifecycle, VChart provides a series of event listeners and hook functions. For example, the `VGRAMMAR_HOOK_EVENT.AFTER_DO_RENDER` event can be triggered after the chart is initially rendered, while the `VGRAMMAR_HOOK_EVENT.ANIMATION_END` will be triggered at the end of the animation.
+
+
+
+
+```xml
+this._event.on(VGRAMMAR_HOOK_EVENT.AFTER_DO_RENDER, () => {
+ this.runAnimationByState(AnimationStateEnum.normal);
+});
+
+this._event.on(VGRAMMAR_HOOK_EVENT.ANIMATION_END, ({ event }) => {
+ if (event.animationState === AnimationStateEnum.appear) {
+ this.runAnimationByState(AnimationStateEnum.normal);
+ }
+});
+
+```
+
+
+This code demonstrates how to start the `normal` animation immediately after the chart rendering is completed, and how to seamlessly switch to the `normal` animation after the entrance animation ends. This design ensures a smooth transition between animations, enhancing the user experience.
+
+
+
+### Summary
+
+
+
+Through the above steps, we have detailed the implementation principle of the `normal` state animation in VChart. The `normal` animation, as a type of state animation, is mainly used to describe the animation effect of chart elements continuously existing in a stable state. VChart ensures the flexibility and maintainability of the `normal` animation through modular design, factory pattern, state manager pattern, and event-driven mechanism. Developers can easily customize different types of `normal` animation effects according to actual needs, thereby enhancing the visual appeal and interactive experience of the chart.
+
+ # This document was revised and organized by the following personnel
+ [玄魂](https://github.com/xuanhun)
\ No newline at end of file
diff --git a/docs/assets/contributing/en/sourcecode/10.4-data-update-animation.md b/docs/assets/contributing/en/sourcecode/10.4-data-update-animation.md
new file mode 100644
index 0000000000..c58bc0d7a2
--- /dev/null
+++ b/docs/assets/contributing/en/sourcecode/10.4-data-update-animation.md
@@ -0,0 +1,608 @@
+---
+title: 10.4 Data Update Animation
+
+key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM
+---
+## 10.4 Data Update Animation
+
+Score: 8
+
+1. Update Animation:
+
+1. Code Entry: `packages/vchart/src/animation/`
+
+1. Key Points:
+
+1. Implementation of Update Animation
+
+1. Other Reference Documents:
+
+https://www.visactor.io/vchart/guide/tutorial_docs/Animation/Animation_Types
+
+https://www.visactor.io/vrender/guide/asd/Basic_Tutorial/Animate
+
+https://visactor.io/vgrammar/guide/guides/animation
+
+[Magic Frame (Part 1): The Principle of Animation Implementation in Front-end Chart Libraries - A vivid visualization work often involves animation. Whether it's various charts or narrative works, organizing the week - Juejin](https://juejin.cn/post/7275270809777520651)
+
+After understanding how to add change animation effects when specific chart element data changes, we can configure data update animations for series elements in a specific type of chart to meet animation effects in specific scenarios.
+
+### Interpretation of Data Update Animation Implementation
+
+
+
+Data update animation refers to the animation effect executed by chart elements based on the new data state when the chart data changes. In VChart, this animation is designed to be very flexible and can be applied to three scenarios: new data entry (`enter`), existing data update (`update`), and old data removal (`exit`). Below is a detailed interpretation of the implementation.
+
+
+
+#### 1. Animation Configuration Structure
+
+
+
+**IAnimationSpec Interface**
+
+
+
+The `IAnimationSpec` interface defines the basic structure of animation configuration, which includes animation settings for different states. For data update animations, it mainly involves the following three properties:
+
+
+
+* `animationEnter`: Describes the animation effect when new data is added.
+
+* `animationUpdate`: Describes the animation effect when existing data is updated.
+
+* `animationExit`: Describes the animation effect when old data is removed.
+
+
+
+
+```xml
+interface IAnimationSpec {
+ animationEnter?: boolean | ICommonStateAnimateSpec | IMarkAnimateSpec;
+ animationUpdate?: boolean | ICommonStateAnimateSpec | IMarkAnimateSpec;
+ animationExit?: boolean | ICommonStateAnimateSpec | IMarkAnimateSpec;
+}
+
+```
+
+
+Each attribute can accept a boolean value (enable/disable), a preset configuration object, or a custom configuration object as a parameter, providing developers with a high degree of customization possibilities.
+
+
+
+#### 2. Animation Manager
+
+
+
+**AnimateManager Class**
+
+
+
+The `AnimateManager` class is responsible for managing and coordinating the state of all animations. It implements the `IAnimate` interface and provides methods to update and retrieve animation states. For data update animations, the `AnimateManager` ensures that these animations are automatically triggered when data changes and can be paused or resumed as needed.
+
+
+
+
+```xml
+class AnimateManager extends StateManager implements IAnimate {
+ updateAnimateState(state: AnimationStateEnum, noRender?: boolean) {
+ if (state === AnimationStateEnum.update) {
+ this.updateState(
+ {
+ animationState: {
+ callback: (datum: any, element: IElement) => element.diffState
+ }
+ },
+ noRender
+ );
+ } else if (state === AnimationStateEnum.appear) {
+ // 出现状态下的动画逻辑
+ } else if (state === AnimationStateEnum.exit) {
+ // 退出状态下的动画逻辑
+ }
+ }
+}
+
+```
+
+
+When chart elements enter the `update`, `appear`, or `exit` states, the `updateAnimateState` method is called and passes the state to the internal state management logic. This allows all eligible elements to perform the corresponding animations.
+
+
+
+#### 3. Animation Configuration Generation
+
+
+
+**animationConfig Function**
+
+
+
+To simplify the merging process between user configurations and default configurations, VChart provides a helper function called `animationConfig`. This function iterates over all possible animation states and constructs the final animation configuration object based on the user-provided configuration or the default configuration.
+
+
+
+
+```xml
+function animationConfig(
+ defaultConfig: MarkAnimationSpec = {},
+ userConfig?: Partial | IAnimationConfig | IAnimationConfig[]>>,
+ params?: { dataIndex: (datum: any, params: any) => number; dataCount: () => number; }
+): MarkAnimationSpec {
+ const config = {} as MarkAnimationSpec;
+
+ for (let i = 0; i < AnimationStates.length; i++) {
+ const state = AnimationStates[i];
+ const userStateConfig = userConfig ? userConfig[state] : undefined;
+
+ if (userStateConfig === false) continue;
+
+ if (state === 'enter' || state === 'update' || state === 'exit') {
+ let defaultStateConfig: IAnimationConfig[];
+ if (isArray(defaultConfig[state])) {
+ defaultStateConfig = defaultConfig[state] as IAnimationConfig[];
+ } else {
+ defaultStateConfig = [{ ...DEFAULT_ANIMATION_CONFIG[state], ...defaultConfig[state] } as any];
+ }
+
+ config[state] = defaultStateConfig;
+ }
+ }
+
+ return config;
+}
+
+```
+
+
+This function handles the merging of animation configurations in `enter`, `update`, and `exit` states, ensuring that the configurations provided by the user are correctly applied to specific graphical elements. If the user does not provide custom animation configurations, the default configurations are used.
+
+
+
+#### 4. Specific Implementation of Data Update Animation
+
+
+
+Taking a bar chart as an example, suppose we want to add a fade-in effect for newly added data points, a scaling effect for updated data points, and a fade-out effect for removed data points. Here are the detailed implementation steps:
+
+
+
+* **Define Animation Configuration**: First, specify the `animationEnter`, `animationUpdate`, and `animationExit` configurations for the bar chart series in the chart configuration. Here, we can choose built-in animation types and adjust their duration and easing functions.
+
+
+
+```xml
+const chartSpec = {
+ series: [
+ {
+ type: 'bar',
+ data: [/* 初始数据数组 */],
+ animationEnter: {
+ type: 'fadeIn', // 新数据点淡入
+ duration: 800,
+ easing: 'easeInOutQuad'
+ },
+ animationUpdate: {
+ type: 'scaleIn', // 更新数据点缩放
+ duration: 500,
+ easing: 'easeInOutQuad'
+ },
+ animationExit: {
+ type: 'fadeOut', // 移除数据点淡出
+ duration: 600,
+ easing: 'easeInOutQuad'
+ }
+ }
+ ]
+};
+
+```
+
+
+* **Register Animation**: Next, we need to ensure that the required animations have been correctly registered in the system. This step is usually completed at project startup or explicitly called where needed.
+
+
+
+
+```xml
+import { Factory } from '@visactor/vchart';
+import { Appear_FadeIn, ScaleInOutAnimation, Appear_FadeOut } from './series/bar/animation';
+
+// 注册淡入动画
+Factory.registerAnimation('fadeIn', Appear_FadeIn);
+
+// 注册缩放动画
+Factory.registerAnimation('scaleIn', ScaleInOutAnimation);
+
+// 注册淡出动画
+Factory.registerAnimation('fadeOut', Appear_FadeOut);
+
+```
+
+
+ The `Appear_FadeIn`, `ScaleInOutAnimation`, and `Appear_FadeOut` functions here define the specific logic for fade-in, scale, and fade-out animations, such as how to change the transparency or size of graphic elements.
+
+
+
+* **Initialize the chart instance**: With the above configuration, we can initialize a `VChart` instance and pass the configuration to it. This will trigger the rendering process of the chart and apply the corresponding animation effects.
+
+
+
+
+```xml
+import { VChart } from '@visactor/vchart';
+
+const container = document.getElementById('chart-container');
+const chart = new VChart({
+ el: container,
+ spec: chartSpec,
+ options: {
+ animation: true, // 开启动画
+ theme: 'light' // 使用浅色主题
+ }
+});
+
+```
+
+
+* **Trigger Animation**: Once the chart is rendered, any change in data will automatically trigger animation. For example, when new data is added, the `animationEnter` configuration takes effect; when data is updated, the `animationUpdate` configuration is effective; and when data is removed, the `animationExit` configuration is applied.
+
+
+
+
+```xml
+// 假设一段时间后需要更新数据
+setTimeout(() => {
+ const newData = [/* 新的数据数组 */];
+ chart.updateSeriesData(newData);
+}, 5000);
+
+```
+
+
+#### 5. Execution of Animation Tasks
+
+
+
+**IAnimationTask Interface**
+
+
+
+For complex animation sequences, VChart introduces the `IAnimationTask` interface to describe the data structure of animation tasks. Each task includes a time offset, an action queue, and a list of successor tasks, forming a chain-like animation execution mechanism.
+
+
+
+
+```xml
+interface IAnimationTask {
+ timeOffset: number;
+ actionList: Action[];
+ nextTaskList: IAnimationTask[];
+}
+
+```
+
+
+This design allows multiple animation tasks to be executed sequentially or concurrently, enabling more complex and delicate animation effects. For data update animations, it can be part of an independent task chain, working in conjunction with other animation tasks.
+
+
+
+#### 6. Example: Creating a Bar Chart with Data Update Animation
+
+
+
+Below is an example of creating a bar chart with data update animation, illustrating how to use VChart's data update animation system to implement the basic process.
+
+
+
+##### Step 1: Define Animation Configuration
+
+
+
+First, we need to define the basic configuration of the bar chart, including the data source and other visual attributes. At the same time, we will also specify the `animationEnter`, `animationUpdate`, and `animationExit` configurations here to ensure that the corresponding animation effects can be triggered when the data changes.
+
+
+
+
+```xml
+const chartSpec = {
+ series: [
+ {
+ type: 'bar',
+ data: [
+ { value: 10 },
+ { value: 20 },
+ { value: 30 }
+ ],
+ animationEnter: {
+ type: 'fadeIn',
+ duration: 800,
+ easing: 'easeInOutQuad'
+ },
+ animationUpdate: {
+ type: 'scaleIn',
+ duration: 500,
+ easing: 'easeInOutQuad'
+ },
+ animationExit: {
+ type: 'fadeOut',
+ duration: 600,
+ easing: 'easeInOutQuad'
+ }
+ }
+ ]
+};
+
+```
+
+
+##### Step 2: Register Animation
+
+
+
+Ensure that the required animations have been correctly registered in the system. This step is usually completed at project startup or explicitly called where needed.
+
+
+
+
+```xml
+import { Factory } from '@visactor/vchart';
+import { Appear_FadeIn, ScaleInOutAnimation, Appear_FadeOut } from './series/bar/animation';
+
+Factory.registerAnimation('fadeIn', Appear_FadeIn);
+Factory.registerAnimation('scaleIn', ScaleInOutAnimation);
+Factory.registerAnimation('fadeOut', Appear_FadeOut);
+
+```
+
+
+##### Step 3: Initialize the Chart Instance
+
+
+
+With the above configuration, we can initialize a `VChart` instance and pass the configuration to it. This step will trigger the chart rendering process and apply the corresponding animation effects.
+
+
+
+
+```xml
+import { VChart } from '@visactor/vchart';
+
+const container = document.getElementById('chart-container');
+const chart = new VChart({
+ el: container,
+ spec: chartSpec,
+ options: {
+ animation: true, // 开启动画
+ theme: 'light' // 使用浅色主题
+ }
+});
+
+```
+
+
+##### Step 4: Trigger Data Update Animation
+
+
+
+Once the chart is rendered, any changes in the data will automatically trigger animations. For example, when new data is added, the `animationEnter` configuration will take effect; when data is updated, the `animationUpdate` configuration is effective; and when data is removed, the `animationExit` configuration is applied.
+
+
+
+
+```xml
+// 模拟数据更新
+setTimeout(() => {
+ const updatedData = [
+ { value: 15 }, // 更新第一个数据点
+ { value: 25 }, // 更新第二个数据点
+ { value: 35 }, // 更新第三个数据点
+ { value: 45 } // 添加一个新的数据点
+ ];
+
+ // 更新图表数据并触发动画
+ chart.updateSeriesData(updatedData);
+}, 5000);
+
+```
+
+
+In this example, the `updateSeriesData` method triggers a series of animations:
+
+* For newly added data points (the fourth data point), the `animationEnter` configuration makes it gradually appear with a fade-in effect.
+
+* For existing data points (the first three data points), the `animationUpdate` configuration adjusts their size based on the new data values and transitions them with a scaling effect.
+
+* If any data points are removed, the `animationExit` configuration makes them disappear with a fade-out effect.
+
+
+
+##### Step 5: Dynamically Control Animations
+
+
+
+In some cases, you may want to dynamically control the behavior of data update animations, such as changing the speed or style of the animation. VChart provides flexible methods to achieve this.
+
+
+
+
+```xml
+// 更新某个系列的数据更新动画配置
+chart.updateSeriesOptions(0, {
+ animationEnter: {
+ duration: 1000, // 更改淡入动画的持续时间
+ easing: 'linear' // 更改缓动函数
+ },
+ animationUpdate: {
+ duration: 700, // 更改缩放动画的持续时间
+ easing: 'easeInOutCubic' // 更改缓动函数
+ },
+ animationExit: {
+ duration: 900, // 更改淡出动画的持续时间
+ easing: 'easeInOutCubic' // 更改缓动函数
+ }
+});
+
+// 重新应用新的动画配置
+chart.render();
+
+```
+
+
+#### 7. Animation Lifecycle Management
+
+
+
+**Event Listeners and Hooks**
+
+
+
+To better manage the lifecycle of animations, VChart provides a series of event listeners and hook functions. For example, the `VGRAMMAR_HOOK_EVENT.AFTER_DO_RENDER` event can be triggered after the chart is initially rendered, while `VGRAMMAR_HOOK_EVENT.ANIMATION_END` will be triggered at the end of the animation.
+
+
+
+
+```xml
+this._event.on(VGRAMMAR_HOOK_EVENT.AFTER_DO_RENDER, () => {
+ // 图表首次渲染完成后的逻辑
+});
+
+this._event.on(VGRAMMAR_HOOK_EVENT.ANIMATION_END, ({ event }) => {
+ if (event.animationState === AnimationStateEnum.enter) {
+ // enter 动画结束后的逻辑
+ } else if (event.animationState === AnimationStateEnum.update) {
+ // update 动画结束后的逻辑
+ } else if (event.animationState === AnimationStateEnum.exit) {
+ // exit 动画结束后的逻辑
+ }
+});
+
+```
+
+
+This code demonstrates how to execute specific logic at different animation stages to ensure smooth transitions between animations and enhance user experience.
+
+
+
+#### 8. Difference Detection and Animation Trigger
+
+
+
+**Difference Detection**
+
+
+
+During the data update process, VChart automatically performs difference detection to identify which data points are new, updated, or removed. Based on this information, `AnimateManager` triggers the corresponding animations.
+
+
+
+
+```xml
+if (state === AnimationStateEnum.update) {
+ this.updateState(
+ {
+ animationState: {
+ callback: (datum: any, element: IElement) => element.diffState
+ }
+ },
+ noRender
+ );
+}
+
+```
+
+
+The `diffState` attribute here indicates the type of state change for the element, such as `enter`, `update`, or `exit`. The `AnimateManager` will decide which type of animation to apply based on this attribute.
+
+
+
+#### 9. Specific Implementation of Animation
+
+
+
+**Specific Animation Functions**
+
+
+
+Each specific animation function (such as `Appear_FadeIn`, `ScaleInOutAnimation`, and `Appear_FadeOut`) defines the specific behavior of the animation. For example, the `Appear_FadeIn` function might look like this:
+
+
+
+
+```xml
+export const Appear_FadeIn: IAnimationTypeConfig = {
+ type: 'fadeIn',
+ duration: 800,
+ easing: 'easeInOutQuad',
+ channel: {
+ opacity: { from: 0, to: 1 }
+ }
+};
+
+```
+
+
+This code defines a fade-in animation by adjusting the `opacity` attribute of a graphic element from 0 to 1 to achieve a visual fade-in effect.
+
+
+
+#### 10. Animation State Management
+
+
+
+**State Transition and Update**
+
+
+
+`AnimateManager` not only manages `normal` animations but also handles animation transitions in other states. For example, when new data is added, the animation in the `enter` state is triggered; when data is updated, the animation in the `update` state takes effect; and when data is removed, the animation in the `exit` state comes into play.
+
+
+
+
+```xml
+class AnimateManager extends StateManager implements IAnimate {
+ updateAnimateState(state: AnimationStateEnum, noRender?: boolean) {
+ if (state === AnimationStateEnum.update) {
+ this.updateState(
+ {
+ animationState: {
+ callback: (datum: any, element: IElement) => element.diffState
+ }
+ },
+ noRender
+ );
+ } else if (state === AnimationStateEnum.appear) {
+ // appear 状态下的动画逻辑
+ } else if (state === AnimationStateEnum.exit) {
+ // exit 状态下的动画逻辑
+ }
+ }
+}
+
+```
+
+
+When chart elements enter the `update`, `appear`, or `exit` states, the `updateAnimateState` method is called and passes the state to the internal state management logic. This allows all eligible elements to perform the corresponding animations.
+
+
+
+### Summary
+
+
+
+Through the above steps, we have detailed the implementation principles of data update animations in VChart. The data update animation system of VChart cleverly combines the factory pattern, state manager pattern, and modular animation configuration, providing not only a rich set of built-in animation effects but also supporting highly customizable needs. Developers can flexibly configure and combine different animations according to actual application scenarios to create visual effects that are both beautiful and practical. Specifically:
+
+
+
+* `**animationEnter**`: Suitable for entry animations of new data points, such as fade-in, growth, etc.
+
+* `**animationUpdate**`: Suitable for update animations of existing data points, such as scaling, color gradient, etc.
+
+* `**animationExit**`: Suitable for exit animations of old data points, such as fade-out, shrink, etc.
+
+
+
+This design ensures that when data changes, the chart can be presented to users in a smooth and intuitive manner, enhancing the interactive experience and visual appeal.
+
+ # This document was revised and organized by the following personnel
+ [Xuanhun](https://github.com/xuanhun)
\ No newline at end of file
diff --git a/docs/assets/contributing/en/sourcecode/10.5-animation-orchestration.md b/docs/assets/contributing/en/sourcecode/10.5-animation-orchestration.md
new file mode 100644
index 0000000000..05da0b67b5
--- /dev/null
+++ b/docs/assets/contributing/en/sourcecode/10.5-animation-orchestration.md
@@ -0,0 +1,2413 @@
+---
+title: 10.5 Animation Arrangement
+
+key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM
+---
+## 10.5 Animation Arrangement
+
+Score: 4
+
+1. Global Animation:
+
+1. Code Entry: `packages/vchart/src/animation/`
+
+1. Key Points Interpretation:
+
+1. Implementation of Animation Arrangement
+
+1. Other Reference Documents:
+
+https://www.visactor.io/vchart/guide/tutorial_docs/Animation/Animation_Types
+
+https://www.visactor.io/vrender/guide/asd/Basic_Tutorial/Animate
+
+https://visactor.io/vgrammar/guide/guides/animation
+
+[Magic Frame (Part 1): The Principle of Front-end Chart Library Animation Implementation A vivid visualization work often involves animation. Whether it's various charts or narrative works, organizing the week - Juejin](https://juejin.cn/post/7275270809777520651)
+
+The animation arrangement in VChart's source code mainly revolves around generating and configuring animations to achieve animation effects in different states. Below, we interpret its implementation from several key functions and type definitions:
+
+1. Type Definitions and Constants
+
+utils.ts
+
+Apply
+
+* // Import various types and constants
+import type { IAnimationConfig } from '@visactor/vgrammar-core';
+// ... other imports ...
+/**
+Define an array of animation states, including all keys in the default animation configuration and 'normal'
+ */
+export const AnimationStates = [...Object.keys(DEFAULT_ANIMATION_CONFIG), 'normal'];
+
+* Type Imports: Various types are imported from different modules, such as `IAnimationConfig`, `IElement`, etc., which are used to define animation configurations, elements, etc., ensuring type safety in the code.
+
+* `AnimationStates` Constant: Contains all possible animation states, including states in the default animation configuration and the 'normal' state, used for subsequent traversal and processing of animation configurations in different states.
+
+1. Generate Animation Configuration
+
+utils.ts
+
+
+```xml
+export function animationConfig(
+ defaultConfig: MarkAnimationSpec = {},
+ userConfig?: Partial<
+ Record | IAnimationConfig | IAnimationConfig[]>
+ >,
+ params?: {
+ dataIndex: (datum: any, params: any) => number;
+ dataCount: () => number;
+ }
+) {
+ // ... 函数实现 ...
+}
+
+```
+* Parameters:
+
+* `defaultConfig`: Default animation configuration.
+
+* `userConfig`: User-defined animation configuration, possibly for partial states.
+
+* `params`: Parameters containing data index and data count functions.
+
+* Implementation logic:
+
+1. Create an empty object `config` to store the final animation configuration.
+
+1. Iterate over the `AnimationStates` array to process the configuration of each animation state.
+
+1. Merge or override the animation configuration of the corresponding state based on user configuration and default configuration.
+
+1. For the `exit` state, set the control option `stopWhenStateChange: true`.
+
+1. Handle the `oneByOne` option in the user configuration to generate an animation configuration that executes one by one.
+
+1. Return the final animation configuration.
+
+1. Generate user animation configuration
+
+utils.ts
+
+```xml
+export function userAnimationConfig(
+ markName: SeriesMarkNameEnum | string,
+ spec: IAnimationSpec,
+ ctx: IModelMarkAttributeContext
+) {
+ // ... 函数实现 ...
+}
+
+```
+* Parameters:
+
+* `markName`: Mark name.
+
+* `spec`: Animation specification.
+
+* `ctx`: Model mark attribute context.
+
+* Implementation logic:
+
+1. Create an empty object `userConfig` to store user animation configurations.
+
+1. Assign the corresponding configuration to `userConfig` based on different animation configurations in `spec` (such as `animationAppear`, `animationDisappear`, etc.).
+
+1. Call the `uniformAnimationConfig` function to unify animation configurations.
+
+1. Return the generated user animation configuration.
+
+1. Execute animation configurations one by one
+
+utils.ts
+
+```xml
+function produceOneByOne(
+ stateConfig: IAnimationTypeConfig,
+ dataIndex: (datum: any, params: any) => number,
+ dataCount?: () => number
+) {
+ // ... 函数实现 ...
+}
+
+```
+* Parameters:
+
+* `stateConfig`: Configuration object for the animation type.
+
+* `dataIndex`: Function that returns the index of the data item in the animation sequence.
+
+* `dataCount`: Optional function that returns the total number of data items.
+
+* Implementation logic:
+
+1. Destructure `oneByOne`, `duration`, `delay`, and `delayAfter` configurations from `stateConfig`.
+
+1. Configure the delay time `delay` before the element appears, calculate the delay time based on the data item index and animation parameters.
+
+1. Configure the delay time `delayAfter` after the element appears, also calculate the delay time based on the data item index and animation parameters.
+
+1. Remove the no longer needed `oneByOne` parameter.
+
+1. Return the updated animation configuration object.
+
+1. Other auxiliary functions
+
+* `defaultDataIndex`: Get the default data index based on the data item or animation parameters.
+
+* `shouldMarkDoMorph`: Determine whether the specified mark should perform morphing animation.
+
+* `isTimeLineAnimation` and `isChannelAnimation`: Determine whether the animation configuration is a timeline animation or a channel animation.
+
+* `uniformAnimationConfig`: Unify the animation configuration, process and convert functions in the configuration.
+
+* `traverseSpec`: Traverse and transform the given object or array, applying the provided transformation function.
+
+* `isAnimationEnabledForSeries`: Determine whether the series has animation enabled, check based on series specifications, area animation properties, and data volume.
+
+### Summary
+
+The animation orchestration implementation of VChart mainly merges and processes default configurations and user configurations through a series of functions and type definitions to generate the final animation configuration. At the same time, it provides functions such as executing animations one by one, morphing animations, and logic to determine whether animations are enabled, ensuring flexibility and configurability of animations in different scenarios.
+
+
+
+### Interpretation of Animation Orchestration Implementation
+
+
+
+Animation orchestration refers to combining multiple animation tasks in a certain order or condition to form a coherent and complex animation sequence. In VChart, the design of animation orchestration allows developers to create multi-stage, multi-element collaborative animation effects, thereby enhancing the visual expressiveness and user experience of the chart. The following is a detailed interpretation of the implementation.
+
+
+
+#### 1. Concept of Animation Orchestration
+
+
+
+**Animation Orchestration** is to enhance the effect of data visualization through carefully designed animation sequences. It is not just simple animation stacking, but also considers the coordination between animations, timeline management, and state transitions. VChart provides flexible tools to achieve animation orchestration, including but not limited to:
+
+
+
+* **Chained Animation**: Multiple animations are executed sequentially.
+
+* **Parallel Animation**: Multiple animations are executed simultaneously.
+
+* **Conditional Trigger**: Certain animations are triggered based on specific conditions.
+
+* **Event Driven**: Animations are triggered based on user interactions or other events.
+
+
+
+#### 2. Animation Configuration Structure
+
+
+
+**IAnimationSpec Interface**
+
+
+
+The `IAnimationSpec` interface defines the basic structure of animation configuration, which includes animation settings for different states. For animation orchestration, it mainly involves the following properties:
+
+
+
+* `animationState`: Used to describe state transition animations, can be used to build complex animation sequences.
+
+* `animationNormal`: Used to describe persistent loop animations, can be used as background animations in animation orchestration.
+
+
+
+
+```xml
+interface IAnimationSpec {
+ animationState?: boolean | IStateAnimationConfig;
+ animationNormal?: IMarkAnimateSpec;
+}
+
+```
+
+
+Each attribute can accept a boolean value (enable/disable), a preset configuration object, or a custom configuration object as a parameter, providing developers with a high degree of customization possibilities.
+
+
+
+#### 3. Animation Task Interface
+
+
+
+**IAnimationTask Interface**
+
+
+
+To support complex animation orchestration, VChart introduces the `IAnimationTask` interface to describe the data structure of animation tasks. Each task includes a time offset, an action queue, and a list of successor tasks, forming a chain-like animation execution mechanism.
+
+
+
+
+```xml
+interface IAnimationTask {
+ timeOffset: number; // 时间偏移量,表示该任务相对于前一个任务的延迟时间
+ actionList: Action[]; // 动作队列,包含一系列动画操作
+ nextTaskList: IAnimationTask[]; // 后继任务列表,表示后续要执行的任务
+}
+
+```
+
+
+This design allows multiple animation tasks to be executed sequentially or concurrently, achieving more complex and delicate animation effects.
+
+
+
+#### 4. Specific Implementation of Animation Orchestration
+
+
+
+Taking the creation of a bar chart with animation orchestration as an example, suppose we want to achieve the following effects:
+
+* When the page loads, all bars grow from the bottom up;
+
+* After the bars finish growing, a pulse effect is added to the top to attract the user's attention;
+
+* If new data is added, new bars fade in, and existing bars slightly scale to indicate changes.
+
+
+
+##### Step 1: Define Animation Configuration
+
+
+
+First, specify `animationAppear`, `animationEnter`, `animationUpdate`, etc., in the chart configuration for the bar chart series. Here we can choose built-in animation types and adjust their duration and easing functions.
+
+
+
+
+```xml
+const chartSpec = {
+ series: [
+ {
+ type: 'bar',
+ data: [/* 初始数据数组 */],
+ animationAppear: {
+ type: 'growCenterIn', // 柱子从中心向外生长
+ duration: 1000,
+ easing: 'easeInOutQuad'
+ },
+ animationNormal: {
+ type: 'pulse', // 生长完成后顶部添加脉冲效果
+ duration: 800,
+ easing: 'easeInOutQuad'
+ },
+ animationEnter: {
+ type: 'fadeIn', // 新数据点淡入
+ duration: 800,
+ easing: 'easeInOutQuad'
+ },
+ animationUpdate: {
+ type: 'scaleIn', // 更新数据点缩放
+ duration: 500,
+ easing: 'easeInOutQuad'
+ }
+ }
+ ]
+};
+
+```
+
+
+##### Step 2: Register Animation
+
+
+
+Ensure that the required animations have been correctly registered in the system. This step is usually completed at project startup or explicitly called where needed.
+
+
+
+
+```xml
+import { Factory } from '@visactor/vchart';
+import { Appear_Grow, pulseAnimation, Appear_FadeIn, ScaleInOutAnimation } from './series/bar/animation';
+
+// 注册柱子生长动画
+Factory.registerAnimation('growCenterIn', Appear_Grow);
+
+// 注册脉冲动画
+Factory.registerAnimation('pulse', pulseAnimation);
+
+// 注册淡入动画
+Factory.registerAnimation('fadeIn', Appear_FadeIn);
+
+// 注册缩放动画
+Factory.registerAnimation('scaleIn', ScaleInOutAnimation);
+
+```
+
+
+##### Step 3: Initialize the Chart Instance
+
+
+
+With the above configuration, we can initialize a `VChart` instance and pass the configuration to it. This will trigger the chart rendering process and apply the corresponding animation effects.
+
+
+
+
+```xml
+import { VChart } from '@visactor/vchart';
+
+const container = document.getElementById('chart-container');
+const chart = new VChart({
+ el: container,
+ spec: chartSpec,
+ options: {
+ animation: true, // 开启动画
+ theme: 'light' // 使用浅色主题
+ }
+});
+
+```
+
+
+##### Step 4: Build Animation Choreography
+
+
+
+To achieve animation choreography, we need to construct a task chain that includes multiple animation tasks. Each task can be a single animation or a composite animation (i.e., containing multiple subtasks). Here are the specific implementation steps:
+
+
+
+* **Define Animation Tasks**: First, define each individual animation task, including their time offsets, action queues, and successor task lists.
+
+
+
+
+```xml
+const appearTask: IAnimationTask = {
+ timeOffset: 0,
+ actionList: [{ type: 'growCenterIn', duration: 1000 }],
+ nextTaskList: [normalTask]
+};
+
+const normalTask: IAnimationTask = {
+ timeOffset: 0,
+ actionList: [{ type: 'pulse', duration: 800, loop: true }],
+ nextTaskList: []
+};
+
+const enterTask: IAnimationTask = {
+ timeOffset: 0,
+ actionList: [{ type: 'fadeIn', duration: 800 }],
+ nextTaskList: []
+};
+
+const updateTask: IAnimationTask = {
+ timeOffset: 0,
+ actionList: [{ type: 'scaleIn', duration: 500 }],
+ nextTaskList: []
+};
+
+```
+
+
+* **Composite Animation Tasks**: Next, combine these tasks into a complete animation choreography. For example, we can create a task chain that includes entrance animations and animations in the normal state.
+
+
+
+
+```xml
+const animationArrangement: IAnimationTask = {
+ timeOffset: 0,
+ actionList: [],
+ nextTaskList: [appearTask, normalTask]
+};
+
+```
+
+
+##### Step 5: Trigger Data Update Animation
+
+
+
+Once the chart is rendered, any changes in the data will automatically trigger animations. For example, when new data is added, the `enter` task will be triggered; when data is updated, the `update` task takes effect; and when data is removed, the `exit` task comes into play.
+
+
+
+
+```xml
+// 模拟数据更新
+setTimeout(() => {
+ const updatedData = [
+ { value: 15 }, // 更新第一个数据点
+ { value: 25 }, // 更新第二个数据点
+ { value: 35 }, // 更新第三个数据点
+ { value: 45 } // 添加一个新的数据点
+ ];
+
+ // 更新图表数据并触发动画
+ chart.updateSeriesData(updatedData);
+}, 5000);
+
+```
+
+
+In this example, the `updateSeriesData` method triggers a series of animations:
+
+* For newly added data points (the fourth data point), the `enter` task will make it gradually appear with a fade-in effect.
+
+* For existing data points (the first three data points), the `update` task will adjust their size based on the new data values and transition with a scaling effect.
+
+
+
+##### Step 6: Dynamically Control Animation Orchestration
+
+
+
+In some cases, you may want to dynamically control the behavior of animation orchestration, such as changing the speed or style of the animation. VChart provides flexible methods to achieve this.
+
+
+
+
+```xml
+// 更新某个系列的动画编排配置
+chart.updateSeriesOptions(0, {
+ animationAppear: {
+ type: 'growCenterIn',
+ duration: 1200, // 更改持续时间
+ easing: 'linear' // 更改缓动函数
+ },
+ animationNormal: {
+ type: 'pulse',
+ duration: 1000, // 更改持续时间
+ easing: 'easeInOutCubic' // 更改缓动函数
+ }
+});
+
+// 重新应用新的动画配置
+chart.render();
+
+```
+
+
+#### 5. Internal Implementation of Animation Orchestration
+
+
+
+**AnimateManager Class**
+
+
+
+The `AnimateManager` class is responsible for managing and coordinating the state of all animations. It implements the `IAnimate` interface and provides methods to update and retrieve animation states. For animation orchestration, `AnimateManager` ensures that these animation tasks are executed in a predetermined order or condition.
+
+
+
+
+```xml
+class AnimateManager extends StateManager implements IAnimate {
+ updateAnimateState(state: AnimationStateEnum, noRender?: boolean) {
+ if (state === AnimationStateEnum.appear) {
+ this.updateState(
+ {
+ animationState: {
+ callback: (datum: any, element: IElement) => state
+ }
+ },
+ noRender
+ );
+ } else if (state === AnimationStateEnum.normal) {
+ this.updateState(
+ {
+ animationState: {
+ callback: (datum: any, element: IElement) => state
+ }
+ },
+ noRender
+ );
+ }
+ }
+
+ // 动画编排逻辑
+ arrangeAnimations(tasks: IAnimationTask[]) {
+ tasks.forEach(task => {
+ // 执行当前任务的动作队列
+ task.actionList.forEach(action => {
+ this.executeAction(action);
+ });
+
+ // 如果存在后继任务,则递归执行
+ if (task.nextTaskList && task.nextTaskList.length > 0) {
+ setTimeout(() => {
+ this.arrangeAnimations(task.nextTaskList);
+ }, task.timeOffset);
+ }
+ });
+ }
+
+ private executeAction(action: Action) {
+ // 根据action.type获取对应的动画配置
+ const animationConfig = Factory.getAnimationInKey(action.type);
+
+ // 应用动画配置到目标元素
+ this.applyAnimation(animationConfig, action.duration, action.easing);
+ }
+
+ private applyAnimation(config: MarkAnimationSpec, duration: number, easing: string) {
+ // 实际应用动画的逻辑
+ }
+}
+
+```
+
+
+This code demonstrates how to execute a set of animation tasks using the `arrangeAnimations` method. The action queue in each task will be executed one by one, and then subsequent tasks will be recursively processed according to the `timeOffset` attribute. This allows for the construction of an ordered animation sequence, achieving complex animation orchestration effects.
+
+
+
+#### 6. Advanced Features of Animation Orchestration
+
+
+
+**Conditional Triggering and Event Listening**
+
+
+
+To increase the flexibility of animation orchestration, VChart also provides conditional triggering and event listening features. For example, animations can be triggered by listening to user interaction events (such as clicks, hovers), or dynamically adjust animation behavior based on specific conditions (such as data thresholds).
+
+
+
+
+```xml
+// 监听用户交互事件
+chart.on('element:click', (event) => {
+ const element = event.detail.element;
+ if (element) {
+ // 根据点击事件触发动画
+ this.triggerCustomAnimation(element);
+ }
+});
+
+// 条件触发动画
+if (someCondition) {
+ // 触发特定条件下的动画
+ this.triggerConditionalAnimation();
+}
+
+```
+
+
+**Parallel Animation**
+
+
+
+Sometimes, we want multiple animations to occur simultaneously rather than waiting for each to finish in sequence. VChart supports parallel animations, allowing developers to define multiple animation tasks to start executing at the same time.
+
+
+
+
+```xml
+const parallelTasks: IAnimationTask[] = [
+ {
+ timeOffset: 0,
+ actionList: [{ type: 'growCenterIn', duration: 1000 }],
+ nextTaskList: []
+ },
+ {
+ timeOffset: 0,
+ actionList: [{ type: 'pulse', duration: 800, loop: true }],
+ nextTaskList: []
+ }
+];
+
+this.arrangeAnimations(parallelTasks);
+
+```
+
+
+**Delay and Interval**
+
+
+
+By setting the `timeOffset` property, you can control the delay time between animation tasks. Additionally, you can use `setInterval` or `setTimeout` to achieve more complex timing logic.
+
+
+
+
+```xml
+// 设置延时
+const delayedTask: IAnimationTask = {
+ timeOffset: 500, // 延迟500毫秒后执行
+ actionList: [{ type: 'pulse', duration: 800, loop: true }],
+ nextTaskList: []
+};
+
+this.arrangeAnimations([delayedTask]);
+
+// 使用 setInterval 实现周期性动画
+setInterval(() => {
+ this.triggerPeriodicAnimation();
+}, 2000); // 每2秒触发一次
+
+```
+
+
+#### 7. Example: Creating a Bar Chart with Animation Orchestration
+
+
+
+Below is an example of creating a bar chart with animation orchestration, illustrating how to use VChart's animation orchestration system to achieve the basic process.
+
+### Example: Creating a Bar Chart with Animation Orchestration
+
+
+
+In VChart, animation orchestration refers to the combination and sequencing of multiple animation effects to achieve complex and coordinated visual effects. Through proper animation orchestration, the interactivity and user experience of the chart can be significantly enhanced. Below we will demonstrate in detail how to create a bar chart with animation orchestration, including the entrance animation for new data points, the update animation for existing data points, and the exit animation for old data points.
+
+
+
+#### 1. Define Animation Configuration
+
+
+
+First, we need to define the basic configuration of the bar chart and specify specific animation effects for each animation state (`enter`, `update`, `exit`). To achieve complex animation orchestration, we can use chained animation tasks to define the specific animation sequence for each state.
+
+
+
+
+```xml
+const chartSpec = {
+ series: [
+ {
+ type: 'bar',
+ data: [
+ { category: 'A', value: 10 },
+ { category: 'B', value: 20 },
+ { category: 'C', value: 30 }
+ ],
+ animationEnter: {
+ type: 'fadeIn',
+ duration: 800,
+ easing: 'easeInOutQuad',
+ nextTaskList: [
+ {
+ timeOffset: 800,
+ actionList: [
+ { type: 'growCenterIn', duration: 500, easing: 'easeInOutQuad' }
+ ],
+ nextTaskList: [
+ {
+ timeOffset: 500,
+ actionList: [
+ { type: 'pulse', duration: 300, easing: 'easeInOutQuad' }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ animationUpdate: {
+ type: 'scaleIn',
+ duration: 500,
+ easing: 'easeInOutQuad'
+ },
+ animationExit: {
+ type: 'fadeOut',
+ duration: 600,
+ easing: 'easeInOutQuad'
+ }
+ }
+ ]
+};
+
+```
+
+
+In this configuration:
+
+* `**animationEnter**`: New data points first fade in (`fadeIn`), then grow outward from the center (`growCenterIn`), and finally pulse slightly (`pulse`).
+
+* `**animationUpdate**`: Existing data points transition with scaling when updated.
+
+* `**animationExit**`: Old data points disappear by fading out.
+
+
+
+#### 2. Register Animation
+
+
+
+Next, we need to ensure that the required animations have been correctly registered in the system. This step is usually completed at project startup or explicitly called where needed.
+
+
+
+
+```xml
+import { Factory } from '@visactor/vchart';
+import { Appear_FadeIn, ScaleInOutAnimation, Appear_FadeOut, growCenterIn, pulseAnimation } from './series/bar/animation';
+
+// 注册淡入动画
+Factory.registerAnimation('fadeIn', Appear_FadeIn);
+
+// 注册缩放动画
+Factory.registerAnimation('scaleIn', ScaleInOutAnimation);
+
+// 注册淡出动画
+Factory.registerAnimation('fadeOut', Appear_FadeOut);
+
+// 注册中心生长动画
+Factory.registerAnimation('growCenterIn', growCenterIn);
+
+// 注册脉冲动画
+Factory.registerAnimation('pulse', pulseAnimation);
+
+```
+
+
+These animation functions define the specific logic for fade-in, zoom, fade-out, center growth, and pulse animations respectively. For example, the `Appear_FadeIn` function might look like this:
+
+
+
+```xml
+export const Appear_FadeIn: IAnimationTypeConfig = {
+ type: 'fadeIn',
+ duration: 800,
+ easing: 'easeInOutQuad',
+ channel: {
+ opacity: { from: 0, to: 1 }
+ }
+};
+
+export const growCenterIn: IAnimationTypeConfig = {
+ type: 'growCenterIn',
+ duration: 500,
+ easing: 'easeInOutQuad',
+ channel: {
+ width: { from: 0, to: '100%' },
+ height: { from: 0, to: '100%' }
+ }
+};
+
+export const pulseAnimation: IAnimationTypeConfig = {
+ type: 'pulse',
+ duration: 300,
+ easing: 'easeInOutQuad',
+ channel: {
+ scale: { from: 1, to: 1.1, toBack: 1 }
+ }
+};
+
+```
+
+
+#### 3. Initialize Chart Instance
+
+
+
+With the above configuration, we can initialize a `VChart` instance and pass the configuration to it. This will trigger the chart rendering process and apply the corresponding animation effects.
+
+
+
+
+```xml
+import { VChart } from '@visactor/vchart';
+
+const container = document.getElementById('chart-container');
+const chart = new VChart({
+ el: container,
+ spec: chartSpec,
+ options: {
+ animation: true, // 开启动画
+ theme: 'light' // 使用浅色主题
+ }
+});
+
+```
+
+
+#### 4. Trigger Animation
+
+
+
+Once the chart is rendered, any changes in the data will automatically trigger animations. For example, when new data is added, the `animationEnter` configuration will take effect; when data is updated, the `animationUpdate` configuration is effective; and when data is removed, the `animationExit` configuration comes into play.
+
+
+
+
+```xml
+// 模拟数据更新
+setTimeout(() => {
+ const updatedData = [
+ { category: 'A', value: 15 }, // 更新第一个数据点
+ { category: 'B', value: 25 }, // 更新第二个数据点
+ { category: 'C', value: 35 }, // 更新第三个数据点
+ { category: 'D', value: 45 } // 添加一个新的数据点
+ ];
+
+ // 更新图表数据并触发动画
+ chart.updateSeriesData(updatedData);
+}, 5000);
+
+```
+
+
+In this example, the `updateSeriesData` method will trigger a series of animations:
+
+* **New Data Points (D)**:
+
+1. Fade In (`fadeIn`): Gradually change from opacity 0 to 1.
+
+1. Grow Center In (`growCenterIn`): Grow outward from the center, with width and height changing from 0 to the final value.
+
+1. Pulse (`pulse`): Slightly enlarge and then return to the original state to attract the user's attention.
+
+* **Existing Data Points (A, B, C)**:
+
+* Scale In (`scaleIn`): Adjust the height of the columns according to the new data values for a smooth transition.
+
+
+
+#### 5. Detailed Implementation of Animation Orchestration
+
+
+
+**Chained Animation Tasks**
+
+
+
+To achieve complex animation orchestration, we can use the `IAnimationTask` interface to define a sequence of animation tasks for each state. Each task includes time offset, action queue, and a list of successor tasks, forming a chained animation execution mechanism.
+
+
+
+
+```xml
+interface IAnimationTask {
+ timeOffset: number;
+ actionList: Action[];
+ nextTaskList: IAnimationTask[];
+}
+
+```
+
+
+**Example: Defining a Chained Animation Task**
+
+
+
+Suppose we want to define a complex chained animation task for new data points in a bar chart, starting with a fade-in, followed by a center growth, and finally a slight pulse effect.
+
+
+
+
+```xml
+const enterAnimationTasks: IAnimationTask[] = [
+ {
+ timeOffset: 0,
+ actionList: [
+ { type: 'fadeIn', duration: 800, easing: 'easeInOutQuad' }
+ ],
+ nextTaskList: [
+ {
+ timeOffset: 800,
+ actionList: [
+ { type: 'growCenterIn', duration: 500, easing: 'easeInOutQuad' }
+ ],
+ nextTaskList: [
+ {
+ timeOffset: 500,
+ actionList: [
+ { type: 'pulse', duration: 300, easing: 'easeInOutQuad' }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+];
+
+```
+
+
+**Using Chained Animation Tasks in Chart Configuration**
+
+
+
+Integrate the defined chained animation tasks into the chart configuration to ensure that new data points execute animations in the expected order and effect.
+
+
+
+
+```xml
+const chartSpec = {
+ series: [
+ {
+ type: 'bar',
+ data: [
+ { category: 'A', value: 10 },
+ { category: 'B', value: 20 },
+ { category: 'C', value: 30 }
+ ],
+ animationEnter: enterAnimationTasks,
+ animationUpdate: {
+ type: 'scaleIn',
+ duration: 500,
+ easing: 'easeInOutQuad'
+ },
+ animationExit: {
+ type: 'fadeOut',
+ duration: 600,
+ easing: 'easeInOutQuad'
+ }
+ }
+ ]
+};
+
+```
+
+
+#### 6. Execution of Animation Tasks
+
+
+
+**Parsing and Execution of Animation Tasks**
+
+
+
+VChart internally parses the animation tasks in `animationEnter`, `animationUpdate`, and `animationExit`, and executes the corresponding animations according to the defined order and time offset. Below is a simplified example showing how to parse and execute chained animation tasks.
+
+
+
+
+```xml
+class AnimateManager extends StateManager implements IAnimate {
+ updateAnimateState(state: AnimationStateEnum, noRender?: boolean) {
+ if (state === AnimationStateEnum.update) {
+ this.updateState(
+ {
+ animationState: {
+ callback: (datum: any, element: IElement) => element.diffState
+ }
+ },
+ noRender
+ );
+ } else if (state === AnimationStateEnum.appear) {
+ // 处理新数据点的入场动画
+ this.handleAnimationTasks(element, element.animationConfig.enter);
+ } else if (state === AnimationStateEnum.exit) {
+ // 处理旧数据点的退场动画
+ this.handleAnimationTasks(element, element.animationConfig.exit);
+ }
+ }
+
+ private handleAnimationTasks(element: IElement, tasks: IAnimationTask[]) {
+ tasks.forEach(task => {
+ setTimeout(() => {
+ task.actionList.forEach(action => {
+ element.startAnimation(action.type, action.duration, action.easing);
+ });
+ if (task.nextTaskList) {
+ this.handleAnimationTasks(element, task.nextTaskList);
+ }
+ }, task.timeOffset);
+ });
+ }
+}
+
+```
+
+
+In this example, the `handleAnimationTasks` method recursively parses and executes each animation task, ensuring that the corresponding animations are triggered in the defined order and time offset.
+
+
+
+#### 7. Specific Implementation of Animations
+
+
+
+**Definition of Animation Functions**
+
+
+
+Each specific animation function (such as `Appear_FadeIn`, `ScaleInOutAnimation`, `Appear_FadeOut`, `growCenterIn`, and `pulseAnimation`) defines the specific behavior of the animation. Here are some examples of specific animation functions:
+
+
+
+
+```xml
+// 淡入动画
+export const Appear_FadeIn: IAnimationTypeConfig = {
+ type: 'fadeIn',
+ duration: 800,
+ easing: 'easeInOutQuad',
+ channel: {
+ opacity: { from: 0, to: 1 }
+ }
+};
+
+// 缩放动画
+export const ScaleInOutAnimation: IAnimationTypeConfig = {
+ type: 'scaleIn',
+ duration: 500,
+ easing: 'easeInOutQuad',
+ channel: {
+ scale: { from: 0.8, to: 1 }
+ }
+};
+
+// 淡出动画
+export const Appear_FadeOut: IAnimationTypeConfig = {
+ type: 'fadeOut',
+ duration: 600,
+ easing: 'easeInOutQuad',
+ channel: {
+ opacity: { from: 1, to: 0 }
+ }
+};
+
+// 中心生长动画
+export const growCenterIn: IAnimationTypeConfig = {
+ type: 'growCenterIn',
+ duration: 500,
+ easing: 'easeInOutQuad',
+ channel: {
+ width: { from: 0, to: '100%' },
+ height: { from: 0, to: '100%' }
+ }
+};
+
+// 脉冲动画
+export const pulseAnimation: IAnimationTypeConfig = {
+ type: 'pulse',
+ duration: 300,
+ easing: 'easeInOutQuad',
+ channel: {
+ scale: { from: 1, to: 1.1, toBack: 1 }
+ }
+};
+
+```
+
+
+**Registration of Animation Functions**
+
+
+
+Ensure that these animation functions have been correctly registered in the system so that they can be called when needed.
+
+
+
+
+```xml
+import { Factory } from '@visactor/vchart';
+import { Appear_FadeIn, ScaleInOutAnimation, Appear_FadeOut, growCenterIn, pulseAnimation } from './series/bar/animation';
+
+Factory.registerAnimation('fadeIn', Appear_FadeIn);
+Factory.registerAnimation('scaleIn', ScaleInOutAnimation);
+Factory.registerAnimation('fadeOut', Appear_FadeOut);
+Factory.registerAnimation('growCenterIn', growCenterIn);
+Factory.registerAnimation('pulse', pulseAnimation);
+
+```
+
+
+#### 8. Complete Example Code
+
+
+
+Below is a complete example code demonstrating how to create a bar chart with complex animation choreography.
+
+
+
+
+```xml
+// 导入必要的模块
+import { VChart } from '@visactor/vchart';
+import { Factory } from '@visactor/vchart';
+import { IElement, IAnimationTypeConfig } from '@visactor/vgrammar-core';
+
+// 定义动画函数
+export const Appear_FadeIn: IAnimationTypeConfig = {
+ type: 'fadeIn',
+ duration: 800,
+ easing: 'easeInOutQuad',
+ channel: {
+ opacity: { from: 0, to: 1 }
+ }
+};
+
+export const ScaleInOutAnimation: IAnimationTypeConfig = {
+ type: 'scaleIn',
+ duration: 500,
+ easing: 'easeInOutQuad',
+ channel: {
+ scale: { from: 0.8, to: 1 }
+ }
+};
+
+export const Appear_FadeOut: IAnimationTypeConfig = {
+ type: 'fadeOut',
+ duration: 600,
+ easing: 'easeInOutQuad',
+ channel: {
+ opacity: { from: 1, to: 0 }
+ }
+};
+
+export const growCenterIn: IAnimationTypeConfig = {
+ type: 'growCenterIn',
+ duration: 500,
+ easing: 'easeInOutQuad',
+ channel: {
+ width: { from: 0, to: '100%' },
+ height: { from: 0, to: '100%' }
+ }
+};
+
+export const pulseAnimation: IAnimationTypeConfig = {
+ type: 'pulse',
+ duration: 300,
+ easing: 'easeInOutQuad',
+ channel: {
+ scale: { from: 1, to: 1.1, toBack: 1 }
+ }
+};
+
+// 注册动画
+Factory.registerAnimation('fadeIn', Appear_FadeIn);
+Factory.registerAnimation('scaleIn', ScaleInOutAnimation);
+Factory.registerAnimation('fadeOut', Appear_FadeOut);
+Factory.registerAnimation('growCenterIn', growCenterIn);
+Factory.registerAnimation('pulse', pulseAnimation);
+
+// 定义链式动画任务
+const enterAnimationTasks: IAnimationTask[] = [
+ {
+ timeOffset: 0,
+ actionList: [
+ { type: 'fadeIn', duration: 800, easing: 'easeInOutQuad' }
+ ],
+ nextTaskList: [
+ {
+ timeOffset: 800,
+ actionList: [
+ { type: 'growCenterIn', duration: 500, easing: 'easeInOutQuad' }
+ ],
+ nextTaskList: [
+ {
+ timeOffset: 500,
+ actionList: [
+ { type: 'pulse', duration: 300, easing: 'easeInOutQuad' }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+];
+
+// 定义图表配置
+const chartSpec = {
+ series: [
+ {
+ type: 'bar',
+ data: [
+ { category: 'A', value: 10 },
+ { category: 'B', value: 20 },
+ { category: 'C', value: 30 }
+ ],
+ animationEnter: enterAnimationTasks,
+ animationUpdate: {
+ type: 'scaleIn',
+ duration: 500,
+ easing: 'easeInOutQuad'
+ },
+ animationExit: {
+ type: 'fadeOut',
+ duration: 600,
+ easing: 'easeInOutQuad'
+ }
+ }
+ ]
+};
+
+// 初始化图表实例
+const container = document.getElementById('chart-container');
+const chart = new VChart({
+ el: container,
+ spec: chartSpec,
+ options: {
+ animation: true, // 开启动画
+ theme: 'light' // 使用浅色主题
+ }
+});
+
+// 模拟数据更新
+setTimeout(() => {
+ const updatedData = [
+ { category: 'A', value: 15 }, // 更新第一个数据点
+ { category: 'B', value: 25 }, // 更新第二个数据点
+ { category: 'C', value: 35 }, // 更新第三个数据点
+ { category: 'D', value: 45 } // 添加一个新的数据点
+ ];
+
+ // 更新图表数据并触发动画
+ chart.updateSeriesData(updatedData);
+}, 5000);
+
+```
+
+
+#### 9. Advanced Usage of Animation Orchestration
+
+
+
+**Conditional Animation Configuration**
+
+
+
+**Conditional Animation Configuration** allows dynamically selecting different animation effects based on specific attributes of data points. For example, when a data value exceeds a certain threshold, a special animation is used; otherwise, the default animation is used. VChart allows you to embed logical judgments in the configuration to achieve such requirements.
+
+
+
+
+```xml
+const chartSpec = {
+ series: [
+ {
+ type: 'bar',
+ data: [
+ { category: 'A', value: 10 },
+ { category: 'B', value: 60 },
+ { category: 'C', value: 30 }
+ ],
+ animationEnter: (datum: any) => {
+ if (datum.value > 50) {
+ return {
+ type: 'specialGrowth', // 特殊的生长动画
+ duration: 1000,
+ easing: 'easeInOutQuad'
+ };
+ } else {
+ return {
+ type: 'fadeIn', // 默认的淡入动画
+ duration: 800,
+ easing: 'easeInOutQuad'
+ };
+ }
+ },
+ animationUpdate: {
+ type: 'scaleIn',
+ duration: 500,
+ easing: 'easeInOutQuad'
+ },
+ animationExit: {
+ type: 'fadeOut',
+ duration: 600,
+ easing: 'easeInOutQuad'
+ }
+ }
+ ]
+};
+
+```
+
+
+In this example, the `animationEnter` configuration accepts a function as a parameter, which can return different animation configuration objects based on the specific attributes of the data points. Specifically:
+
+* **Data point B has a value of 60**, which is greater than the threshold of 50, so the `specialGrowth` animation is used.
+
+* **Data points A and C have values of 10 and 30 respectively**, which are less than the threshold of 50, so the `fadeIn` animation is used.
+
+
+
+**Custom Animation Types**
+
+
+
+In addition to using built-in animation types, VChart also supports developers in customizing animation logic. You can create new animation effects by inheriting or extending existing animation classes and register them into the system.
+
+
+
+
+```xml
+// 定义一个新的动画类型
+function specialGrowthAnimation(params: any): IAnimationTypeConfig {
+ return {
+ type: 'specialGrowth',
+ duration: 1000,
+ easing: 'easeInOutQuad',
+ channel: {
+ width: { from: 0, to: params.width },
+ height: { from: 0, to: params.height },
+ opacity: { from: 0, to: 1 }
+ }
+ };
+}
+
+// 注册自定义动画
+Factory.registerAnimation('specialGrowth', specialGrowthAnimation);
+
+// 在图表配置中使用自定义动画
+const chartSpec = {
+ series: [
+ {
+ type: 'bar',
+ data: [
+ { category: 'A', value: 10 },
+ { category: 'B', value: 60 },
+ { category: 'C', value: 30 }
+ ],
+ animationEnter: (datum: any) => {
+ if (datum.value > 50) {
+ return {
+ type: 'specialGrowth',
+ duration: 1000,
+ easing: 'easeInOutQuad'
+ };
+ } else {
+ return {
+ type: 'fadeIn',
+ duration: 800,
+ easing: 'easeInOutQuad'
+ };
+ }
+ },
+ animationUpdate: {
+ type: 'scaleIn',
+ duration: 500,
+ easing: 'easeInOutQuad'
+ },
+ animationExit: {
+ type: 'fadeOut',
+ duration: 600,
+ easing: 'easeInOutQuad'
+ }
+ }
+ ]
+};
+
+```
+
+
+In this example, we define a custom animation named `specialGrowth` and register it into the system. Then, in the `animationEnter` configuration, we dynamically choose to use either the `specialGrowth` or `fadeIn` animation based on the value of the data point.
+
+
+
+#### 10. Advanced Usage of Animation Tasks
+
+
+
+**Nested Animation Tasks**
+
+
+
+In addition to simple chained animation tasks, VChart also supports nested animation tasks, making animation orchestration more flexible and complex. Through nested tasks, more precise animation control can be achieved.
+
+
+
+**Example: Nested Animation Tasks**
+
+
+
+Suppose we want to create a more complex animation sequence for newly added data points, starting with a fade-in, followed by a center growth, then a slight pulse effect, and finally a highlight.
+
+
+
+
+```xml
+const enterAnimationTasks: IAnimationTask[] = [
+ {
+ timeOffset: 0,
+ actionList: [
+ { type: 'fadeIn', duration: 800, easing: 'easeInOutQuad' }
+ ],
+ nextTaskList: [
+ {
+ timeOffset: 800,
+ actionList: [
+ { type: 'growCenterIn', duration: 500, easing: 'easeInOutQuad' }
+ ],
+ nextTaskList: [
+ {
+ timeOffset: 500,
+ actionList: [
+ { type: 'pulse', duration: 300, easing: 'easeInOutQuad' }
+ ],
+ nextTaskList: [
+ {
+ timeOffset: 300,
+ actionList: [
+ { type: 'highlight', duration: 500, easing: 'easeInOutQuad' }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+];
+
+```
+
+
+In this nested animation task:
+
+1. **Fade In (**`**fadeIn**`**)**: Gradually changes from opacity 0 to 1.
+
+1. **Grow Center In (**`**growCenterIn**`**)**: Grows outward from the center, with width and height changing from 0 to the final value.
+
+1. **Pulse (**`**pulse**`**)**: Slightly enlarges and then returns to its original state to attract the user's attention.
+
+1. **Highlight (**`**highlight**`**)**: Adds a highlight effect to the data point after the animation ends.
+
+
+
+**Define Highlight Animation**
+
+
+
+First, define and register the highlight animation.
+
+
+
+
+```xml
+export const highlightAnimation: IAnimationTypeConfig = {
+ type: 'highlight',
+ duration: 500,
+ easing: 'easeInOutQuad',
+ channel: {
+ fill: { from: 'blue', to: 'red', toBack: 'blue' }
+ }
+};
+
+// 注册高亮显示动画
+Factory.registerAnimation('highlight', highlightAnimation);
+
+```
+
+
+**Use Nested Animation Tasks in Chart Configuration**
+
+
+
+Integrate the defined nested animation tasks into the chart configuration.
+
+
+
+
+```xml
+const chartSpec = {
+ series: [
+ {
+ type: 'bar',
+ data: [
+ { category: 'A', value: 10 },
+ { category: 'B', value: 20 },
+ { category: 'C', value: 30 }
+ ],
+ animationEnter: enterAnimationTasks,
+ animationUpdate: {
+ type: 'scaleIn',
+ duration: 500,
+ easing: 'easeInOutQuad'
+ },
+ animationExit: {
+ type: 'fadeOut',
+ duration: 600,
+ easing: 'easeInOutQuad'
+ }
+ }
+ ]
+};
+
+```
+
+
+#### 11. Execution Mechanism of Animation Tasks
+
+
+
+**Parsing and Execution of Animation Tasks**
+
+
+
+VChart internally parses the animation tasks in `animationEnter`, `animationUpdate`, and `animationExit`, and executes the corresponding animations according to the defined order and time offset. Below is a simplified example showing how to parse and execute chained animation tasks.
+
+
+
+
+```xml
+class AnimateManager extends StateManager implements IAnimate {
+ updateAnimateState(state: AnimationStateEnum, noRender?: boolean) {
+ if (state === AnimationStateEnum.update) {
+ this.updateState(
+ {
+ animationState: {
+ callback: (datum: any, element: IElement) => element.diffState
+ }
+ },
+ noRender
+ );
+ } else if (state === AnimationStateEnum.appear) {
+ // 处理新数据点的入场动画
+ this.handleAnimationTasks(element, element.animationConfig.enter);
+ } else if (state === AnimationStateEnum.exit) {
+ // 处理旧数据点的退场动画
+ this.handleAnimationTasks(element, element.animationConfig.exit);
+ }
+ }
+
+ private handleAnimationTasks(element: IElement, tasks: IAnimationTask[]) {
+ tasks.forEach(task => {
+ setTimeout(() => {
+ task.actionList.forEach(action => {
+ element.startAnimation(action.type, action.duration, action.easing);
+ });
+ if (task.nextTaskList) {
+ this.handleAnimationTasks(element, task.nextTaskList);
+ }
+ }, task.timeOffset);
+ });
+ }
+}
+
+```
+
+
+In this example, the `handleAnimationTasks` method recursively parses and executes each animation task, ensuring that the corresponding animations are triggered in the defined order and time offset.
+
+
+
+**Timing of Animation Task Triggering**
+
+
+
+To ensure animations are triggered at the appropriate time, VChart provides a series of hook functions, such as `VGRAMMAR_HOOK_EVENT.AFTER_DO_RENDER` and `VGRAMMAR_HOOK_EVENT.ANIMATION_END`. These hooks can help us execute specific logic when the chart is first rendered or when the animation ends.
+
+
+
+
+```xml
+this._event.on(VGRAMMAR_HOOK_EVENT.AFTER_DO_RENDER, () => {
+ // 图表首次渲染完成后的逻辑
+ console.log('图表首次渲染完成');
+});
+
+this._event.on(VGRAMMAR_HOOK_EVENT.ANIMATION_END, ({ event }) => {
+ if (event.animationState === AnimationStateEnum.enter) {
+ // enter 动画结束后的逻辑
+ console.log('新数据点入场动画结束');
+ } else if (event.animationState === AnimationStateEnum.update) {
+ // update 动画结束后的逻辑
+ console.log('现有数据点更新动画结束');
+ } else if (event.animationState === AnimationStateEnum.exit) {
+ // exit 动画结束后的逻辑
+ console.log('旧数据点退场动画结束');
+ }
+});
+
+```
+
+
+#### 12. Best Practices for Animation Coordination
+
+
+
+**Batch Update Data**
+
+
+
+To improve performance, it is recommended to minimize frequent data update operations. If you need to update a large amount of data, consider merging these updates into a single batch operation to reduce unnecessary rendering times.
+
+
+
+
+```xml
+// 不推荐的做法:逐个更新数据点
+data.forEach((item, index) => {
+ setTimeout(() => {
+ chart.updateSeriesData([/* 更新后的数据 */]);
+ }, index * 100); // 每隔100毫秒更新一个数据点
+});
+
+// 推荐的做法:一次性批量更新所有数据
+setTimeout(() => {
+ const updatedData = data.map(item => /* 更新后的数据 */);
+ chart.updateSeriesData(updatedData);
+}, 1000); // 1秒后一次性更新所有数据
+
+```
+
+
+**Lazy Load Animation**
+
+
+
+For scenarios with large charts or a large number of data points, lazy loading can be used to delay loading animations until user interaction or specific conditions are met. This helps improve initial loading speed and overall performance.
+
+
+
+
+```xml
+// 懒加载动画配置
+const chartSpec = {
+ series: [
+ {
+ type: 'bar',
+ data: [/* 大量数据数组 */],
+ animationEnter: {
+ type: 'lazyFadeIn',
+ duration: 800,
+ easing: 'easeInOutQuad',
+ lazyLoad: true // 启用懒加载
+ }
+ }
+ ]
+};
+
+// 当用户滚动到视口内时触发懒加载动画
+window.addEventListener('scroll', () => {
+ if (isInViewPort(chartContainer)) {
+ chart.startLazyAnimations();
+ }
+});
+
+```
+
+
+**Cache Animation Results**
+
+
+
+For those animation effects with high computational cost, consider caching their results to avoid repeated calculations. For example, for complex path animations, you can pre-calculate the keyframes of the path and reuse these keyframes in subsequent rendering.
+
+
+
+
+```xml
+class PathAnimator {
+ private cachedFrames: KeyFrame[];
+
+ constructor(private pathData: PathData) {
+ this.cachedFrames = this.computeKeyFrames(pathData);
+ }
+
+ private computeKeyFrames(data: PathData): KeyFrame[] {
+ // 计算路径的关键帧并返回
+ }
+
+ public animate(element: IElement): void {
+ // 使用缓存的关键帧进行动画
+ this.applyCachedFrames(element);
+ }
+}
+
+```
+
+
+**Event Throttling and Debouncing**
+
+
+
+To avoid performance issues caused by frequent event triggering, you can apply throttling or debouncing techniques to event listeners. For example, when handling mouse hover events, you can limit the frequency of animation triggers.
+
+
+
+
+```xml
+import throttle from 'lodash/throttle';
+
+// 对鼠标悬停事件应用节流
+chart.on('element:hover', throttle((event) => {
+ // 触发悬停动画
+}, 200)); // 每200毫秒最多触发一次
+
+```
+
+
+**Dynamic Control of Animation**
+
+
+
+In some cases, you may want to dynamically control the behavior of animations, such as changing the speed or style of the animation. VChart provides flexible methods to achieve this.
+
+
+
+
+```xml
+// 更新某个系列的动画配置
+chart.updateSeriesOptions(0, {
+ animationEnter: {
+ duration: 1000, // 更改淡入动画的持续时间
+ easing: 'linear' // 更改缓动函数
+ },
+ animationUpdate: {
+ duration: 700, // 更改缩放动画的持续时间
+ easing: 'easeInOutCubic' // 更改缓动函数
+ },
+ animationExit: {
+ duration: 900, // 更改淡出动画的持续时间
+ easing: 'easeInOutCubic' // 更改缓动函数
+ }
+});
+
+// 重新应用新的动画配置
+chart.render();
+
+```
+
+
+#### 13. Complete Example Code
+
+
+
+Below is a complete example code demonstrating how to create a bar chart with complex animation choreography, implementing conditional animation configuration and custom animation types.
+
+
+
+
+```xml
+// 导入必要的模块
+import { VChart } from '@visactor/vchart';
+import { Factory } from '@visactor/vchart';
+import { IElement, IAnimationTypeConfig } from '@visactor/vgrammar-core';
+
+// 定义动画函数
+export const Appear_FadeIn: IAnimationTypeConfig = {
+ type: 'fadeIn',
+ duration: 800,
+ easing: 'easeInOutQuad',
+ channel: {
+ opacity: { from: 0, to: 1 }
+ }
+};
+
+export const ScaleInOutAnimation: IAnimationTypeConfig = {
+ type: 'scaleIn',
+ duration: 500,
+ easing: 'easeInOutQuad',
+ channel: {
+ scale: { from: 0.8, to: 1 }
+ }
+};
+
+export const Appear_FadeOut: IAnimationTypeConfig = {
+ type: 'fadeOut',
+ duration: 600,
+ easing: 'easeInOutQuad',
+ channel: {
+ opacity: { from: 1, to: 0 }
+ }
+};
+
+export const growCenterIn: IAnimationTypeConfig = {
+ type: 'growCenterIn',
+ duration: 500,
+ easing: 'easeInOutQuad',
+ channel: {
+ width: { from: 0, to: '100%' },
+ height: { from: 0, to: '100%' }
+ }
+};
+
+export const pulseAnimation: IAnimationTypeConfig = {
+ type: 'pulse',
+ duration: 300,
+ easing: 'easeInOutQuad',
+ channel: {
+ scale: { from: 1, to: 1.1, toBack: 1 }
+ }
+};
+
+export const highlightAnimation: IAnimationTypeConfig = {
+ type: 'highlight',
+ duration: 500,
+ easing: 'easeInOutQuad',
+ channel: {
+ fill: { from: 'blue', to: 'red', toBack: 'blue' }
+ }
+};
+
+// 注册动画
+Factory.registerAnimation('fadeIn', Appear_FadeIn);
+Factory.registerAnimation('scaleIn', ScaleInOutAnimation);
+Factory.registerAnimation('fadeOut', Appear_FadeOut);
+Factory.registerAnimation('growCenterIn', growCenterIn);
+Factory.registerAnimation('pulse', pulseAnimation);
+Factory.registerAnimation('highlight', highlightAnimation);
+
+// 定义链式动画任务
+const enterAnimationTasks: IAnimationTask[] = [
+ {
+ timeOffset: 0,
+ actionList: [
+ { type: 'fadeIn', duration: 800, easing: 'easeInOutQuad' }
+ ],
+ nextTaskList: [
+ {
+ timeOffset: 800,
+ actionList: [
+ { type: 'growCenterIn', duration: 500, easing: 'easeInOutQuad' }
+ ],
+ nextTaskList: [
+ {
+ timeOffset: 500,
+ actionList: [
+ { type: 'pulse', duration: 300, easing: 'easeInOutQuad' }
+ ],
+ nextTaskList: [
+ {
+ timeOffset: 300,
+ actionList: [
+ { type: 'highlight', duration: 500, easing: 'easeInOutQuad' }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+];
+
+// 定义图表配置
+const chartSpec = {
+ series: [
+ {
+ type: 'bar',
+ data: [
+ { category: 'A', value: 10 },
+ { category: 'B', value: 20 },
+ { category: 'C', value: 30 }
+ ],
+ animationEnter: enterAnimationTasks,
+ animationUpdate: {
+ type: 'scaleIn',
+ duration: 500,
+ easing: 'easeInOutQuad'
+ },
+ animationExit: {
+ type: 'fadeOut',
+ duration: 600,
+ easing: 'easeInOutQuad'
+ }
+ }
+ ]
+};
+
+// 初始化图表实例
+const container = document.getElementById('chart-container');
+const chart = new VChart({
+ el: container,
+ spec: chartSpec,
+ options: {
+ animation: true, // 开启动画
+ theme: 'light' // 使用浅色主题
+ }
+});
+
+// 模拟数据更新
+setTimeout(() => {
+ const updatedData = [
+ { category: 'A', value: 15 }, // 更新第一个数据点
+ { category: 'B', value: 25 }, // 更新第二个数据点
+ { category: 'C', value: 35 }, // 更新第三个数据点
+ { category: 'D', value: 65
+
+```
+
+
+In this example, the `animationEnter` configuration accepts a function as a parameter, which can return different values based on the specific attributes of the data points.
+
+### Continuing to Interpret the Implementation of Data Update Animation
+
+
+
+In the previous section, we have detailed the basic concepts and implementation methods of data update animation in VChart. Next, we will delve into some more specific details, including how to handle complex animation sequences, advanced usage of animation configuration, and best practices for optimizing performance.
+
+
+
+#### 1. Handling Complex Animation Sequences
+
+
+
+**Chained Animation Tasks**
+
+
+
+For complex animation sequences, VChart introduces the `IAnimationTask` interface to describe the data structure of animation tasks. Each task includes a time offset, an action queue, and a list of successor tasks, forming a chained animation execution mechanism.
+
+
+
+
+```xml
+interface IAnimationTask {
+ timeOffset: number;
+ actionList: Action[];
+ nextTaskList: IAnimationTask[];
+}
+
+```
+
+
+This design allows multiple animation tasks to be executed sequentially or concurrently, achieving more complex and subtle animation effects. For example, in a bar chart, we can define a series of consecutive animation tasks, first letting the newly added data points fade in, then gradually grow to the final height, and finally add some decorative animations (such as highlighting).
+
+
+
+**Example: Creating Chained Animations**
+
+
+
+Suppose we want to create a chained entry animation for new data points in a bar chart, starting with a fade-in, followed by growth, and finally a slight pulse effect to attract the user's attention.
+
+
+
+
+```xml
+const enterAnimationTasks: IAnimationTask[] = [
+ {
+ timeOffset: 0,
+ actionList: [
+ { type: 'fadeIn', duration: 800, easing: 'easeInOutQuad' }
+ ],
+ nextTaskList: [
+ {
+ timeOffset: 800,
+ actionList: [
+ { type: 'growCenterIn', duration: 500, easing: 'easeInOutQuad' }
+ ],
+ nextTaskList: [
+ {
+ timeOffset: 500,
+ actionList: [
+ { type: 'pulse', duration: 300, easing: 'easeInOutQuad' }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+];
+
+```
+
+
+In this example, we use the `enterAnimationTasks` array to define a series of animation tasks, each with its own time offset, action queue, and list of successor tasks. In this way, very rich visual effects can be achieved.
+
+
+
+#### 2. Advanced Usage of Animation Configuration
+
+
+
+**Conditional Animation Configuration**
+
+
+
+Sometimes, you may want to dynamically choose different animation effects based on certain conditions. For example, when a data value exceeds a certain threshold, use a special animation; otherwise, use the default animation. VChart allows you to embed logical judgments in the configuration to achieve such requirements.
+
+
+
+
+```xml
+const chartSpec = {
+ series: [
+ {
+ type: 'bar',
+ data: [/* 数据数组 */],
+ animationEnter: (datum: any) => {
+ if (datum.value > 50) {
+ return {
+ type: 'specialGrowth', // 特殊的生长动画
+ duration: 1000,
+ easing: 'easeInOutQuad'
+ };
+ } else {
+ return {
+ type: 'fadeIn', // 默认的淡入动画
+ duration: 800,
+ easing: 'easeInOutQuad'
+ };
+ }
+ },
+ animationUpdate: {
+ type: 'scaleIn',
+ duration: 500,
+ easing: 'easeInOutQuad'
+ },
+ animationExit: {
+ type: 'fadeOut',
+ duration: 600,
+ easing: 'easeInOutQuad'
+ }
+ }
+ ]
+};
+
+```
+
+
+In this example, the `animationEnter` configuration accepts a function as a parameter, which can return different animation configuration objects based on the specific attributes of the data points. This allows the animation behavior to be dynamically adjusted according to the actual data, enhancing the expressiveness of the chart.
+
+
+
+**Custom Animation Types**
+
+
+
+In addition to using built-in animation types, VChart also supports developers in customizing animation logic. You can create new animation effects by inheriting or extending existing animation classes and registering them into the system.
+
+
+
+```xml
+import { Factory } from '@visactor/vchart';
+import { IElement, IAnimationTypeConfig } from '@visactor/vgrammar-core';
+
+// 定义一个新的动画类型
+function customGrowAnimation(params: any): IAnimationTypeConfig {
+ return {
+ type: 'customGrow',
+ duration: 1000,
+ easing: 'easeInOutQuad',
+ channel: {
+ width: { from: 0, to: params.width },
+ height: { from: 0, to: params.height }
+ }
+ };
+}
+
+// 注册自定义动画
+Factory.registerAnimation('customGrow', customGrowAnimation);
+
+// 在图表配置中使用自定义动画
+const chartSpec = {
+ series: [
+ {
+ type: 'bar',
+ data: [/* 数据数组 */],
+ animationEnter: {
+ type: 'customGrow',
+ width: 50,
+ height: 100
+ }
+ }
+ ]
+};
+
+```
+
+
+This code demonstrates how to define and register a custom animation named `customGrow`, which adjusts the width and height of graphic elements based on the parameters passed. Then, this custom animation can be directly used in the chart configuration.
+
+
+
+#### 3. Performance Optimization and Best Practices
+
+
+
+**Batch Update Data**
+
+
+
+To improve performance, it is recommended to minimize frequent data update operations. If you need to update a large amount of data, consider merging these updates into a single batch operation to reduce unnecessary rendering times.
+
+
+
+
+```xml
+// 不推荐的做法:逐个更新数据点
+data.forEach((item, index) => {
+ setTimeout(() => {
+ chart.updateSeriesData([/* 更新后的数据 */]);
+ }, index * 100); // 每隔100毫秒更新一个数据点
+});
+
+// 推荐的做法:一次性批量更新所有数据
+setTimeout(() => {
+ const updatedData = data.map(item => /* 更新后的数据 */);
+ chart.updateSeriesData(updatedData);
+}, 1000); // 1秒后一次性更新所有数据
+
+```
+
+
+**Lazy Load Animation**
+
+
+
+For scenarios with large charts or a large number of data points, lazy loading can be used to delay the animation until user interaction or specific conditions are met. This helps improve initial loading speed and overall performance.
+
+
+
+
+```xml
+// 懒加载动画配置
+const chartSpec = {
+ series: [
+ {
+ type: 'bar',
+ data: [/* 大量数据数组 */],
+ animationEnter: {
+ type: 'lazyFadeIn',
+ duration: 800,
+ easing: 'easeInOutQuad',
+ lazyLoad: true // 启用懒加载
+ }
+ }
+ ]
+};
+
+// 当用户滚动到视口内时触发懒加载动画
+window.addEventListener('scroll', () => {
+ if (isInViewPort(chartContainer)) {
+ chart.startLazyAnimations();
+ }
+});
+
+```
+
+
+**Cache Animation Results**
+
+
+
+For those animation effects with high computational cost, consider caching their results to avoid repeated calculations. For example, for complex path animations, you can pre-calculate the keyframes of the path and reuse these keyframes in subsequent renderings.
+
+
+
+
+```xml
+class PathAnimator {
+ private cachedFrames: KeyFrame[];
+
+ constructor(private pathData: PathData) {
+ this.cachedFrames = this.computeKeyFrames(pathData);
+ }
+
+ private computeKeyFrames(data: PathData): KeyFrame[] {
+ // 计算路径的关键帧并返回
+ }
+
+ public animate(element: IElement): void {
+ // 使用缓存的关键帧进行动画
+ this.applyCachedFrames(element);
+ }
+}
+
+```
+
+
+**Event Throttling and Debouncing**
+
+
+
+To avoid performance issues caused by frequent event triggering, you can apply throttling or debouncing techniques to event listeners. For example, when handling mouse hover events, you can limit the frequency of animation triggers.
+
+
+
+
+```xml
+import throttle from 'lodash/throttle';
+
+// 对鼠标悬停事件应用节流
+chart.on('element:hover', throttle((event) => {
+ // 触发悬停动画
+}, 200)); // 每200毫秒最多触发一次
+
+```
+
+
+#### 4. Case Study
+
+
+
+**Case: Dynamic Bar Chart**
+
+
+
+Suppose we are developing a dynamic bar chart that updates in real-time, with a new batch of data added to the chart every second. We need to ensure that each time the data is updated, the newly added data points are presented to the user in a smooth and engaging manner, while the existing data points remain stable.
+
+
+
+##### Step 1: Define Basic Configuration
+
+
+
+First, define the basic configuration of the bar chart, including initial data and other visual attributes. At the same time, specify `animationEnter`, `animationUpdate`, and `animationExit` configurations to ensure animations are triggered when data changes.
+
+
+
+
+```xml
+const chartSpec = {
+ series: [
+ {
+ type: 'bar',
+ data: [/* 初始数据数组 */],
+ animationEnter: {
+ type: 'fadeIn',
+ duration: 800,
+ easing: 'easeInOutQuad'
+ },
+ animationUpdate: {
+ type: 'scaleIn',
+ duration: 500,
+ easing: 'easeInOutQuad'
+ },
+ animationExit: {
+ type: 'fadeOut',
+ duration: 600,
+ easing: 'easeInOutQuad'
+ }
+ }
+ ]
+};
+
+```
+
+
+##### Step 2: Implement Data Update Logic
+
+
+
+Next, implement a timer that adds a batch of new data to the chart every second and triggers the corresponding animation.
+
+
+
+
+```xml
+setInterval(() => {
+ const newDataBatch = generateNewData(); // 生成新的数据批次
+ const updatedData = [...chart.getData(), ...newDataBatch];
+
+ // 更新图表数据并触发动画
+ chart.updateSeriesData(updatedData);
+}, 1000);
+
+```
+
+
+##### Step 3: Optimize Performance
+
+
+
+Considering that a new batch of data is added every second, it may impact performance. Therefore, we can take the following optimization measures:
+
+
+
+* **Batch update data**: Update all new data to the chart at once, instead of adding them one by one.
+
+* **Lazy load animations**: Enable lazy load animations for newly added data points, so that animations only start playing when they enter the viewport.
+
+* **Event throttling**: Apply throttling techniques to interaction events such as mouse hover to prevent unnecessary animations from being triggered frequently.
+
+
+
+
+```xml
+// 批量更新数据
+setTimeout(() => {
+ const updatedData = generateAllNewData(); // 生成所有新的数据
+ chart.updateSeriesData(updatedData);
+}, 1000);
+
+// 懒加载动画配置
+const chartSpec = {
+ series: [
+ {
+ type: 'bar',
+ data: [/* 数据数组 */],
+ animationEnter: {
+ type: 'lazyFadeIn',
+ duration: 800,
+ easing: 'easeInOutQuad',
+ lazyLoad: true
+ }
+ }
+ ]
+};
+
+// 对鼠标悬停事件应用节流
+chart.on('element:hover', throttle((event) => {
+ // 触发悬停动画
+}, 200));
+
+```
+
+
+##### Step 4: Enhance User Experience
+
+
+
+To make the charts more vivid and interesting, you can add additional decorative animations to the newly added data points, such as highlighting or tooltip labels. This not only enhances visual appeal but also helps users better understand the changes in the data.
+
+
+
+
+```xml
+// 添加高亮显示动画
+const chartSpec = {
+ series: [
+ {
+ type: 'bar',
+ data: [/* 数据数组 */],
+ animationEnter: {
+ type: 'fadeIn',
+ duration: 800,
+ easing: 'easeInOutQuad',
+ onEnd: (element: IElement) => {
+ element.addHighlight(); // 添加高亮效果
+ }
+ }
+ }
+ ]
+};
+
+// 添加标签提示动画
+chart.on('element:hover', (event) => {
+ const element = event.detail.element;
+ if (element) {
+ element.showTooltip(); // 显示标签提示
+ }
+});
+
+```
+
+
+#### 5. Dynamic Control of Animation
+
+
+
+**Dynamically Adjust Animation Parameters**
+
+
+
+In some cases, you may want to dynamically adjust animation parameters such as duration, easing functions, etc., based on user input or other external factors. VChart provides flexible methods to achieve this.
+
+
+
+
+```xml
+// 根据用户选择动态调整动画参数
+const updateAnimationParams = (seriesIndex: number, newParams: Partial) => {
+ chart.updateSeriesOptions(seriesIndex, {
+ animationEnter: {
+ ...chart.getSeriesOptions(seriesIndex).animationEnter,
+ ...newParams
+ }
+ });
+
+ // 重新应用新的动画配置
+ chart.render();
+};
+
+// 用户选择更快的动画速度
+updateAnimationParams(0, { duration: 500 });
+
+```
+
+
+**Pause and Resume Animation**
+
+
+
+ # This document was revised and organized by the following person
+ [玄魂](https://github.com/xuanhun)
\ No newline at end of file
diff --git a/docs/assets/contributing/en/sourcecode/11.1-theme-configuration-parsing-logic.md b/docs/assets/contributing/en/sourcecode/11.1-theme-configuration-parsing-logic.md
new file mode 100644
index 0000000000..55aacd1960
--- /dev/null
+++ b/docs/assets/contributing/en/sourcecode/11.1-theme-configuration-parsing-logic.md
@@ -0,0 +1,436 @@
+---
+title: 11.1 Theme Configuration Parsing Logic
+
+key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM
+---
+# VChart Theme Related Concepts
+
+The theme module of VChart is a powerful and flexible chart style configuration system. It allows users to customize the visual appearance of charts in a unified and reusable way. Users can easily define comprehensive style configurations for the entire chart or specific chart types, including colors, fonts, layouts, component styles, etc. By using predefined themes, users can quickly achieve a consistent design style without having to repeatedly configure styles for each chart, greatly simplifying the chart development process and ensuring visual consistency and professionalism across different scenarios. In simple terms, the theme of VChart is like a "design template" for charts, allowing users to quickly create beautiful and professional data visualization charts by simply selecting or customizing a theme.
+
+Theme concept related documents: [VisActor/VChart tutorial documents](https://www.visactor.io/vchart/guide/tutorial_docs/Theme/Theme_Concept_and_Design_Rules)
+
+## Theme Related Source Code Location and Content
+
+* package/vchart/scr/util/theme: A folder of utility classes related to themes, including tools for theme merging, parsing, preprocessing (color palettes, token semantics), and converting string themes to objects.
+
+* package/vchart/scr/core/vchart.ts: Defines the core class VChart, including a series of hooks throughout the chart lifecycle such as theme initialization, registration, updating, switching, and destruction. VChart is a specific chart instance responsible for application and rendering, closely related to theme configuration and updates.
+
+* package/vchart/src/theme: This folder contains special concepts related to themes: color palettes (color-theme), tokenMap, theme manager class (theme-manager), and other data structures.
+
+## Core Classes and Their Relationships
+
+* VChart: Responsible for specific rendering, instantiation, and lifecycle management of charts
+
+* ThemeManager: Responsible for global registration, management, and switching of themes
+
+`ThemeManager` is exposed as a static class of VChart, allowing users to manage themes using commands like
+
+`VChart.ThemeManager.registerTheme('myTheme', { ... });` or `VChart.ThemeManager.setCurrentTheme('myTheme');`
+
+```xml
+export class VChart implements IVChart {
+ static readonly ThemeManager = ThemeManager;
+}
+
+```
+However, essentially, `ThemeManager` is still an independent class, but it provides a more convenient way to access it through this method. This design pattern of exposing static properties achieves the decoupling of theme management and chart rendering.
+
+# **Theme Configuration Parsing Logic**
+
+VChart provides two ways to configure chart themes:
+
+* Through chart `spec` configuration
+
+* By registering themes through `ThemeManager`
+
+## **Theme Configuration Retrieval and Priority Comparison (core/vchart.ts)**
+
+
+
+Both configurations can be set up with a `ITheme` type theme object, but what is the priority of these two configurations? This priority issue is handled in the updateCurrentTheme method:
+
+
+
+ **Note**: Strictly speaking, there are three sources of themes:
+
+> * `currentTheme`: The global default theme registered through `ThemeManager`
+> * `optionTheme`: The theme passed in the options of the VChart constructor
+> * `specTheme`: The theme specified in the chart specification (spec)
+>
+> Their priority from low to high is:
+> * `currentTheme` < `optionTheme` < `specTheme`
+
+
+
+In `src/core/vchart.ts`, the following properties are used to obtain the theme content configured by the user:
+
+
+
+* `_spec.theme`: The theme specified by the user in the chart spec object configuration
+
+* `_currentThemeName`: The current global theme name registered through `VChart.ThemeManager.registerTheme`
+
+### **Brief Analysis of Theme Merging Logic (util/theme/merge-theme.ts)**
+
+#### **mergeTheme Function**
+
+```xml
+export function mergeTheme(target: Maybe, ...sources: Maybe[]): Maybe {
+ return mergeSpec(transformThemeToMerge(target), ...sources.map(transformThemeToMerge));
+}
+
+```
+* It is the basis for merging themes, a simple layer of encapsulation. Simply put, it is the overriding of object properties.
+
+* The result is that the later appearing `sources` will override the earlier appearing `theme`.
+
+**Example**
+
+```xml
+const baseTheme = { color: 'blue', fontSize: 12 };
+const optionTheme = { color: 'red' };
+const specTheme = { fontSize: 14 };
+
+const finalTheme = mergeTheme({}, baseTheme, optionTheme, specTheme);
+// 结果:{ color: 'red', fontSize: 14 }
+
+```
+#### transformThemeToMerge function
+
+
+```xml
+ function transformThemeToMerge(theme?: Maybe): Maybe {
+ if (!theme) {
+ return theme;
+ }
+ // 将色板转化为标准形式
+ const colorScheme = transformColorSchemeToMerge(theme.colorScheme);
+
+ return Object.assign({}, theme, {
+ colorScheme,
+ token: theme.token ?? {},
+ series: Object.assign({}, theme.series)
+ } as Partial);
+}
+
+/** 将色板转化为标准形式 */
+export function transformColorSchemeToMerge(colorScheme?: Maybe): Maybe {
+ if (colorScheme) {
+ colorScheme = Object.keys(colorScheme).reduce((scheme, key) => {
+ const value = colorScheme[key];
+ scheme[key] = transformColorSchemeToStandardStruct(value);
+ return scheme;
+ }, {} as IThemeColorScheme);
+ }
+ return colorScheme;
+}
+
+```
+`transformThemeToMerge` generally serves to standardize and normalize the theme object, addressing the following:
+
+* Colors are always in array form
+
+* Always have `token` and `series` attributes
+
+This ensures that regardless of the theme configuration provided by the user, it can be transformed into a structurally complete, consistent, and predictable theme object, providing a standardized data structure for subsequent theme merging and application.
+
+#### **processThemeByChartType Function**
+
+```xml
+const processThemeByChartType = (type: string, theme: ITheme) => {
+ if (theme.chart?.[type]) {
+ theme = mergeTheme({}, theme, theme.chart[type]);
+ }
+ return theme;
+};
+
+```
+`processThemeByChartType` is a key function in the VChart theme system that implements chart type personalization. It achieves the ability to provide customized styles for different chart types while maintaining global theme consistency through conditional merging and `mergeTheme`.
+
+### **Parsing and Processing of String Themes and Object Themes**
+
+When configuring themes, users can easily and conveniently pass in string themes (usually themes exported from third-party theme packages), for example:
+
+```xml
+import vScreenVolcanoBlue from '@visactor/vchart-theme/public/vScreenVolcanoBlue.json';
+import VChart from '@visactor/vchart';
+
+VChart.ThemeManager.registerTheme('vScreenVolcanoBlue', vScreenVolcanoBlue);
+
+VChart.ThemeManager.setCurrentTheme('vScreenVolcanoBlue');
+
+```
+You can also pass in a custom theme with detailed configuration, for example:
+
+```xml
+const chart = new VChart({
+ theme: {
+ color: { primary: 'red' },
+ fontSize: 14,
+ chart: {
+ bar: {
+ color: 'blue'
+ }
+ }
+ }
+});
+
+```
+The core of handling both in the source code is to determine the type in \_updateCurrentTheme and convert it through `getThemeObject()`, uniformly processing it into an object theme for parsing. This is a simple logic, yet it provides flexibility and convenience for VChart's configuration.
+
+Ultimately, after layers of priority comparison, merging of table types (`processThemeByChartType`), and theme merging processing logic, the `currentTheme` attribute mounted on the VChart object is finally obtained.
+
+## **Preprocessing of Theme Configuration**
+
+When the theme configuration is merged, it enters the preprocessing stage. Theme preprocessing is a key step in the VChart theme system, converting abstract theme descriptions into specific style configurations, providing developers with intuitive configuration capabilities.
+
+Mainly accomplishes the following tasks:
+
+1. Semantic color conversion
+
+* Convert color semantics like `{ color: 'brand.primary' }` into specific color values
+
+1. Token replacement
+
+* Convert token semantics like `{ fontSize: 'size.m' }` into specific font sizes
+
+1. Recursive processing of nested objects
+
+**Preprocessing Flow**:
+
+
+```xml
+this._currentTheme = preprocessTheme(processThemeByChartType(chartType, finalTheme));
+
+```
+## **Preprocessing and Parsing of Themes**
+
+```xml
+export function preprocessTheme(
+ obj: any, //主题对象
+ colorScheme?: IThemeColorScheme, // 颜色方案
+ tokenMap?: TokenMap, // 标记映射
+ seriesSpec?: ISeriesSpec // 系列规格
+);
+
+```
+这里涉及了 VChart 主题配置的重要概念:
+
+* `colorScheme`: Color scheme
+
+* `tokenMap`: Token mapping
+
+```xml
+VChart.ThemeManager.registerTheme('dataVizTheme', {
+ colorScheme: {
+ brand: { primary: '#3A8DFF' },
+ data: {
+ positive: '#48BB78',
+ negative: '#F56565'
+ }
+ },
+ tokenMap: {
+ typography: {
+ fontSize: {
+ small: 12,
+ medium: 14,
+ large: 16
+ }
+ }
+ }
+});
+
+```
+
+
+Developers can use the `registerTheme` method during registration to register a complex theme configuration based on these two concepts, as shown in the example above. In actual use, developers can reference these definitions through { color: 'data.positive' } or { fontSize: { token: 'typography.fontSize.medium' } }. Here, let's discuss how VChart parses this complex object.
+
+
+
+First, analyze layer by layer, the key algorithm of this processing function processTheme is to recursively traverse the object:
+
+```xml
+Object.keys(obj).forEach(key => {
+ const value = obj[key];
+ if (IGNORE_KEYS.includes(key)) {
+ newObj[key] = value;
+ }
+ // 处理颜色语义化转换、Token 语义化转换
+ else if (isPlainObject(value)) {
+ if (isColorKey(value)) {
+ newObj[key] = getActualColor(value, colorScheme, seriesSpec);
+ } else if (isTokenKey(value)) {
+ newObj[key] = queryToken(tokenMap, value);
+ }
+ // 这里使用了递归处理嵌套对象,使得能够处理任意深度的嵌套对象
+ else {
+ newObj[key] = preprocessTheme(value, colorScheme, tokenMap, seriesSpec);
+ }
+ }
+ // 非对象类型直接赋值
+ else {
+ newObj[key] = value;
+ }
+});
+
+```
+
+
+Next, analyze the specific handling and parsing of color semantics and token semantics
+
+#### **getActualColor Color Semantics**
+
+```xml
+/** 查询语义化颜色 */
+export const getActualColor = (value: any, colorScheme?: IThemeColorScheme, seriesSpec?: ISeriesSpec) => {
+ if (colorScheme && isColorKey(value)) {
+ const color = queryColorFromColorScheme(colorScheme, value, seriesSpec);
+ if (color) {
+ return color;
+ }
+ }
+ return value;
+};
+
+export function queryColorFromColorScheme(
+ colorScheme: IThemeColorScheme,
+ colorKey: IColorKey,
+ seriesSpec?: ISeriesSpec
+): ColorSchemeItem | undefined {
+ const scheme = getColorSchemeBySeries(colorScheme, seriesSpec);
+ if (!scheme) {
+ return undefined;
+ }
+ let color;
+ const { palette } = scheme as IColorSchemeStruct;
+ if (isObject(palette)) {
+ color = getUpgradedTokenValue(palette, colorKey.key) ?? colorKey.default;
+ }
+ if (!color) {
+ return undefined;
+ }
+ if ((isNil(colorKey.a) && isNil(colorKey.l)) || !isString(color)) {
+ return color;
+ }
+ let c = new Color(color);
+ if (isValid(colorKey.l)) {
+ const { r, g, b } = c.color;
+ const { h, s } = rgbToHsl(r, g, b);
+ const rgb = hslToRgb(h, s, colorKey.l);
+ const newColor = new Color(`rgb(${rgb.r}, ${rgb.g}, ${rgb.b})`);
+ newColor.setOpacity(c.color.opacity);
+ c = newColor;
+ }
+ if (isValid(colorKey.a)) {
+ c.setOpacity(colorKey.a);
+ }
+ return c.toRGBA();
+}
+
+```
+
+
+queryColorFromColorScheme is the core function for color processing in the VChart theme system. It receives a color scheme (colorScheme), a color key (colorKey), and an optional series specification (seriesSpec). Through a series of complex color lookup and conversion algorithms, it achieves precise localization and dynamic enhancement of semantic colors.
+
+
+
+The core logic of the function is: first, obtain a specific color scheme based on the series specification, and then look up the corresponding color from the palette.
+
+
+```xml
+export function getColorSchemeBySeries(
+ colorScheme?: IThemeColorScheme,
+ seriesSpec?: ISeriesSpec
+): ColorScheme | undefined {
+ const { type: seriesType } = seriesSpec ?? {};
+ let scheme: ColorScheme | undefined;
+ if (!seriesSpec || isNil(seriesType)) {
+ scheme = colorScheme?.default;
+ } else {
+ const direction = getDirectionFromSeriesSpec(seriesSpec);
+ scheme = colorScheme?.[`${seriesType}_${direction}`] ?? colorScheme?.[seriesType] ?? colorScheme?.default;
+ }
+ return scheme;
+}
+
+```
+This algorithm prioritizes matching the color scheme of a specific `seriesType_direction`, then matches the general `seriesType` color scheme, and finally matches the default color scheme.
+
+It is worth mentioning that this function also provides two advanced color processing capabilities, dynamically handling color characteristics based on the `l` or `a` attributes in `colorKey`:
+
+1. **Dynamic adjustment of color brightness through HSL color space conversion**
+
+ **Algorithm Principle**
+
+ Color space conversion: RGB → HSL → RGB
+
+ **Core code for HSL brightness adjustment**
+
+```xml
+ if (isValid(colorKey.l)) {
+ const { r, g, b } = c.color;
+ const { h, s } = rgbToHsl(r, g, b);
+ const rgb = hslToRgb(h, s, colorKey.l);
+ const newColor = new Color(rgb(${rgb.r}, ${rgb.g}, ${rgb.b}));
+ newColor.setOpacity(c.color.opacity);
+ c = newColor;
+ }
+
+```
+Simply put, it is to adjust the brightness level (L) of the color while maintaining the original hue (H) and saturation (S). The conversion algorithm between hsl and rgb formats is not the focus of the topic analysis, so it is briefly mentioned:
+
+
RGB to HSL algorithm:
+1. Normalize RGB values to [0,1]
+1. Find the maximum and minimum values among R, G, B
+1. Calculate brightness L = (max + min) / 2
+1. Calculate saturation S
+1. Calculate hue H
+HSL to RGB algorithm:
+1. Divide H into 6 intervals
+1. Calculate intermediate variables based on S and L
+1. Calculate R, G, B values using different formulas
+1. Map the results to [0,255]
+
+* If max == min, S = 0
+
+* Otherwise S = (max - min) / (1 - |2L - 1|)
+
+* Use different formulas based on which color component is the largest
+
+* Range 0-360 degrees
+
+2. **Set the transparency of the color**
+
+ **Core code for transparency adjustment**
+
+```javascript
+if (isValid(colorKey.a)) {
+ c.setOpacity(colorKey.a);
+}
+
+```
+#### **queryToken Token Semantics**
+
+
+```xml
+export function queryToken(tokenMap: TokenMap, tokenKey: ITokenKey): T | undefined {
+ if (tokenMap && tokenKey.key in tokenMap) {
+ return tokenMap[tokenKey.key];
+ }
+ return tokenKey.default;
+}
+
+```
+This function is used to query the corresponding token value based on tokenMap and tokenKey. If the corresponding token exists in tokenMap, it returns the corresponding value; otherwise, it returns the default value.
+
+
+
+---
+# This document is provided by the following personnel
+
+Dundun (https://github.com/Shabi-x)
+
+
+
+ # This document is revised and organized by the following personnel
+ [Xuanhun](https://github.com/xuanhun)
\ No newline at end of file
diff --git a/docs/assets/contributing/en/sourcecode/11.2-theme-update-source-code-analysis.md b/docs/assets/contributing/en/sourcecode/11.2-theme-update-source-code-analysis.md
new file mode 100644
index 0000000000..1e7cfe2ed5
--- /dev/null
+++ b/docs/assets/contributing/en/sourcecode/11.2-theme-update-source-code-analysis.md
@@ -0,0 +1,300 @@
+---
+title: 11.2 Source Code Interpretation of Theme Updates
+
+key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM
+---
+# Basic Concepts of Theme Updates
+
+VChart theme switching is a common operation: for example, according to different seasons, holidays, or internationalization, personalized color schemes, and the common night mode. Users can manually or listen to the user's system to switch different styles of themes to adapt to different usage environments.
+
+## Theme Update Examples
+
+For example, registration and switching of night mode:
+
+```xml
+VChart.ThemeManager.registerTheme('darkTheme', { ... });
+VChart.ThemeManager.registerTheme('lightTheme', { ... });
+
+function toggleTheme(isDarkMode) {
+ const themeName = isDarkMode ? 'darkTheme' : 'lightTheme';
+ VChart.ThemeManager.setCurrentTheme(themeName);
+}
+
+```
+Style switching for different application scenarios:
+
+
+```xml
+// 不同风格的主题配置
+const themes = {
+ 'finance': { ... },
+ 'medical': { ... },
+ 'technology': { ... }
+};
+
+Object.keys(themes).forEach(key => {
+ VChart.ThemeManager.registerTheme(key + 'Theme', themes[key]);
+});
+
+function switchDashboardTheme(businessType) {
+ const themeName = businessType + 'Theme';
+ VChart.ThemeManager.setCurrentTheme(themeName);
+}
+
+```
+# Source Code Location and Content Related to Themes
+
+* package/vchart/scr/core/**vchart.ts**: The theme updater for a single chart instance, implementing the specific theme application logic, transforming the global theme into actual style changes for the chart. The main update logic of the chart is here.
+
+* package/vchart/src/core/instance-manager.ts: The central hub for chart instance registration and management, providing the infrastructure for traversing and locating theme instance updates, ensuring that each chart can receive theme updates.
+
+* package/vchart/src/theme/theme-manager.ts: The global theme scheduling center, responsible for theme registration, retrieval, and global updates, providing a unified theme management entry and coordination mechanism.
+
+
Through the methods defined in the `VChart` class, the core rendering and update logic of the chart is implemented. `ThemeManager` and `InstanceManager` are responsible for the global management of themes and instances, respectively, forming a decoupled, flexible, and extensible chart library architecture; `VChart` provides a unified update entry, implementing most of the update operation logic; while `ThemeManager` and `InstanceManager` achieve global theme updates through instance registration and traversal mechanisms.
+# In-depth Analysis of the Theme Update Process
+
+The VChart official website divides theme updates into two dimensions, namely
+
+* Updating the theme of **a single chart instance**
+
+* Updating the theme of **all charts globally** through `ThemeManager`.
+
+
+
+The specific approach can be viewed at [🎁 VisActor Data Visualization Competition](https://www.visactor.io/vchart/guide/tutorial_docs/Theme/Customize_Theme). Both methods use the same `setCurrentTheme` call to switch themes. The former is called by an instance generated by the VChart object, updating a single chart; the latter is called through `ThemeManager`, updating the global chart theme. Therefore, my approach to reading the source code is based on the declaration and definition of the `setCurrentTheme` method, delving deeper layer by layer.
+
+## Example:
+
+Updating a single instance:
+
+```xml
+const vchart = new VChart(spec, { dom: CONTAINER_ID });
+//单个theme实例的更新
+vchart.setCurrentTheme('userTheme');
+
+```
+Update of global themes:
+
+
+```xml
+// 注册主题
+VChart.ThemeManager.registerTheme('userTheme', theme);
+//全局主题更新
+VChart.ThemeManager.setCurrentTheme('userTheme');
+
+```
+## Theme Update Executor: VChart.ts \r\n\r\nAnalyze update behavior, focusing on reading this call chain: \r\n\r\n\u0060setCurrentTheme()\u0060→ \u0060setCurrentThemeSync()\u0060\u0026\u0060updateCustomConfigAndRerender()\u0060→ \u0060_setCurrentTheme()\u0060 execution process \r\n\r\n### \u0060_setCurrentTheme() \u0060\r\n\r
+```xml
+ protected _setCurrentTheme(name?: string): IUpdateSpecResult {
+ this._updateCurrentTheme(name);
+ this._initChartSpec(this._getSpecFromOriginalSpec(), 'setCurrentTheme');
+ this._chart?.setCurrentTheme();
+ return { change: true, reMake: false };
+ }
+
+```
+First, analyze the internal private method _setCurrentTheme, first trigger `_updateCurrentTheme`, enter the theme merging and parsing process explained in section 11-1, then reinitialize the chart specification (spec). `chart` is the core rendering instance of the chart, responsible for specific rendering and interaction logic. Here, the method `setCurrentTheme` is called, which will be analyzed in detail below.
+
+Finally, the returned { change: true, reMake: false } indicates: change means the configuration has changed, triggering a re-render, informing the rendering engine that an update is needed. reMake means a complete rebuild of the chart is not necessary, only a partial update is required. This structure is returned to trigger the chart update behavior in the subsequent `setCurrentThemeSync` in `updateCustomConfigAndRerender`.
+
+
+
+### `setCurrentThemeSync()` & `updateCustomConfigAndRerender()`
+
+```xml
+ /**
+ * **同步方法** 设置当前主题。
+ * **注意,如果在 spec 上配置了 theme,则 spec 上的 theme 优先级更高。**
+ * @param name 主题名称
+ * @returns
+ */
+ setCurrentThemeSync(name: string) {
+ if (!ThemeManager.themeExist(name)) {
+ return this as unknown as IVChart;
+ }
+ const result = this._setCurrentTheme(name);
+ this._setFontFamilyTheme(this._currentTheme?.fontFamily as string);
+ this.updateCustomConfigAndRerender(result, true, {
+ transformSpec: false,
+ actionSource: 'setCurrentTheme'
+ });
+ return this as unknown as IVChart;
+ }
+
+```
+After checking for null, we first get the agreed object { change: true, reMake: false }, which means the theme is updated and must trigger a re-render, but there is no need to completely rebuild the table, just a partial update is sufficient.
+
+
+
+#### `updateCustomConfigAndRerender()`
+
+```xml
+ //result: { change: true, reMake: false };
+
+ //调用updateCustomConfigAndRerender
+ this.updateCustomConfigAndRerender(result, true, {
+ transformSpec: false,
+ actionSource: 'setCurrentTheme'
+ });
+
+ //updateCustomConfigAndRerender具体实现
+ updateCustomConfigAndRerender(
+ updateSpecResult: IUpdateSpecResult | (() => IUpdateSpecResult),
+ sync?: boolean,
+ option: IVChartRenderOption = {}
+ ) {
+ if (this._isReleased || !updateSpecResult) {
+ return undefined;
+ }
+ if (isFunction(updateSpecResult)) {
+ updateSpecResult = updateSpecResult();
+ }
+
+ if (updateSpecResult.reAnimate) {
+ this.stopAnimation();
+ this._updateAnimateState(true);
+ }
+
+ this._reCompile(updateSpecResult);
+ if (sync) {
+ return this._renderSync(option);
+ }
+ return this._renderAsync(option);
+ }
+
+
+```
+`updateCustomConfigAndRerender` 是主题重渲染的核心逻辑,也是任何主题配置更改(数据模型、图表spec等发生更改时)重渲染的核心。在主题更新里的逻辑并不复杂,因为传入的`updateSpecResult`:{ change: true, reMake: false } 并不包括动画处理、也不是函数类型,只执行了`_reCompile()`和`_renderSync()`;
+
+##### `recompile()`
+
+```xml
+ protected _reCompile(updateResult: IUpdateSpecResult, morphConfig?: IMorphConfig) {
+ if (updateResult.reMake) {
+ this._releaseData();
+ this._initDataSet();
+ this._chart?.release();
+ this._chart = null as unknown as IChart;
+ }
+
+ if (updateResult.reTransformSpec) {
+ // 释放图表等等
+ this._chartSpecTransformer = null;
+ }
+
+ // 卸载了chart之后再设置主题 避免多余的reInit
+ if (updateResult.changeTheme) {
+ this._setCurrentTheme();
+ this._setFontFamilyTheme(this._currentTheme?.fontFamily as string);
+ } else if (updateResult.changeBackground) {
+ this._compiler?.setBackground(this._getBackground());
+ }
+
+ if (updateResult.reMake) {
+ // 如果不需要动画,那么释放item,避免元素残留
+ this._compiler?.releaseGrammar(this._option?.animation === false || this._spec?.animation === false);
+ // chart 内部事件 模块自己必须删除
+ // 内部模块删除事件时,调用了event Dispatcher.release() 导致用户事件被一起删除
+ // 外部事件现在需要重新添加
+ this._userEvents.forEach(e => this._event?.on(e.eType as any, e.query as any, e.handler as any));
+
+ if (updateResult.reSize) {
+ this._doResize();
+ }
+ } else {
+ if (updateResult.reCompile) {
+ // recompile
+ // 清除之前的所有 compile 内容
+ this._compiler?.clear(
+ { chart: this._chart, vChart: this },
+ this._option?.animation === false || this._spec?.animation === false
+ );
+ // TODO: 释放事件? vgrammar 的 view 应该不需要释放,响应的stage也没有释放,所以事件可以不绑定
+ // 重新绑定事件
+ // TODO: 释放XX?
+ // 重新compile
+ this._compiler?.compile({ chart: this._chart, vChart: this }, {});
+ }
+ if (updateResult.reSize) {
+ const { width, height } = this.getCurrentSize();
+ this._chart.onResize(width, height, false);
+ this._compiler.resize(width, height, false);
+ }
+ }
+ }
+
+```
+* When reMake is true, the chart will be completely reset through `releaseData`, `initDataSet`, and `release`, releasing all related resources to prepare for re-rendering. As mentioned earlier, theme updates do not completely reset the chart.
+
+* When reMake is false, re-compilation and chart resizing will be performed based on the values of `reCompile` and `reSize`, respectively. Operations are implemented through methods on instances such as `_chart` and `_compiler`.
+
+
+
+After reading the source code, it is known that theme updates do not trigger reCompile operations. Generally, reCompile is needed only when there are additions or deletions in the graphics.
+
+##### `_renderSync()`
+
+```xml
+ protected _renderSync = (option: IVChartRenderOption = {}) => {
+ const self = this as unknown as IVChart;
+ if (!this._beforeRender(option)) {
+ return self;
+ }
+ // 填充数据绘图
+ this._compiler?.render(option.morphConfig);
+ this._afterRender();
+ return self;
+ };
+
+
+```
+This is a synchronous rendering method, which prepares and checks before rendering through `_beforeRender` to ensure that the rendering conditions are met; it calls the `render` method of `_compiler` to perform the actual chart drawing, and can pass in transformation configurations; after completing the drawing, `_afterRender` performs post-rendering cleanup and state updates, and returns the current instance.
+
+## Principle of Global Update
+
+### Theme Scheduling Center theme-manager
+
+As mentioned earlier, the VChart instance updates the theme for a single chart, while the themeManager updates the global theme
+
+
https://www.visactor.io/vchart/guide/tutorial_docs/Theme/Customize_Theme
+After registering the theme in `ThemeManager`, you can use `ThemeManager.setCurrentTheme` to hot-update the registered theme by theme name. Note: This method will affect all chart instances on the page.
+
+```xml
+ static setCurrentTheme(name: string) {
+ if (!ThemeManager.themeExist(name)) {
+ return;
+ }
+ ThemeManager._currentThemeName = name;
+ InstanceManager.forEach((instance: IVChart) => instance?.setCurrentTheme(name));
+ }
+
+```
+It is not difficult to see that this method globally sets the current theme name, then iterates over all registered chart instances and calls `setCurrentTheme` on each instance, thereby achieving a global update of the theme for all instances.
+
+### Reason for Theme Instance Operations instance-manager
+
+The operation of the instance on the chart is actually because, within the constructor of the VChart class, the current VChart instance is registered in `InstanceManager.instances`, thereby supporting global operations such as unified theme updates.
+
+```xml
+ export class VChart implements IVChart {
+ constructor(spec: ISpec, options: IInitOption) {
+ //......其他
+ InstanceManager.registerInstance(this);
+ }
+ }
+
+```
+
+
+# Conclusion
+
+In summary, most of the update operations in vchart.ts are implemented in the VChart class, not only involving theme updates but also other situations that require updates. Theme updates are just a part of it; the theme-manager and instance-manager allow developers to manage global theme updates through the registration and traversal of instances, achieving both single instance updates and global updates of themes.
+
+---
+# This document is provided by
+
+Dun Dun (https://github.com/Shabi-x)
+
+
+# This document is revised and organized by
+[Xuan Hun](https://github.com/xuanhun)
\ No newline at end of file
diff --git a/docs/assets/contributing/en/sourcecode/12.1-vchart-plugin-mechanism.md b/docs/assets/contributing/en/sourcecode/12.1-vchart-plugin-mechanism.md
new file mode 100644
index 0000000000..c353c45d92
--- /dev/null
+++ b/docs/assets/contributing/en/sourcecode/12.1-vchart-plugin-mechanism.md
@@ -0,0 +1,136 @@
+---
+title: 12.1 VChart Plugin Mechanism
+
+key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM
+---
+> ## 12.1 VChart Plugin Mechanism
+> Score: 5
+> ## 12.2 Detailed Explanation of VChart Plugin Function Source Code
+> Score: 5
+> 1. Code Entry: `packages/vchart/src/plugin`
+> 1. Key Points of Interpretation:
+
+1. Different Types of Plugins
+
+1. Plugin Mechanism and Implementation Principles
+
+
+
+# Plugin System Concept
+
+VChart provides a series of plugin extension supports. This article only describes the concept of the plugin system and simple usage examples. In-depth source code exploration is analyzed and introduced in section 12.2;
+
+## Different Types of VChart Plugins
+
+### Formatting Plugins
+
+Formatting plugins in VChart support using formatters to update data display styles, enriching data display styles through simple configuration:
+
+
+```xml
+ const spec = {
+ data: [
+ {
+ id: "barData",
+ values: [
+ { month: "Monday", sales: 22.324 },
+ { month: "Tuesday", sales: 13.663 },
+ { month: "Wednesday", sales: 25.342 },
+ { month: "Thursday", sales: 29.3257 },
+ { month: "Friday", sales: 12.999 },
+ ],
+ },
+ ],
+ type: "bar",
+ xField: "month",
+ yField: "sales",
+ label: {
+ visible: true,
+ position: "top",
+ formatter: "¥{sales:.2t}",
+ **//格式化:销售额指定保留两位小数但不四舍五入**
+ },
+ legends: {
+ visible: true,
+ },
+ };
+
+```
+
+
+>
+> The formatting effect is shown in the image
+
+
+
+### media-query
+
+The media-query plugin module implements media query functionality. To facilitate understanding, a demo from the official website can be used to explain:
+
+```Typescript
+const getSpec = () => ({
+ type: 'pie',
+ data: [
+ //...
+ ],
+ //query-media配置流程
+ media: [
+ {
+ query: {
+ maxHeight: 200
+ },
+ action: [
+ {
+ filterType: 'legends',
+ filter: [{ orient: 'top' }, { orient: 'bottom' }],
+ spec: { orient: 'left', padding: 0 }
+ },
+ {
+ filterType: 'title',
+ spec: { visible: false }
+ },
+ {
+ filterType: 'chart',
+ spec: { padding: 10 }
+ }
+ ]
+ }
+ ]
+});
+
+```
+
+
+
+
+
+
+
+
+Observing this example, it is not difficult to find that under the effect of media queries, by declaring media query logic, the style changes of the chart's dynamic layout at different heights are achieved:
+
+* When the chart height ≤ 200px:
+
+* The legend direction changes to the left side, with padding of 0.
+
+* The title is hidden.
+
+* The chart padding is 10.
+
+* When the chart height > 200px:
+
+* Restore default styles.
+
+
+
+Simply put, the media-query plugin of VChart supports us in triggering actions to rearrange the chart layout, achieving responsive design of the chart, enhancing user experience and development efficiency.
+
+
+
+
+
+In the next chapter, I will provide a deeper interpretation of the specific implementation mechanism of the plugin:
+
+
+ # This document was revised and organized by the following personnel
+ [Xuanhun](https://github.com/xuanhun)
\ No newline at end of file
diff --git a/docs/assets/contributing/en/sourcecode/12.2-vchart-plugin-feature-source-code-analysis.md b/docs/assets/contributing/en/sourcecode/12.2-vchart-plugin-feature-source-code-analysis.md
new file mode 100644
index 0000000000..8df10b2bcd
--- /dev/null
+++ b/docs/assets/contributing/en/sourcecode/12.2-vchart-plugin-feature-source-code-analysis.md
@@ -0,0 +1,103 @@
+---
+title: 12.2 VChart Plugin Functionality Source Code Explanation
+
+key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM
+---
+In the previous section (#12.1 VChart Plugin Mechanism), the basic usage of plugins in VChart was introduced. In this section, I will delve into the source code to explore the implementation logic of various plugins in depth;
+
+## Relevant Source Code Locations
+
+* ` packages/vchart/src/plugin/chart/formatter/` : Core implementation of the formatting plugin
+
+* ` packages/vchart/src/plugin/chart/media-query/` : Core implementation of the media query plugin
+
+## Formatting Plugin
+
+### Numerical Text Formatting
+
+
+```xml
+ protected _formatSingleText(text: string | number, formatter: string): string | number {
+ const isNumeric = numberSpecifierReg.test(formatter);
+ if (isNumeric && this._numericFormatter) {
+ // 内置的 formatter 逻辑,可以进行缓存性能优化
+ let numericFormat;
+ if (this._numericFormatterCache && this._numericSpecifier) {
+ if (this._numericFormatterCache.get(formatter)) {
+ numericFormat = this._numericFormatterCache.get(formatter);
+ } else {
+ numericFormat = this._numericSpecifier(formatter) as any;
+ this._numericFormatterCache.set(formatter, numericFormat);
+ }
+ return numericFormat(Number(text));
+ }
+ return this._numericFormatter(formatter, Number(text));
+ } else if (formatter.includes('%') && this._timeFormatter) {
+ return this._timeFormatter(formatter, text);
+ }
+ return text;
+ }
+
+
+```
+### Time Text Formatting
+
+VChart for time format conversion in
+
+
+```xml
+private readonly _timeModeFormat = {
+ utc: TimeUtil.getInstance().timeUTCFormat,
+ local: TimeUtil.getInstance().timeFormat
+};
+
+// 在 onInit 中设置时间格式化器
+onInit(service: IChartPluginService, chartSpec: any) {
+ const { timeMode, timeFormatter } = this._spec;
+
+ if (isFunction(timeFormatter)) {
+ // 使用自定义时间格式化函数
+ this._timeFormatter = timeFormatter;
+ } else if (timeMode && this._timeModeFormat[timeMode]) {
+ // 使用内置的 UTC 或本地时间格式化
+ this._timeFormatter = this._timeModeFormat[timeMode];
+ }
+}
+
+// 在 _formatSingleText 中处理时间格式化
+protected _formatSingleText(text: string | number, formatter: string): string | number {
+ // 数值格式化逻辑...
+
+ // 时间格式化逻辑
+ else if (formatter.includes('%') && this._timeFormatter) {
+ return this._timeFormatter(formatter, text);
+ }
+
+ return text;
+}
+
+```
+### Data Variable Replacement
+
+1. **Template Parsing**:
+
+* Use regular expression `/\{([^}]\u002B)\}/g` to match curly brace templates
+
+* Support nested format definitions (e.g., `{field:format}`)
+
+1. **Field Extraction**:
+
+* Split field name and format specification with a colon (`field:format`)
+
+1. **Dynamic Replacement**:
+
+* Extract corresponding field values from the data object `datum`
+
+* Recursively apply format specifications for secondary formatting
+
+## Media-query Plugin
+
+
+
+ # This document was revised and organized by the following person
+ [玄魂](https://github.com/xuanhun)
\ No newline at end of file
diff --git a/docs/assets/contributing/en/sourcecode/13.1-vchart-on-demand-loading-mechanism.md b/docs/assets/contributing/en/sourcecode/13.1-vchart-on-demand-loading-mechanism.md
new file mode 100644
index 0000000000..d5ee627d78
--- /dev/null
+++ b/docs/assets/contributing/en/sourcecode/13.1-vchart-on-demand-loading-mechanism.md
@@ -0,0 +1,147 @@
+---
+title: 13.1 VChart On-Demand Loading Mechanism
+
+key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM
+---
+VChart is a ready-to-use chart library that provides 20+ chart types by default. As the number of chart types increases and features become richer, package size is a major concern for everyone. Therefore, VChart uses an on-demand loading mechanism to meet various needs for VChart in different scenarios. Before introducing the specific design, we need to understand two prerequisite concepts:
+
+* VChart chart composition
+
+* What is tree-shaking
+
+This article will introduce the principle of VChart's on-demand loading from these two perspectives.
+
+## VChart Chart Composition
+
+### Terminology Definition
+
+Before delving into the composition of VChart charts, we need to understand the following terms:
+
+* `series` - The main body of the chart, also known as a series, contains a set of graphic elements and their corresponding chart logic.
+
+* `mark` - Basic graphic elements, also known as basic graphics, such as points, lines, etc.
+
+* `region` - Spatial information element, associated with one or more series, helps in spatial positioning.
+
+* `component` - Components that assist in reading and interacting with the chart, such as legends, axes, tooltips, etc.
+
+* `layout` - Layout, manages the spatial distribution of chart elements.
+
+* `chart` - An abstract concept of a chart, the manager that integrates and manages data, graphic elements, components, and layout elements.
+
+### Chart Definition
+
+#### Logical Layer Chart Elements
+
+We break down the logical layer elements of a chart into the following four parts:
+
+* series is the main body of the chart, containing a set of graphic elements and the corresponding type of chart logic. For example, in a line chart, series refers to the collection of points and lines and all the logic of the line chart.
+
+* component provides auxiliary capabilities, helping with reading and interacting with the chart, such as legends, axes, tooltips, dataZoom, etc.
+
+* region is a spatial information element that can associate with one or more series, helping series with spatial positioning, and is also a minimum combination unit.
+
+* chart is an abstract concept, the manager that integrates and manages various elements of the chart, and is the core context of the chart's logical layer.
+
+##### Simple Chart
+
+A simple chart consists of a region, a series of a determined type, a component, and a chart that manages the chart logic. Taking a common line chart as an example, its composition is as follows
+
+
+
+##### Combination Chart
+
+We define a combination chart as consisting of multiple regions, multiple series of determined types, components, and a chart that manages the chart logic. Here, we encapsulate the chart as a combination chart with `type: 'common'`.
+
+In a combination chart, several different types of sub-charts can be defined. Each sub-chart can independently configure its own data and components, and all sub-charts are by default associated with the same region. At this point, each sub-chart overlaps on the region. We take the common bar-line dual-axis chart as an example to introduce the combination chart in detail:
+
+* First, if we need to create a combination chart, we need to declare `type: 'common'`, indicating that the type of chart we need to create is a combination chart.
+
+* As mentioned above, the chart is the manager that integrates and manages data, graphic elements, components, and layout elements. Logically, it consists of region + series + layout, and the bar and line correspond to the 'bar' and 'line' series types, respectively. By default, all series are associated with the same region, so we do not need to configure the region here.
+
+* Each series can have its own data source, or the data source can be directly configured on the chart. In the series, it is associated through `fromDataId` or `fromDataIndex`. In the current example, we choose to configure it on the chart.
+
+
+
+As mentioned earlier, a region is a spatial information element that can be used in conjunction with layouts to divide the canvas into spatial sections using multiple differently positioned regions. At the same time, components can also specify relationships associated with regions. When a component is associated with multiple regions, it will by default collect the data dimensions of all subgraphs under the regions for display, as shown in the following example:
+
+
+
+### Primitive mark
+
+Primitives are the definition of graphics in the chart view layer. VChart defines primitives in charts, including basic primitives and composite primitives.
+
+Basic primitives include: symbol, rect, line, rule, arc, area, text, path, image, 3D rect, 3D arc, polygon, etc.
+
+Composite primitives are formed by combining multiple basic primitives. We collectively refer to basic primitives and composite primitives as primitives.
+
+Logical layer elements (such as series) are composed of several primitives. For example, the area chart (`'area'`) series includes points, lines, and areas, corresponding to the basic primitives: symbol, line, area.
+
+
+
+## What is tree-shaking
+
+
+
+Tree Shaking is a code optimization technique used to remove unused code (dead code) in JavaScript. This concept was first proposed by Rollup and later widely adopted by build tools such as Webpack.
+
+
+
+The implementation of Tree Shaking mainly relies on these features of ES Module:
+
+* Import and export statements can only be at the top level of the module
+
+* The names of imported and exported modules cannot be dynamic
+
+* Imported modules are immutable
+
+
+
+
+```javascript
+// 1. 导入导出语句只能在模块顶层
+import { foo } from './foo';
+export const bar = () => {};
+
+// 2. 导入导出的模块名字不能是动态的
+import { 'f' + 'oo' }; // 错误
+
+// 3. 导入的模块是不可变的
+import { foo } from './foo';
+foo = 'bar'; // 错误
+
+```
+The packaging tool constructs a module dependency graph during the marking phase based on the dependencies between files, analyzes import and export relationships, and removes unused exports during the packaging phase, retaining only the used code.
+
+
+
+
+```javascript
+// 1. 标记阶段
+// module.js
+export const foo = () => console.log('foo');
+export const bar = () => console.log('bar');
+
+// main.js
+import { foo } from './module';
+foo(); // foo被标记为使用
+// bar未被使用,标记为dead code
+
+// 2. 删除阶段
+// 打包后,bar函数被删除
+const foo = () => console.log('foo');
+foo();
+
+```
+When using Tree Shaking, the `sideEffects` configuration plays a crucial role in ensuring that unused code is correctly removed. In the project's `package.json` file, the `sideEffects` field is used to inform the bundler which files or modules have side effects, meaning they perform actions other than exporting values (such as modifying global state, executing initialization code, etc.). If a module has no side effects, the bundler can safely remove unreferenced parts.
+
+## The Principle of VChart On-Demand Loading
+
+Based on the above understanding of VChart chart composition and the concept of Tree Shaking, the core idea of VChart on-demand loading is to use Tree Shaking technology to only bundle the chart types, components, and graphic elements that the user actually uses, thereby reducing the package size. In the next chapter, we will detail some implementation specifics.
+
+
+
+
+
+# This document was revised and organized by the following personnel
+[玄魂](https://github.com/xuanhun)
\ No newline at end of file
diff --git a/docs/assets/contributing/en/sourcecode/13.2-vchart-on-demand-loading-source-code-analysis.md b/docs/assets/contributing/en/sourcecode/13.2-vchart-on-demand-loading-source-code-analysis.md
new file mode 100644
index 0000000000..8d39fd61ae
--- /dev/null
+++ b/docs/assets/contributing/en/sourcecode/13.2-vchart-on-demand-loading-source-code-analysis.md
@@ -0,0 +1,191 @@
+---
+title: 13.2 VChart On-Demand Loading Source Code Explanation
+
+key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM
+---
+Based on the previous articles, we have introduced the composition of VChart and the concept of Tree Shaking. Based on these two preliminary concepts, we will now elaborate on the specific implementation of VChart's on-demand loading.
+
+## Core Creation Process of VChart Charts
+
+
+
+
+
+## Factory
+
+The on-demand loading of VChart mainly relies on the `Factory` class to achieve this. This class plays an important role, responsible for registering and creating various charts, series, components, graphics, Regions, layouts, and plugins. Below, we will conduct an in-depth analysis from the aspects of the registration mechanism, creation mechanism, and on-demand registration of charts.
+
+### Registration Mechanism
+
+The `Factory` class provides a series of static methods for registering different types of modules. Through these methods, modules are registered into the static properties of `Factory`, thereby forming a registry. The specific code is as follows:
+
+```xml
+static registerChart(key: string, chart: IChartConstructor) {
+ Factory._charts[key] = chart;
+}
+static registerSeries(key: string, series: ISeriesConstructor) {
+ Factory._series[key] = series;
+}
+static registerComponent(key: string, cmp: IComponentConstructor, alwaysCheck?: boolean) {
+ Factory._components[key] = { cmp, alwaysCheck };
+}
+// 其他注册方法...
+
+```
+### Creation Mechanism
+
+The `Factory` class also provides a series of static methods for creating module instances as needed. These methods look up the corresponding constructor from the registry based on the type and create an instance. The sample code is as follows:
+
+
+```xml
+static createChart(chartType: string, spec: any, options: IChartOption): IChart | null {
+ if (!Factory._charts[chartType]) {
+ return null;
+ }
+ const ChartConstructor = Factory._charts[chartType];
+ return new ChartConstructor(spec, options);
+}
+static createSeries(seriesType: string, spec: any, options: ISeriesOption) {
+ if (!Factory._series[seriesType]) {
+ return null;
+ }
+ const SeriesConstructor = Factory._series[seriesType];
+ return new SeriesConstructor(spec, options);
+}
+// 其他创建方法...
+
+```
+### On-Demand Registration of Charts
+
+Taking the line chart as an example, let's look at the specific implementation of on-demand registration. In `packages/vchart/src/chart/line/line.ts`, there is the following code:
+
+
+```javascript
+export const registerLineChart = () => {
+ registerLineSeries();
+ Factory.registerChart(LineChart.type, LineChart);
+};
+
+```
+The `registerLineSeries` is implemented in `packages/vchart/src/series/line/line.ts`, the code is as follows:
+
+```javascript
+export const registerLineSeries = () => {
+ registerSampleTransform();
+ registerMarkOverlapTransform();
+ registerLineMark();
+ registerSymbolMark();
+ registerLineAnimation();
+ registerScaleInOutAnimation();
+ registerCartesianBandAxis();
+ registerCartesianLinearAxis();
+ Factory.registerSeries(LineSeries.type, LineSeries);
+};
+
+```
+By implementing the above code, when using VChart, if you call `registerLineChart` to register a line chart, it will automatically register the necessary elements such as the line series, line chart elements, and point chart elements that the line chart depends on. The specific usage is as follows:
+
+```xml
+import { VChart } from './core';
+import { registerLineChart } from './chart/line';
+VChart.useRegisters([
+ registerLineChart,
+ // 其他需要的模块
+]);
+
+```
+In `packages/vchart/src/core/vchart.ts`, the chart instance is not created by direct path reference, but by using `Factory.createChart`. In this way, the core class `vchart` can create instances based on the charts registered by the user without referencing all chart implementations. The relevant code is as follows:
+
+```xml
+private _initChart(spec: any) {
+ // ...
+ const chart = Factory.createChart(spec.type, spec, this._getChartOption(spec.type));
+ //...
+ }
+
+```
+## Core Class VChart On-Demand Loading
+
+Next, let's discuss a question: Is there a difference between the following two ways of referencing `VChart`?
+
+* Method One:
+
+
+```javascript
+import VChart from '@visactor/vchart';
+
+```
+* Method Two:
+
+```javascript
+import { VChart } from '@visactor/vchart';
+
+```
+The answer is yes, the effects produced by these two citation methods are different. Below is an analysis of the reasons for their differences.
+
+First, in the corresponding `package.json` of the vchart codebase, you can see the following configuration:
+
+```xml
+{
+ "sideEffects": [
+ "./*/index-lark.js",
+ "./*/index-wx-simple.js",
+ "./*/index-wx.js",
+ "./*/vchart-all.js",
+ "./*/vchart-simple.js"
+ ],
+}
+
+```
+The configuration explicitly declares all files with side effects.
+
+In `packages/vchart/index.ts`, the following exports are present:
+
+```xml
+import { VChart } from './vchart-all';
+export default VChart;
+export * from './core';
+
+```
+In the `core/index.ts` file, the following exports are present:
+
+```javascript
+import { VChart } from './vchart';
+export { VChart, Factory };
+
+```
+So method one is equivalent to the following reference, where the referenced VChart is the VChart class exported by vchart-all, and method two is equivalent to the VChart class exported from `core/vchart.ts`.
+
+```json
+import { default as VChart } from '@visactor/vchart';
+
+```
+The main purpose of the file `vchart-all.ts` is to register and export all functional modules of VChart:
+
+```json
+VChart.useRegisters([
+ // charts
+ registerLineChart,
+ registerAreaChart,
+ // ...其他图表
+ // components
+ registerCartesianLinearAxis,
+ registerCartesianBandAxis,
+ // ...其他组件
+ // layout
+ registerGridLayout,
+ registerLayout3d,
+ // mark
+ registerAllMarks,
+ // plugin
+ registerDomTooltipHandler,
+ registerCanvasTooltipHandler,
+ // ...其他插件
+]);
+export { VChart };
+
+```
+Since vchart - all is declared as a file with side effects, when VChart is referenced using method one, all files that vchart-all depends on will be packaged; whereas when VChart is referenced using method two, only core/vchart.ts will be packaged.
+
+# This document was revised and organized by the following personnel
+[玄魂](https://github.com/xuanhun)
\ No newline at end of file
diff --git a/docs/assets/contributing/en/sourcecode/14.1.1-react-vchart-introduction.md b/docs/assets/contributing/en/sourcecode/14.1.1-react-vchart-introduction.md
new file mode 100644
index 0000000000..8cb61864ee
--- /dev/null
+++ b/docs/assets/contributing/en/sourcecode/14.1.1-react-vchart-introduction.md
@@ -0,0 +1,134 @@
+---
+title: 14.1.1 Introduction to React-VChart
+
+key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM
+---
+## Overview
+
+react-vchart is the React wrapper version of VChart, mainly providing two styles of components externally:
+
+* `` and ``
+
+* `` and other semantic tags
+
+Their differences are as follows:
+
+* **Applicable Scenarios**:
+
+* ``: A large and comprehensive unified entry tag that encapsulates chart specifications, providing standardized update and unload logic. Suitable for toB pages, product pages with page building, and business parties migrating with self-encapsulated VChart.
+
+* Semantic tags: Suitable for simple pages, where developers write code manually, making it easy to implement unpacking and on-demand loading.
+
+* **Usage**:
+
+* ``: Receives a complete spec as the chart definition. When using, introduce the `VChart` component and pass in spec and other related attributes. For example:
+
+
+```xml
+import { VChart } from '@visactor/react-vchart';
+// 假设已经有了 spec 图表描述信息
+const spec = {
+ // 图表定义相关内容
+};
+const App = () => {
+ return (
+
+ );
+};
+export default App;
+
+```
+* Syntax tags: Encapsulate the chart container and each component as React components for export. Choose the corresponding chart tag according to the chart type when using, and then match it with the appropriate component tags and series tags. For example, to create a bar chart: \r\n\r
+```javascript
+import React, { useRef } from'react';
+import { BarChart, Bar, Legend, Axis } from '@visactor/react-vchart';
+const App = () => {
+ const chartRef = useRef(null);
+ const handleChartClick = () => {
+ console.log('图表被点击了');
+ };
+ const barData = [
+ { type: 'Autocracies', year: '1930', value: 129 },
+ // 其他数据项
+ ];
+ return (
+
+
+
+
+
+
+
+
+ );
+};
+export default App;
+
+```
+Through the above code examples, the differences in usage between the two components can be understood more intuitively.
+
+
+
+## Core Code Implementation
+
+
+
+From the implementation perspective, the encapsulation principles of `` and `` do not differ much. Firstly, all Chart components are encapsulated based on `BaseChart`, with the core code in the following files:
+
+* [`packages/react-vchart/src/containers/withContainer.tsx`](https://github.com/VisActor/VChart/blob/develop/packages/react-vchart/src/containers/withContainer.tsx)
+
+* [`packages/react-vchart/src/charts/BaseChart.tsx`](https://github.com/VisActor/VChart/blob/develop/packages/react-vchart/src/charts/BaseChart.tsx)
+
+For semantic tags, apart from the above modules, the main focus is on the encapsulation of components and series, with the core code as follows:
+
+* [`packages/react-vchart/src/components/BaseComponent.tsx`](https://github.com/VisActor/VChart/blob/develop/packages/react-vchart/src/components/BaseComponent.tsx)
+
+* [`packages/react-vchart/src/series/BaseSeries.tsx`](https://github.com/VisActor/VChart/blob/develop/packages/react-vchart/src/series/BaseSeries.tsx)
+
+
+
+Taking AreaChart as an example, the main class relationship diagram is as follows
+
+
+
+
+
+
+
+
+在接下来的章节,我们将详细的分析Chart组件、系列组件、VChart组件的封装
+
+
+
+
+
+
+
+
+
+
+
+ # 本文档由以下人员修正整理
+ [玄魂](https://github.com/xuanhun)
\ No newline at end of file
diff --git a/docs/assets/contributing/en/sourcecode/14.1.2-react-vchart-source-code-analysis.md b/docs/assets/contributing/en/sourcecode/14.1.2-react-vchart-source-code-analysis.md
new file mode 100644
index 0000000000..7ea32b8755
--- /dev/null
+++ b/docs/assets/contributing/en/sourcecode/14.1.2-react-vchart-source-code-analysis.md
@@ -0,0 +1,466 @@
+---
+title: 14.1.2 react-vchart Source Code Explanation
+
+key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM
+---
+## Implementation of BaseChart
+
+In react-vchart, the encapsulation of all charts is achieved through the higher-order component `createChart`. Next, we will take the implementation of `` as an example to explain the implementation principle in detail.
+
+
+
+### 1.1 Explanation of `` Encapsulation
+
+The encapsulation of `` is as follows:
+
+
+```javascript
+export const VChart = createChart('VChart', {
+ vchartConstrouctor: VChartCore
+});
+
+```
+This code is relatively simple and includes the following content:
+
+1. Use the `createChart` factory function to create a component
+
+2. Specify the component name as `VChart`
+
+3. Inject the `VChartCore` constructor
+
+
+
+### 1.2 Basic Chart Implementation (BaseChart.tsx)
+
+
+
+#### 1.2.1 State Management
+
+
+```Typescript
+const [updateId, setUpdateId] = useState(0);
+const chartContext = useRef({});
+const [view, setView] = useState(null);
+const isUnmount = useRef(false);
+
+```
+
+
+Key States:
+
+* `updateId`: Used to control the update of subcomponents.
+
+* `chartContext`: Used to store chart instances.
+
+* `view`: Used to store view instances.
+
+* `isUnmount`: Used to control the unmount state of the component.
+
+#### 1.2.2 Spec Parsing System
+
+```xml
+const parseSpec = (props: Props) => {
+ let spec: ISpec;
+ // 1. 处理直接传入的 spec
+ if (hasSpec && props.spec) {
+ spec = props.spec;
+ if (isValid(props.data)) {
+ spec = {
+ ...props.spec,
+ data: props.data
+ };
+ }
+ }
+ // 2. 处理从子组件收集的 spec
+ else {
+ spec = {
+ ...prevSpec.current,
+ ...specFromChildren.current
+ };
+ }
+ // 3. 处理 tooltip
+ const tooltipSpec = initCustomTooltip(setTooltipNode, props, spec.tooltip);
+ if (tooltipSpec) {
+ spec.tooltip = tooltipSpec;
+ }
+ return spec;
+};
+
+```
+The Spec parsing system includes three levels:
+
+1. Directly passed spec configuration.
+
+2. Aggregation of subcomponent configurations.
+
+3. Handling of special components (such as tooltip).
+
+#### 1.2.3 Subcomponent Parsing System
+
+
+```xml
+const parseSpecFromChildren = (props: Props) => {
+ const specFromChildren: Omit = {};
+ toArray(props.children).map((child, index) => {
+ const parseSpec = child?.type?.parseSpec;
+ if (parseSpec && child.props) {
+ // 处理子组件配置...
+ const specResult = parseSpec(childProps);
+ // 处理单例和数组配置
+ if (specResult.isSingle) {
+ specFromChildren[specResult.specName] = specResult.spec;
+ } else {
+ if (!specFromChildren[specResult.specName]) {
+ specFromChildren[specResult.specName] = [];
+ }
+ specFromChildren[specResult.specName].push(specResult.spec);
+ }
+ }
+ });
+ return specFromChildren;
+};
+
+```
+The responsibilities of the system include:
+
+1. Collecting configurations of all sub-components.
+
+2. Distinguishing between singleton and array types of configurations.
+
+3. Generating the final configuration object.
+
+#### 1.2.4 Update Mechanism
+
+```xml
+useEffect(() => {
+ // 1. 首次渲染
+ if (!chartContext.current?.chart) {
+ createChart(props);
+ renderChart();
+ return;
+ }
+ // 2. spec 更新
+ if (hasSpec) {
+ if (!isEqual(eventsBinded.current.spec, props.spec)) {
+ chartContext.current.chart.updateSpecSync(parseSpec(props));
+ handleChartRender(true);
+ }
+ // 3. 数据更新
+ else if (eventsBinded.current.data!== props.data) {
+ chartContext.current.chart.updateFullDataSync(props.data);
+ handleChartRender(true);
+ }
+ return;
+ }
+ // 4. 子组件更新
+ const newSpec = pickWithout(props, notSpecKeys);
+ if (!isEqual(newSpec, prevSpec.current)) {
+ // 更新处理...
+ }
+}, [props]);
+
+```
+The update mechanism covers the following four scenarios:
+
+1. Initial rendering
+
+2. Spec configuration update
+
+3. Data update
+
+4. Updates caused by subcomponents
+
+#### 1.2.4 Lifecycle Management
+
+
+```xml
+useEffect(() => {
+ return () => {
+ if (chartContext.current?.chart) {
+ chartContext.current.chart.release();
+ chartContext.current.chart = null;
+ }
+ eventsBinded.current = null;
+ isUnmount.current = true;
+ };
+}, []);
+
+```
+When the component is destroyed, ensure that resources can be released, including:
+
+* Release chart instances
+
+* Clean up event bindings
+
+* Update component status
+
+## Implementation of BaseComponent
+
+### 2.1 Core Implementation Mechanism
+
+In the react-vchart framework, the creation of all components relies on the `createComponent` factory function. The definition of this function is as follows:
+
+```xml
+const createComponent = (
+ componentName: string, // 组件名
+ specName: string, // 规格名称
+ supportedEvents?: Record, // 支持的事件
+ isSingle?: boolean, // 是否单例
+ registers?: (() => void)[] // 注册器
+): any => {
+ // ...组件创建逻辑
+};
+
+```
+Here, the generic `T extends ComponentProps` is used to constrain the type of component properties passed in. The function receives multiple parameters:
+
+* `componentName`: Used to identify the name of the component, which is unique throughout the application, making it easy for developers to recognize and manage components.
+
+* `specName`: Represents the specification name corresponding to the component, which is very important for configuration collection and management. Different components are distinguished by different specification names for their respective configurations.
+
+* `supportedEvents`: An optional object used to define the events supported by the component. The key-value pair form of the object represents the event type and the corresponding event handling logic. For example, a component may support the `click` event and define the corresponding handler function.
+
+* `isSingle`: A boolean value used to indicate whether the component is in singleton mode. If `true`, it means that there will only be one instance of the component in the entire application; if `false`, multiple instances can be created.
+
+* `registers`: An array of functions, each used to perform specific registration operations. These registration operations may include registering specific functions or plugins of the component into the framework.
+
+To understand more intuitively, the following shows the encapsulation code using the axis component and legend component as examples:
+
+* **Axis**
+
+```xml
+export const Axis = createComponent('Axis', 'axes');
+
+```
+Here, a coordinate axis component named `Axis` is created, the component name is `Axis`, and the corresponding specification name is `axes`. In this way, the framework can accurately identify and handle the relevant configurations and operations of the coordinate axis component.
+
+* **Legend**
+
+```xml
+export const Legend = createComponent(
+ 'Legend',
+ 'legends',
+ LEGEND_CUSTOMIZED_EVENTS,
+ false,
+ [registerDiscreteLegend]
+);
+
+```
+This code creates a `Legend` component, with the component name being `Legend` and the specification name being `legends`. It also specifies the custom events supported by this component `LEGEND_CUSTOMIZED_EVENTS`, and the component is not in singleton mode (`false`). Finally, a registrar function `registerDiscreteLegend` is passed in to perform specific registration operations, which may be to register discrete data-related functions for the legend component.
+
+### 2.2 Component Communication Mechanism
+
+#### 2.2.1 Context Communication
+
+
+```xml
+const Comp: React.FC = (props: T) => {
+ const context = useContext(RootChartContext);
+ // ...
+};
+
+```
+In a React application, communication between components is an important issue. Here, the `useContext` hook function is used to achieve communication between components. `RootChartContext` is a context object that contains information related to charts, such as chart instances, global configurations, etc. By using `useContext(RootChartContext)`, components can access this global information to achieve data sharing and interaction between components. For example, a child component may need to obtain the global configuration information of the chart to adjust its display mode, and it can obtain context information in this way.
+
+#### 2.2.2 Event System
+
+
+```xml
+// 事件绑定
+if (supportedEvents) {
+ bindEventsToChart(
+ context.chart,
+ props,
+ eventsBinded.current,
+ supportedEvents
+ );
+}
+
+```
+This part of the code implements the event binding functionality of the component. When the component defines `supportedEvents` (i.e., supported events), the `bindEventsToChart` function is called to bind events. This function receives four parameters:
+
+* `context.chart`: Represents the chart instance, obtained through the context. Events are bound to this chart instance so that the handling logic can be triggered when the chart experiences corresponding events.
+
+* `props`: The properties of the component, which may include configuration information related to events, such as event handler functions.
+
+* `eventsBinded.current`: Possibly an object or variable that stores the events that have already been bound, used to record the currently bound events to avoid duplicate bindings.
+
+* `supportedEvents`: The aforementioned object of events supported by the component, containing the mapping relationship between event types and handler functions. In this way, the component can interact with the chart instance to achieve the association between user operations and component behavior.
+
+### 2.3 Configuration Collection Mechanism
+
+Each component implements the `parseSpec` method to parse the configuration corresponding to the component, ultimately assembling it into the complete `spec` required by vchart:
+
+
+```xml
+Comp.parseSpec = (props: T) => {
+ return {
+ spec: pickWithout(props, notSpecKeys),
+ specName,
+ isSingle
+ };
+};
+
+```
+`parseSpec` method plays a key role in component configuration management. It receives the component's `props` as a parameter and returns an object containing three attributes:
+
+* `spec`: The component configuration obtained through the `pickWithout(props, notSpecKeys)` method. The `pickWithout` function might be a custom function used to filter out the required configuration information from `props`, excluding unnecessary keys (`notSpecKeys`). This configuration information will be used as the actual configuration for the component in vchart.
+
+* `specName`: The aforementioned component specification name, used to identify the type of component configuration, facilitating differentiation and management in the overall configuration.
+
+* `isSingle`: A boolean value indicating whether the component is in singleton mode. This information is also crucial in the process of configuration assembly and management, for example, when handling multiple component configurations, it is necessary to decide how to merge configurations based on the value of `isSingle`. By implementing the `parseSpec` method for each component, the framework can collect the configuration information of each component and ultimately assemble it into a complete configuration `spec` that meets vchart requirements.
+
+### 2.4 Component Registration Mechanism
+
+
+```xml
+if (registers && registers.length) {
+ VChart.useRegisters(registers);
+}
+
+```
+This part of the code implements the component registration mechanism. When a component defines `registers` (i.e., an array of registrars) and the array is not empty, the `VChart.useRegisters(registers)` method is called. `VChart` may be a global chart object or a framework core object, and the `useRegisters` method is used to register functions from the registrar array into the framework. These registrar functions may be used to register specific features, plugins, or integrations with other modules for the component. In this way, the component can register some of its special features or configurations into the framework to function throughout the application.
+
+### 2.5 Configuration Filtering
+
+
+```xml
+const notSpecKeys = supportedEvents
+ ? Object.keys(supportedEvents).concat(ignoreKeys)
+ : ignoreKeys;
+
+```
+This code implements the configuration filtering function. The `notSpecKeys` variable is used to store unwanted configuration keys. If the component defines `supportedEvents` (i.e., supported events), then `notSpecKeys` is formed by merging all keys of `supportedEvents` with `ignoreKeys`; otherwise, `notSpecKeys` is directly equal to `ignoreKeys`. `ignoreKeys` may be a predefined array containing some keys that need to be ignored during the configuration parsing process. In this way, during the configuration collection and parsing process, unwanted configuration information can be excluded, ensuring that the final configuration `spec` only contains useful information, thereby improving the accuracy and effectiveness of the configuration.
+
+### 2.6 Update Control
+
+
+```xml
+if (props.updateId!== updateId.current) {
+ updateId.current = props.updateId;
+ // 处理更新逻辑...
+}
+
+```
+This part of the code implements the update control of the component. `updateId` is an identifier used to control component updates. When the `props.updateId` received by the component is not equal to the currently stored `updateId.current`, it indicates that an update has occurred. At this point, `updateId.current` is updated to `props.updateId`, and then the subsequent update logic is executed (indicated in the code by the comment `// Handle update logic...`). This update control mechanism ensures that when the component receives a new update identifier, it can correctly handle update operations, such as re-rendering the component, updating data, or performing specific update tasks, thereby ensuring that the component's state remains consistent with the latest requirements.
+
+## Implementation of BaseSeries
+
+The series components of React-VChart are also mainly implemented using higher-order components. The following will provide a more detailed analysis of its core implementation.
+
+### 3.1 Series Component Creator
+
+```xml
+export const createSeries = (
+ componentName: string, // 组件名称
+ markNames: string[], // 图形标记名称
+ type?: string, // 图表类型
+ registers?: (() => void)[] // 注册函数
+) => {
+ //...
+}
+
+```
+This factory function plays a core role in the creation process of the entire series of components. It strictly constrains the type of component properties passed in through the generic `\u003CT extends BaseSeriesProps\u003E`, ensuring type safety.
+
+The parameters received by the function have their own important responsibilities:
+
+* `componentName`: Serves as the unique identifier of the component, having uniqueness throughout the application. This makes it more convenient for developers to manage and identify components, just like giving each component a unique "name tag".
+
+* `markNames`: An array of series element names used to determine the elements used by the component.
+
+* `type`: The chart type, although an optional parameter, clarifies the chart type corresponding to the component.
+
+* `registers`: Declares the resources that the series needs to register, used for on-demand loading through tree-shaking to achieve package size optimization.
+
+### 3.2 Area Component Implementation
+
+```xml
+export type AreaProps = BaseSeriesProps & Omit;
+export const Area = createSeries(
+ 'Area', // 组件名
+ ['area'], // 图形标记
+ 'area', // 类型
+ [registerAreaSeries] // 注册器
+);
+
+```
+`Area` 组件的定义首先通过 `export type AreaProps = BaseSeriesProps & Omit` 来定义其属性类型。它结合了 `BaseSeriesProps` 和 `IAreaSeriesSpec`,并通过 `Omit` 操作排除了 `'type'` 属性,这是因为在创建组件时,类型已经通过 `createSeries` 函数的参数进行了指定。
+
+然后,通过 `createSeries` 函数创建 `Area` 组件。传入的参数分别为组件名 `'Area'`、图形标记 `['area']`、图表类型 `'area'` 以及注册器 `[registerAreaSeries]`。注册器 `registerAreaSeries` 用于执行与面积图相关的特定注册操作,可能包括注册面积图的样式、动画效果等。
+
+### 3.3 核心功能实现
+
+* **标记 ID 管理**
+
+```xml
+const addMarkId = (spec: any, seriesId: string | number) => {
+ markNames.forEach(markName => {
+ const defaultMarkId = `${seriesId}-${markName}`;
+ if (isNil(spec[markName])) {
+ spec[markName] = { id: defaultMarkId };
+ } else if (isNil(spec[markName].id)) {
+ spec[markName].id = defaultMarkId;
+ }
+ });
+};
+
+```
+In the process of chart rendering, each graphic mark needs to have a unique identifier, which is the role of mark ID management. The `addMarkId` function receives `spec` (configuration object) and `seriesId` (series ID) as parameters.
+
+The function generates a default `markId` for each graphic mark by traversing the `markNames` array. The generation rule is to concatenate `seriesId` and `markName` with `-`, for example, `'series1-area'`.
+
+If a property corresponding to a `markName` does not exist in `spec`, an object containing the default `markId` is created; if the `markName` property exists but `id` does not, the default `markId` is set for it. This ensures that each graphic mark has a unique identifier, facilitating subsequent event handling and style setting operations.
+
+* **Event Handling System**
+
+```xml
+const handleEvent = (e: any) => {
+ const markIds = markNames.map(markName =>
+ `${id}-${markName}`
+ );
+ if (e?.mark && markIds.includes(e.mark.getUserId())) {
+ props[VCHART_TO_REACT_EVENTS[e.event.type]](e);
+ }
+};
+
+```
+The event handling system is responsible for processing user interactions with the chart. The `handleEvent` function receives an event object `e`.
+
+First, generate all possible `markId` arrays `markIds` through the `markNames` array. Then check whether the `mark` in the event object `e` exists and whether the user ID of `mark` is in the `markIds` array.
+
+If the conditions are met, it indicates that the event is triggered by the graphic mark of the current component. Then, find the corresponding event handler through `props[VCHART_TO_REACT_EVENTS[e.event.type]]` and pass the event object `e` into it to perform the corresponding operation. `VCHART_TO_REACT_EVENTS` is a mapping table used to map VChart's event types to React component's event handlers.
+
+* **Configuration Parsing**
+
+```xml
+Comp.parseSpec = (compProps: T) => {
+ const newSeriesSpec = pickWithout(compProps, notSpecKeys);
+ // 添加标记 ID
+ addMarkId(newSeriesSpec, compProps.id?? compProps.componentId);
+ // 设置类型
+ if (!isNil(type)) {
+ newSeriesSpec.type = type;
+ }
+ return {
+ spec: newSeriesSpec,
+ specName:'series'
+ };
+};
+
+```
+The configuration parsing function `Comp.parseSpec` is responsible for parsing the component's properties into a configuration object that meets the requirements of VChart.
+
+First, the function `pickWithout(compProps, notSpecKeys)` is used to filter out the required configuration information from `compProps`, excluding unnecessary keys `notSpecKeys`. `notSpecKeys` may contain some properties unrelated to event handling or other aspects, ensuring the purity of the configuration object in this way.
+
+Then, the `addMarkId` function is called to add a mark ID to the new series configuration `newSeriesSpec`, ensuring that each graphic mark has a unique identifier.
+
+Next, if the `type` parameter is not empty, the chart type is set in `newSeriesSpec`.
+
+Finally, an object containing `spec` (the parsed configuration object) and `specName` (the configuration type name, here as `'series'`) is returned. This object will be passed to VChart for rendering as the final configuration.
+
+Through the detailed analysis above, we have gained a deeper understanding of the implementation principles of the React-VChart series components, including component creation, property definition, and the implementation of core functions. These technical principles provide a solid foundation for developers when using and extending React-VChart.
+
+
+# This document was revised and organized by the following personnel
+[玄魂](https://github.com/xuanhun)
\ No newline at end of file
diff --git a/docs/assets/contributing/en/sourcecode/14.2.1-taro-vchart-introduction.md b/docs/assets/contributing/en/sourcecode/14.2.1-taro-vchart-introduction.md
new file mode 100644
index 0000000000..459761ee90
--- /dev/null
+++ b/docs/assets/contributing/en/sourcecode/14.2.1-taro-vchart-introduction.md
@@ -0,0 +1,104 @@
+---
+title: 14.2.1 Taro-VChart Introduction
+
+key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM
+---
+## Overview
+
+taro-vchart is the Taro mini program encapsulation version of VChart, providing an encapsulation of the VChart React version in the Taro environment.
+
+* For more information about the Taro mini program host environment, please refer to the official documentation: https://docs.taro.zone/docs/
+
+## Core Code Structure
+
+taro-vchart's directory and architecture correspond to:
+
+* Chart Factory Layer: `charts` directory
+
+Using the factory pattern to uniformly generate chart components (such as `BoxPlotChart`), which includes all available chart type components. Each chart is created through the createChart method with standardized parameters:
+
+
+```xml
+export const Chart = createChart(
+ 'ChartName',
+ { chartConstructor: VChart }, // 核心图表构造器
+ [registerModules] // 按需注册的图表模块
+);
+
+```
+* Cross-platform adaptation layer: The `components` directory implements the core logic for cross-platform rendering, including a general chart component and a browser chart component, with consistent functionality mainly to address different platforms.
+
+* General chart component `general-chart/index.tsx`
+
+```Typescript
+export class GeneralChart extends React.Component {
+ // 小程序专用生命周期
+ async componentDidMount() {
+ // 通过循环最多尝试100次获取DOM节点(解决飞书小程序异步问题)
+ for (let i = 0; i < MAX_TIMES; i++) {
+ const domref = await getDomRef();
+ this.init({ domref });
+ }
+ }
+
+ // 小程序专用渲染结构
+ render() {
+ return (
+
+ {/* 交互事件画布 */}
+ {/* 主渲染画布 */}
+ {/* 辅助画布 */}
+
+ )
+ }
+}
+
+```
+* Browser chart component `web-chart/index.tsx`
+
+```xml
+export class WebChart extends React.Component {
+ // 标准浏览器生命周期
+ componentDidMount() {
+ this.vchart = new chartConstructor(spec, {
+ dom: canvasId // 直接使用DOM容器
+ });
+ }
+
+ // 简单DOM结构
+ render() {
+ return
// 单容器方案
+ }
+}
+
+```
+The cross-platform adaptation architecture is shown in the figure below:
+
+
+
+Taro is a framework that can run in various mini-program environments. When using GeneralChart, you can pass in different environments to adapt:
+
+```Typescript
+const strategies = {
+ lark: () => ,
+ tt: () => ,
+ weapp: () => ,
+ web: () => ,
+ h5: () =>
+};
+
+```
+TTCanvas is responsible for managing specific VChart instances, receiving props passed by GeneralChart, and implements the chart capabilities for seamless integration into the mini-program ecosystem through an abstract general interface.
+
+
+
+In the following chapters, we will analyze the encapsulation of the WX-VChart component in detail.
+
+
+
+
+
+
+
+ # This document was revised and organized by the following person
+ [玄魂](https://github.com/xuanhun)
\ No newline at end of file
diff --git a/docs/assets/contributing/en/sourcecode/14.2.2-taro-vchart-source-code-analysis.md b/docs/assets/contributing/en/sourcecode/14.2.2-taro-vchart-source-code-analysis.md
new file mode 100644
index 0000000000..af51af7843
--- /dev/null
+++ b/docs/assets/contributing/en/sourcecode/14.2.2-taro-vchart-source-code-analysis.md
@@ -0,0 +1,189 @@
+---
+title: 14.2.2 Taro-VChart Source Code Explanation
+
+key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM
+---
+## Compatibility with Host Environment
+
+The Taro framework, based on the React technology stack, provides cross-platform component development capabilities (https://taro-docs.jd.com/docs/component). A Taro component consists of the following files:
+
+* index.config.ts: Component compilation configuration (optional)
+
+* index.tsx: Component logic and template content
+
+* index.module.scss: Component styles (CSS Modules scheme recommended)
+
+
+
+### File Description
+
+1. **index.tsx**
+
+Main component file, includes:
+
+* Define the component using `function Component() { ... }` or `class Component extends Component { ... }`
+
+* Write component structure using JSX template syntax
+
+* Export the component through export default
+
+* Component lifecycle management (using Hooks or Class lifecycle)
+
+* Event handling (following React synthetic event specifications)
+
+
+
+2. **index.module.scss**
+
+Component style file:
+
+* Supports Sass/Scss preprocessing
+
+* Use CSS Modules to avoid style pollution
+
+* Import using `import styles from './index.module.scss'`
+
+* Bind styles using className={styles.container}
+
+
+
+3. **index.config.ts** (optional)
+
+Component compilation configuration:
+
+* Define component name: `defineCustomComponent({ name: 'my-component' })`
+
+* Set default values for component properties
+
+* Configure native mini-program components needed by the component
+
+* Cross-platform compatibility configuration
+
+
+
+### 1. Core Entry Module
+
+`index.tsx` is the entry file of the entire library, exporting two core components `VChart` and `VChartSimple`:
+
+
+```xml
+import { VChartSimple } from './simple';
+import { VChart } from './vchart';
+
+export * from './charts'; // 导出所有图表组件
+export { VChart, VChartSimple }; // 导出核心适配器
+export default VChart; // 默认导出
+
+```
+Three-layer export strategy is implemented here:
+
+* Chart component set: Export all predefined charts in bulk through export *
+
+* Core adapters: Individually export the two main components, VChart and VChartSimple
+
+* Default export: Maintain compatibility with the original VChart API
+
+## 2. Environment Adaptation Layer
+
+### 2.1 VChart Component
+
+`vchart.tsx` is the main environment adaptation component, which will choose the appropriate rendering strategy based on the current environment:
+
+
+```xml
+const strategies = {
+ lark: () => ,
+ tt: () => ,
+ weapp: () => ,
+ web: () => ,
+ h5: () =>
+};
+
+```
+Key Design Points:
+
+* Use strategy pattern to handle different environments
+
+* Automatically register environment-specific configurations (such as registerLarkEnv)
+
+* Pass in specific mode parameters to adapt to different mini-program platforms
+
+### 2.2 VChartSimple Component
+
+`simple.tsx` is a simplified version of VChart, without environment registration logic:
+
+
+```xml
+export function VChartSimple({ type, ...args }: IVChartProps) {
+ const env = (type ?? Taro.getEnv()).toLocaleLowerCase();
+ const strategies = {
+ lark: () => ,
+ tt: () => ,
+ // ...其他环境
+ };
+
+ // 环境选择逻辑
+}
+
+```
+This component is used for on-demand loading scenarios to reduce package size.\r\n\r\n## Chart Factory System\r\n\r\n`charts/generate-charts.tsx` implements the factory pattern for chart components, providing:\r\n\r\n* Unified component creation process\r\n\r\n* Automatic registration of chart dependency modules\r\n\r\n* Type safety (through generic constraints)\r\n\r\nUsing the factory pattern to uniformly generate chart components (such as `BoxPlotChart`), which includes all available chart type components. Each chart is created through the createChart method, standardizing parameters:\r\n\r
+```xml
+export const Chart = createChart(
+ 'ChartName',
+ { chartConstructor: VChart }, // 核心图表构造器
+ [registerModules] // 按需注册的图表模块
+);
+
+```
+## Rendering Component Layer
+
+After configuring the corresponding charts, we enter the rendering component layer, which includes a general chart component and a browser chart component. Their functions are the same, mainly to cater to different platforms. A brief flowchart is as follows:
+
+
+
+
+### General Chart Component
+
+`components/general-chart/index.tsx` is the core rendering component in the mini program environment, with the following key technical points:
+
+* Asynchronous DOM acquisition mechanism (solving Feishu mini program issues)
+
+* Three-canvas rendering architecture (main canvas, interactive canvas, auxiliary canvas)
+
+* Event delegation and redirection
+
+* Environment-specific configuration
+
+### Web Chart Component
+
+`components/web-chart/index.tsx` is the rendering component for the browser environment, with the main differences from the mini program component:
+
+* Single container rendering (vs. three-canvas structure)
+
+* Synchronous DOM acquisition (vs. asynchronous loop attempts)
+
+* Direct event binding (vs. event delegation)
+
+## Chart Control Layer
+
+`utils/tt-canvas/index.ts` is the controller for chart instances, TTCanvas is responsible for managing VChart instances, receiving props passed by GeneralChart, and achieving seamless integration of chart capabilities in the mini program ecosystem through abstract general interfaces.
+
+
+
+The core responsibilities of TTCanvas:
+
+* Lifecycle management (creation, rendering, updating, releasing)
+
+* Cross-end parameter bridging (converting mini program parameters to VChart usable format)
+
+* Event system adaptation (binding custom events)
+
+* Rendering strategy control (environment-specific configuration)
+
+
+
+
+
+
+ # This document was revised and organized by the following person
+ [玄魂](https://github.com/xuanhun)
\ No newline at end of file
diff --git a/docs/assets/contributing/en/sourcecode/14.3.1-lark-vchart-introduction.md b/docs/assets/contributing/en/sourcecode/14.3.1-lark-vchart-introduction.md
new file mode 100644
index 0000000000..db70c747fa
--- /dev/null
+++ b/docs/assets/contributing/en/sourcecode/14.3.1-lark-vchart-introduction.md
@@ -0,0 +1,39 @@
+---
+title: 14.3.1 Lark-VChart 简介
+
+key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM
+---
+## 概览
+
+lark-vchart 是 VChart 的 Lark 小程序封装版本,提供了在飞书小程序环境下的 VChart 封装。
+
+* 关于更多飞书小程序的宿主环境介绍,请参见官方文档:https://open.feishu.cn/document/client-docs/gadget/introduction/host-environment
+
+* Lark-vchart 包的使用示例请参见文档:https://github.com/VisActor/lark-vchart-example
+
+
+
+## 核心代码结构
+
+Lark-vchart 包的核心实现包含两个部分:
+
+* Lark 环境相关适配:Lark 环境的适配逻辑包含必要的实现代码及声明,其内容存放于 `packages/lark-vchart/src` 中;
+
+* VChart 产物:vchart 图表库相关的能力直接引用了 VChart 的打包产物,其内容存放于 `packages/lark-vchart/src/vchart/index.js` 中。
+
+
+
+在接下来的章节,我们将详细的分析Lark-VChart组件的封装。
+
+
+
+
+
+
+
+
+
+
+
+ # 本文档由以下人员修正整理
+ [玄魂](https://github.com/xuanhun)
\ No newline at end of file
diff --git a/docs/assets/contributing/en/sourcecode/14.3.2-lark-vchart-source-code-analysis.md b/docs/assets/contributing/en/sourcecode/14.3.2-lark-vchart-source-code-analysis.md
new file mode 100644
index 0000000000..d25465e177
--- /dev/null
+++ b/docs/assets/contributing/en/sourcecode/14.3.2-lark-vchart-source-code-analysis.md
@@ -0,0 +1,55 @@
+---
+title: 14.3.2 Lark-VChart Source Code Explanation
+
+key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM
+---
+
+
+## Compatibility with Host Environment
+
+Feishu gadgets provide the ability to create custom components (https://open.feishu.cn/document/client-docs/gadget/component-component/custom-components/custom-components), each custom gadget includes several parts:
+
+* index.js: Component registration logic
+
+* index.json: Component declaration
+
+* index.ttml: Component template content
+
+* index.ttss: Component style
+
+
+
+### Component Declaration
+
+To ensure the VChart capability in the Feishu environment, Lark VChart's custom components declare three canvases:
+
+* Render canvas: Used to render VChart chart content;
+
+* Hit canvas: Although called Hit Canvas, VChart no longer uses an additional canvas for graphic picking. This canvas is mainly used for additional canvas operations. For example, pixel matching logic in the word cloud layout algorithm and texture rendering logic need to be performed in an additional canvas;
+
+* Tooltip canvas: Used to render additional tooltip content, separating Render canvas and Tooltip canvas to avoid redrawing the entire canvas.
+
+
+
+### Component Registration
+
+Component registration includes properties and necessary lifecycle.
+
+**Component Properties:**
+
+* spec: Same as VChart's spec configuration, but an observer is added in the registration to monitor changes in the chart spec. When the spec is updated, vchart.updateSpec() will be automatically called;
+
+* options: Same as VChart's options configuration;
+
+* events: Same as VChart's registered events, vchart.on will be called during chart initialization to listen to corresponding events.
+
+**Component Methods:**
+
+* init: The core of VChart rendering requires the Canvas. In the init function, Lark VChart will find the corresponding canvas component and initialize the VChart instance to execute the rendering process. The rendering process is the same as a regular VChart example;
+
+* bindEvent: Bind events and filter out potentially duplicate PC & mobile events in the Feishu environment.
+
+
+
+ # This document was revised and organized by the following personnel
+ [Xuanhun](https://github.com/xuanhun)
\ No newline at end of file
diff --git a/docs/assets/contributing/en/sourcecode/14.4.1-tt-vchart-introduction.md b/docs/assets/contributing/en/sourcecode/14.4.1-tt-vchart-introduction.md
new file mode 100644
index 0000000000..dd0939f212
--- /dev/null
+++ b/docs/assets/contributing/en/sourcecode/14.4.1-tt-vchart-introduction.md
@@ -0,0 +1,35 @@
+---
+title: 14.4.1 TT-VChart Introduction
+
+key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM
+---
+## Overview
+
+TT-vchart is the Douyin mini program encapsulated version of VChart, providing VChart encapsulation in the Feishu mini program environment.
+
+* For more information about the host environment of Byte mini programs, please refer to the official documentation: https://developer.open-douyin.com/docs/resource/zh-CN/mini-app/develop/tutorial/custom-component/custom-component
+
+
+
+## Core Code Structure
+
+The core implementation of the TT-vchart package consists of two parts:
+
+* Douyin mini program environment adaptation: The adaptation logic for the Douyin mini program environment includes necessary implementation code and declarations, which are stored in `packages/tt-vchart/src`;
+
+* VChart products: The capabilities related to the vchart chart library directly reference the packaged products of VChart, which are stored in `packages/tt-vchart/src/vchart/index.js`.
+
+
+
+In the following chapters, we will analyze the encapsulation of the TT-VChart component in detail.
+
+
+
+
+
+
+
+
+
+ # This document was revised and organized by the following personnel
+ [Xuanhun](https://github.com/xuanhun)
\ No newline at end of file
diff --git a/docs/assets/contributing/en/sourcecode/14.4.2-tt-vchart-source-code-analysis.md b/docs/assets/contributing/en/sourcecode/14.4.2-tt-vchart-source-code-analysis.md
new file mode 100644
index 0000000000..5bc50b51ad
--- /dev/null
+++ b/docs/assets/contributing/en/sourcecode/14.4.2-tt-vchart-source-code-analysis.md
@@ -0,0 +1,55 @@
+---
+title: 14.4.2 TT-VChart Source Code Explanation
+
+key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM
+---
+
+
+## Compatibility with Host Environment
+
+Douyin widgets provide the ability to create custom components (https://developer.open-douyin.com/docs/resource/zh-CN/mini-app/develop/tutorial/custom-component/custom-component). Each custom widget includes several parts:
+
+* index.js: Component registration logic
+
+* index.json: Component declaration
+
+* index.ttml: Component template content
+
+* index.ttss: Component style
+
+
+
+### Component Declaration
+
+To ensure VChart capabilities in the Douyin environment, the TT VChart custom component declares three canvases:
+
+* Render canvas: Used to render VChart chart content;
+
+* Hit canvas: Although called Hit Canvas, VChart no longer uses an additional canvas for graphic picking. This canvas is mainly used for additional canvas operations. For example, pixel matching logic in the word cloud layout algorithm and texture rendering logic need to be performed on an additional canvas;
+
+* Tooltip canvas: Used to render additional tooltip content, separating Render canvas and Tooltip canvas to avoid redrawing the entire canvas.
+
+
+
+### Component Registration
+
+Component registration includes properties and necessary lifecycle.
+
+**Component Properties:**
+
+* spec: Same as VChart's spec configuration, but an observer is added in the registration to monitor changes in the chart spec. When the spec is updated, vchart.updateSpec() will be automatically called;
+
+* options: Same as VChart's options configuration;
+
+* events: Same as VChart's registered events, vchart.on will be called during chart initialization to listen for corresponding events.
+
+**Component Methods:**
+
+* init: The core of VChart rendering requires a Canvas. In the init function, tt vchart will find the corresponding canvas component and initialize the VChart instance to execute the rendering process. The rendering process is the same as a regular VChart example;
+
+* bindEvent: Bind events and filter out potentially duplicate PC & mobile events in the Douyin environment.
+
+
+
+ # This document was revised and organized by the following personnel
+ [Xuanhun](https://github.com/xuanhun)
\ No newline at end of file
diff --git a/docs/assets/contributing/en/sourcecode/14.5.1-wx-vchart-introduction.md b/docs/assets/contributing/en/sourcecode/14.5.1-wx-vchart-introduction.md
new file mode 100644
index 0000000000..f3fa133fbc
--- /dev/null
+++ b/docs/assets/contributing/en/sourcecode/14.5.1-wx-vchart-introduction.md
@@ -0,0 +1,33 @@
+---
+title: 14.5.1 WX-VChart Introduction
+
+key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM
+---
+## Overview
+
+wx-vchart is the WeChat Mini Program encapsulation version of VChart, providing VChart encapsulation in the WeChat Mini Program environment.
+
+* For more introduction to the host environment of WeChat Mini Programs, please refer to the official documentation: https://developers.weixin.qq.com/miniprogram/dev/framework/
+
+
+
+## Core Code Structure
+
+The core implementation of the wx-vchart package consists of two parts:
+
+* WeChat Mini Program environment adaptation: The adaptation logic for the WeChat Mini Program environment includes necessary implementation code and declarations, which are stored in `packages/wx-vchart/miniprogram`;
+
+* VChart product: The capabilities related to the vchart chart library directly reference the packaged product of VChart, which is stored in `packages/wx-vchart/miniprogram/src/vchart/index.js`.
+
+
+
+In the following chapters, we will analyze the encapsulation of the WX-VChart component in detail.
+
+
+
+
+
+
+
+ # This document was revised and organized by the following personnel
+ [Xuanhun](https://github.com/xuanhun)
\ No newline at end of file
diff --git a/docs/assets/contributing/en/sourcecode/14.5.2-wx-vchart-source-code-analysis.md b/docs/assets/contributing/en/sourcecode/14.5.2-wx-vchart-source-code-analysis.md
new file mode 100644
index 0000000000..02aacad958
--- /dev/null
+++ b/docs/assets/contributing/en/sourcecode/14.5.2-wx-vchart-source-code-analysis.md
@@ -0,0 +1,53 @@
+---
+title: 14.5.2 WX-VChart Source Code Explanation
+
+key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM
+---
+## Compatibility with Host Environment
+
+WeChat mini-programs provide the ability to create custom components (https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/), a custom component consists of four files: `json` `wxml` `wxss` `js`:
+
+* index.js: Component registration logic
+
+* index.json: Component declaration
+
+* index.wxml: Component template content
+
+* index.wxss: Component style
+
+
+
+### Component Declaration
+
+To ensure the VChart capability in the WeChat environment, the WX VChart custom component declares three canvases:
+
+* Render canvas: Used to render VChart chart content;
+
+* Hit canvas: Although called Hit Canvas, VChart no longer uses an additional canvas for graphic picking. This canvas is mainly used for executing additional canvas operations. For example, pixel matching logic in the word cloud layout algorithm and texture rendering logic need to be performed on an additional canvas;
+
+* Tooltip canvas: Used to render additional tooltip content, separating Render canvas and Tooltip canvas to avoid redrawing the entire canvas.
+
+
+
+### Component Registration
+
+Component registration includes properties and necessary lifecycle.
+
+**Component Properties:**
+
+* spec: Same as VChart's spec configuration, but an observer is added in the registration to monitor changes in the chart spec. When the spec is updated, vchart.updateSpec() will be automatically called;
+
+* options: Same as VChart's options configuration;
+
+* events: Same as VChart's registered events, vchart.on will be called during chart initialization to listen to corresponding events.
+
+**Component Methods:**
+
+* init: The core of VChart rendering requires the Canvas, in the init function, wx vchart will find the corresponding canvas component and initialize the VChart instance to execute the rendering process. The rendering process is the same as a regular VChart example;
+
+* bindEvent: Bind events and filter out potentially duplicate PC & mobile events in the WeChat environment.
+
+
+
+ # This document was revised and organized by the following personnel
+ [Xuanhun](https://github.com/xuanhun)
\ No newline at end of file
diff --git a/docs/assets/contributing/en/sourcecode/14.6.1-openinula-vchart-introduction.md b/docs/assets/contributing/en/sourcecode/14.6.1-openinula-vchart-introduction.md
new file mode 100644
index 0000000000..804495283d
--- /dev/null
+++ b/docs/assets/contributing/en/sourcecode/14.6.1-openinula-vchart-introduction.md
@@ -0,0 +1,109 @@
+---
+title: 14.6.1 Introduction to Openinula-VChart
+
+key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM
+---
+# I. Component Introduction
+
+`@visactor/openinula-vchart` is a packaged version of the [VChart](https://visactor.io/vchart) chart library provided by [VisActor](https://visactor.io/) for [Openinula](https://openinula.net/). It offers a series of easy-to-use [Openinula](https://openinula.net/) components for conveniently creating various types of charts in the [Openinula](https://openinula.net/) development environment, including line charts, bar charts, pie charts, etc. The components of `@visactor/openinula-vchart` are highly customizable and extensible, allowing different chart effects to be achieved by passing different parameters and configurations.
+
+# II. **Component Overview**
+
+**openinula-vchart** provides two styles of components:
+
+1. **Unified entry components,** such as: `` and ``
+
+1. **Semantic chart components, including:**
+
+1. Charts, such as: `` `` etc.
+
+1. Series, such as `` `` etc.
+
+1. Controls, such as `` `` etc.
+
+
+
+Features
+
+
+``
+
+
+``
+
+
+Semantic components
+
+
+Configuration method
+
+
+Full spec
+
+
+Full spec, but only supports some charts
+
+
+Componentized declaration
+
+
+Extensibility
+
+
+High
+
+
+High
+
+
+Medium
+
+
+Development experience
+
+
+Configuration-driven
+
+
+Configuration-driven
+
+
+Declarative development
+
+# III. Usage Examples
+
+### Unified Entry Mode
+
+
+```xml
+import { VChart } from '@visactor/openinula-vchart';
+
+const spec = {
+ type: 'bar',
+ data: [{ values: [...] }]
+};
+
+export default () => ;
+
+```
+### Declarative Pattern
+
+
+```xml
+import { LineChart, Line, Axis, Legend } from '@visactor/openinula-vchart';
+
+export default () => (
+
+
+
+
+
+);
+
+```
+
+
+
+
+ # This document was revised and organized by the following person
+ [玄魂](https://github.com/xuanhun)
\ No newline at end of file
diff --git a/docs/assets/contributing/en/sourcecode/14.6.2-openinula-vchart-source-code-analysis.md b/docs/assets/contributing/en/sourcecode/14.6.2-openinula-vchart-source-code-analysis.md
new file mode 100644
index 0000000000..cc1cc63dda
--- /dev/null
+++ b/docs/assets/contributing/en/sourcecode/14.6.2-openinula-vchart-source-code-analysis.md
@@ -0,0 +1,699 @@
+---
+title: 14.6.2 Openinula-VChart Source Code Explanation
+
+key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM
+---
+# 1. Core Mechanism
+
+As mentioned earlier, openinula-vchart provides two ways to declare components.
+
+1. **Unified entry components,** such as: `` and ``
+
+1. **Semantic chart components, including:**
+
+1. Charts, such as: `` `` etc.
+
+1. Series, such as `` `` etc.
+
+1. Controls, such as `` `` etc.
+
+
+
+The following diagram shows the implementation mechanism of openinula-vchart:
+
+
+
+
+
+
+Next, let's introduce the specific implementation of different modules:
+
+# II. Chart
+
+
+
+
+## Component Entry
+
+> packages/openinula-vchart/src/VChart.tsx
+> packages/openinula-vchart/src/VChartSimple.tsx
+> packages/openinula-vchart/src/charts
+
+Whether it is a unified entry component or a semantic component, it will go into the `createChart` logic. createChart creates different charts based on different parameters.
+
+Take `` as an example, this component does only one thing, which is createChart:
+
+```Typescript
+import { BaseChartProps, createChart } from './charts/BaseChart';
+import VChartCore from '@visactor/vchart';
+export { VChartCore };
+
+// 定义 VChart 组件属性,排除基础图表中不需要的 props
+export type VChartProps = Omit;
+
+// 创建 VChart 组件实例
+export const VChart = createChart('VChart', {
+ vchartConstrouctor: VChartCore // 构造器: VChart 核心库
+});
+
+```
+
+
+## Create Chart Container
+
+> packages/openinula-vchart/src/charts/BaseChart.tsx
+
+```Typescript
+export const createChart = (
+ componentName: string, // 组件名称, 用于配置class等
+ defaultProps?: Partial, // 组件属性,用于创建vchart实例、解析spec、挂载event等
+ callback?: (props: T, defaultProps?: Partial) => T // 回调,用于处理props
+) => {
+ // 基于BaseChart封装容器,并设置css属性、挂在ref等
+ const Com = withContainer(BaseChart as any, componentName, (props: T) => {
+ // 自定义属性处理
+ if (callback) {
+ return callback(props, defaultProps);
+ }
+
+ // 如果有默认属性,则将组件属性与默认属性合并
+ if (defaultProps) {
+ return Object.assign(props, defaultProps);
+ }
+
+ // 直接返回属性
+ return props;
+ });
+ // 设置组件识别标志
+ Com.displayName = componentName;
+ return Com;
+};
+
+```
+This step mainly involves the following based on the passed component name, component properties, and callbacks:
+
+1. Container encapsulation: Encapsulated based on `**BaseChart**`, during which CSS properties are set, refs are mounted, etc.
+
+1. Props handling: If there are custom property handling or default properties, perform custom handling or merge default properties
+
+1. displayName: Set the component identification flag for React debugging
+
+
+
+## BaseChart Chart Base Class
+
+> packages/openinula-vchart/src/charts/BaseChart.tsx
+
+### State Management
+
+
+```Typescript
+// 状态管理
+const [updateId, setUpdateId] = useState(0); // 图表更新计数器
+const chartContext = useRef({}); // 图表上下文引用
+useImperativeHandle(ref, () => chartContext.current?.chart); // 对外暴露图表实例
+const hasSpec = !!props.spec; // 是否存在全量 spec 配置
+
+// 视图与生命周期
+const [view, setView] = useState(null); // 底层 VGrammar 视图实例
+const isUnmount = useRef(false); // 组件卸载标记
+
+// 配置缓存
+const prevSpec = useRef(pickWithout(props, notSpecKeys)); // 过滤非 spec 属性后的配置
+const specFromChildren = useRef>(null); // 子组件生成的 spec
+
+// 事件系统
+const eventsBinded = React.useRef(null); // 已绑定的事件属性缓存
+
+// 性能优化
+const skipFunctionDiff = !!props.skipFunctionDiff; // 是否跳过函数对比
+
+// tooltip节点
+const [tooltipNode, setTooltipNode] = useState(null); // 自定义 tooltip 节点
+
+```
+Two core designs:
+
+1. Differential comparison optimization: Achieve precise configuration change detection through prevSpec and pickWithout
+
+2. Dual update mode: Distinguish between full spec updates and declarative component updates based on the hasSpec variable
+
+### Subcomponent spec analysis
+
+
+```Typescript
+const parseSpecFromChildren = (props: Props) => {
+ // 初始化空 spec 对象(排除 type/data/width/height 字段)
+ const specFromChildren: Omit = {};
+
+ // 将子组件转换为数组并遍历
+ toArray(props.children).map((child, index) => {
+ // 获取子组件的 parseSpec 方法(需组件实现)
+ const parseSpec = child && (child as any).type && (child as any).type.parseSpec;
+
+ if (parseSpec && (child as any).props) {
+ // 生成子组件 props:自动添加 componentId
+ const childProps = isNil((child as any).props.componentId)
+ ? {
+ ...(child as any).props,
+ componentId: getComponentId(child, index) // 生成唯一组件ID
+ }
+ : (child as any).props;
+
+ // 调用子组件的规范解析方法
+ const specResult = parseSpec(childProps);
+
+ // 合并解析结果到总 spec
+ if (specResult.isSingle) {
+ // 单例模式(如标题组件)
+ specFromChildren[specResult.specName] = specResult.spec;
+ } else {
+ // 多例模式(如多个数据标记)
+ if (!specFromChildren[specResult.specName]) {
+ specFromChildren[specResult.specName] = [];
+ }
+ specFromChildren[specResult.specName].push(specResult.spec);
+ }
+ }
+ });
+
+ return specFromChildren;
+};
+
+```
+The main task of this module is to parse the spec from subcomponents and mount it onto specFromChildren. Due to different component configuration modes, some are singleton and some are multiple instances, so the parsing logic is slightly different.
+
+Key content of this module:
+
+1. **Declarative Component Transformation:**
+
+Transform JSX declarations like this:
+
+```javascript
+
+
+
+
+
+```
+Convert to VChart standard JSON spec:
+
+```json
+{
+ "mark": [{ "type": "point" }],
+ "axes": [{ "orient": "bottom" }]
+}
+
+```
+1. **Component Unique Identifier:**
+
+The ID generated by getComponentId is structured as ComponentType-Index (e.g., `Mark-0`), used for:
+
+* Precise component update tracking
+
+* Avoiding duplicate component conflicts
+
+* Component identification during debugging
+
+3. **Dual-mode spec merge strategy:**
+
+
+
+**Typical Subcomponent Implementation**
+
+Take the Marker component as an example:
+
+```xml
+// 实现 parseSpec 方法
+class MarkPoint extends BaseComponent {
+ static parseSpec(props: MarkProps) {
+ return {
+ specName: 'markPoint', // 对应 spec 中的字段名
+ isSingle: false, // 允许多个 MarkPoint 组件
+ spec: {
+ type: props.type,
+ style: props.style
+ }
+ };
+ }
+}
+
+```
+### Create Chart
+
+
+```xml
+const createChart = (props: Props) => {
+ // 1. 实例化图表(利用传入的图表构造器)
+ const cs = new props.vchartConstrouctor(
+ parseSpec(props), // 合并后的图表spec
+ {
+ ...props.options, // 透传图表配置
+ onError: props.onError, // 异常处理回调
+ autoFit: true, // 开启自动尺寸适配
+ dom: props.container // 绑定 DOM 容器
+ }
+ );
+
+ // 2. 更新上下文引用
+ chartContext.current = { ...chartContext.current, chart: cs };
+
+ // 3. 重置卸载标记
+ isUnmount.current = false;
+};
+
+```
+#### spec analysis
+
+
+```Typescript
+const parseSpec = (props: Props) => {
+ // 决策逻辑:优先使用全量 spec 配置
+ let spec: ISpec = undefined;
+
+ // 全量 spec 模式(直接使用传入的 spec)
+ if (hasSpec && props.spec) {
+ spec = props.spec;
+ }
+ // 声明式组件模式(合并 props 和子组件生成的 spec)
+ else {
+ spec = {
+ ...prevSpec.current, // 来自组件 props 的配置
+ ...specFromChildren.current // 来自子组件解析的配置
+ } as ISpec;
+ }
+
+ // 自定义 tooltip 处理(React 组件与 VChart 的桥接)
+ const tooltipSpec = initCustomTooltip(setTooltipNode, props, spec.tooltip);
+ if (tooltipSpec) {
+ spec.tooltip = tooltipSpec; // 覆盖默认 tooltip 配置
+ }
+
+ return spec;
+};
+
+```
+### Render Charts
+
+
+```xml
+ const renderChart = () => {
+ if (chartContext.current.chart) {
+ chartContext.current.chart.renderSync({
+ reuse: false
+ });
+ handleChartRender();
+ }
+ };
+
+```
+Get the mounted instance through the chartContext and call the instance's `renderSync` method to render the chart.
+
+### Event Binding & Context Update
+
+```Typescript
+const handleChartRender = () => {
+ // 1. 安全检查:确保组件未卸载且图表实例存在
+ if (!isUnmount.current) {
+ if (!chartContext.current || !chartContext.current.chart) {
+ return;
+ }
+
+ // 2. 事件系统:重新绑定所有图表事件
+ bindEventsToChart(chartContext.current.chart, props, eventsBinded.current, CHART_EVENTS);
+
+ // 3. 获取底层视图实例
+ const newView = chartContext.current.chart.getCompiler().getVGrammarView();
+
+ // 4. 状态更新:触发子组件重渲染
+ setUpdateId(updateId + 1);
+
+ // 5. 生命周期回调:通知父组件渲染完成
+ if (props.onReady) {
+ props.onReady(chartContext.current.chart, updateId === 0); // 区分首次渲染
+ }
+
+ // 6. 更新视图上下文
+ setView(newView);
+ }
+};
+
+```
+This section mainly executes the processing logic after the chart rendering is completed, mainly implementing:
+
+1. Event Update:
+
+Dynamic update of event listeners is achieved through `bindEventsToChart`, using a differential comparison strategy to avoid duplicate bindings.
+
+It is particularly important to remount events after the chart is re-rendered (such as data updates) to ensure the correctness of interactive responses.
+
+1. Bidirectional State Synchronization
+
+Trigger child component updates through setUpdateId (using the key value change mechanism), while storing the VGrammar view instance in the React context to achieve state synchronization between the Canvas layer and the React component layer. The judgment of updateId === 0 distinguishes the first rendering.
+
+1. Lifecycle Notification
+
+Achieve parent-child communication in a layered architecture through the onReady callback. After the underlying chart completes the rendering pipeline (layout, drawing, animation), notify the business layer to perform subsequent operations (such as data fetching, associated interactions, etc.).
+
+# Three, Series
+
+
+
+
+
+
+## Event Binding
+
+
+```Typescript
+const addMarkEvent = (events: EventsProps) => {
+ // 1. 安全校验:确保事件对象和图表实例存在
+ if (!events || !context.chart) {
+ return;
+ }
+
+ // 2. 清理旧事件:遍历解除所有已绑定的事件监听
+ if (bindedEvents.current) {
+ Object.keys(bindedEvents.current).forEach(eventKey => {
+ context.chart.off(REACT_TO_VCHART_EVENTS[eventKey], bindedEvents.current[eventKey]);
+ bindedEvents.current[eventKey] = null; // 清除引用
+ });
+ }
+
+ // 3. 绑定新事件:动态建立 React 事件到 VChart 的映射关系
+ events &&
+ Object.keys(events).forEach(eventKey => {
+ if (!bindedEvents.current?.[eventKey]) {
+ // 通过事件类型映射表转换事件名
+ context.chart.on(REACT_TO_VCHART_EVENTS[eventKey], handleEvent);
+
+ // 更新绑定记录
+ if (!bindedEvents.current) {
+ bindedEvents.current = {};
+ }
+ bindedEvents.current[eventKey] = handleEvent;
+ }
+ });
+};
+
+```
+1. Input Check: The function receives events as a parameter. If events is empty or context.chart does not exist, the function will return immediately without further operations.
+
+1. Unbind Old Events:
+
+If bindedEvents.current exists, it means events have been bound before. At this point, each event in bindedEvents.current will be iterated over, and these events will be unbound using the context.chart.off method, setting the value of the corresponding event key in bindedEvents.current to null.
+
+1. Bind New Events:
+
+If events exist, each event in events will be iterated over.
+
+For events that do not exist in bindedEvents.current, i.e., the event context, the handleEvent will be bound to the corresponding event using the context.chart.on method, and the context will be updated.
+
+## Event Clearing
+
+```xml
+const removeMarkEvent = () => {
+ addMarkEvent({});
+};
+
+```
+When the component is uninstalled, the events will be cleared
+
+## spec analysis
+
+```Typescript
+ (Comp as any).parseSpec = (compProps: T & { updateId?: number; componentId?: string }) => {
+ // 从组件属性中移除不需要的键,生成新的系列规范
+ const newSeriesSpec = pickWithout(compProps, notSpecKeys);
+
+ // 为每个标记添加默认的 ID
+ addMarkId(newSeriesSpec, compProps.id ?? compProps.componentId);
+
+ // 如果提供了 type 参数,则将其添加到spec中
+ if (!isNil(type)) {
+ (newSeriesSpec as any).type = type;
+ }
+
+ // 返回包含系列规范和规范名称的对象
+ return {
+ spec: newSeriesSpec,
+ specName: 'series'
+ };
+ };
+
+```
+series is a declarative component, and parseSpec will be called by the parent component to parse and add it to the overall spec.
+
+In series, the main functions of `parseSpec` are:
+
+1. Filter out unnecessary attributes to generate a new series specification.
+
+2. Add a default ID for each mark.
+
+3. If a type parameter is provided, add it to the series specification.
+
+4. Return an object containing the series specification and specification name.
+
+# Four, Component
+
+
+
+
+## Event Binding
+
+```Typescript
+// 检查是否需要更新(通过 updateId 变化检测)
+if (props.updateId !== updateId.current) {
+ // 更新当前记录的版本号,保持与父组件同步
+ updateId.current = props.updateId;
+
+ // 重新绑定图表事件(仅当组件支持事件时执行)
+ const hasPrevEventsBinded = supportedEvents
+ ? bindEventsToChart( // 调用事件绑定工具方法
+ context.chart, // 从上下文获取图表实例
+ props, // 当前组件属性(含新事件处理器)
+ eventsBinded.current, // 之前绑定的事件缓存
+ supportedEvents // 该组件支持的事件类型映射
+ )
+ : false;
+
+ // 如果事件绑定成功,更新事件缓存引用
+ if (hasPrevEventsBinded) {
+ eventsBinded.current = props; // 保存当前事件配置用于下次差异比较
+ }
+}
+
+```
+* Update Detection:
+
+Determine whether the component needs to be updated by checking if props.updateId !== updateId.current. The updateId is an update identifier from the parent component (usually a chart) used to trigger the update process of the child component.
+
+* Event Rebinding
+
+When an update is detected, call the bindEventsToChart method to rebind events. Here, a conditional check is used:
+
+* If the component supports events (supportedEvents exists), perform event binding
+
+* After successful binding, update the eventsBinded cache to record the currently bound event properties
+
+* State Synchronization - Update updateId.current to the latest value to ensure the accuracy of subsequent update detections.
+
+## spec Parsing
+
+```Typescript
+ (Comp as any).parseSpec = (props: T & { updateId?: number; componentId?: string }) => {
+ // 使用 pickWithout 函数从 props 中移除 notSpecKeys 中指定的键,得到新的组件配置
+ const newComponentSpec: Partial = pickWithout(props, notSpecKeys);
+
+ // 返回一个包含新组件配置、specName 和 isSingle 的对象
+ return {
+ spec: newComponentSpec,
+ specName,
+ isSingle
+ };
+ };
+
+```
+* specName is used to determine the mounted specKey
+
+* isSingle flag is used by the parent component to determine if it is a singleton when parsing the spec
+
+# Five, Event Handling
+
+> packages/openinula-vchart/src/eventsUtils.ts
+
+
+
+## Event Extraction
+
+```Typescript
+// 泛型方法:从组件属性中提取有效事件配置
+export const findEventProps = (
+ props: T, // 组件属性集合
+ supportedEvents: Record = REACT_TO_VCHART_EVENTS // 允许的事件映射表
+): EventsProps => {
+ const result: EventsProps = {}; // 存储过滤后的事件配置
+
+ // 遍历所有属性键
+ Object.keys(props).forEach(key => {
+ // 双重校验:1. 是否为支持的事件类型 2. 是否存在有效回调函数
+ if (supportedEvents[key] && props[key]) {
+ result[key] = props[key]; // 收集符合条件的事件处理器
+ }
+ });
+
+ return result; // 返回纯净的事件配置对象
+};
+
+```
+## Binding Events
+
+
+```Typescript
+export const bindEventsToChart = (
+ chart: IVChart, // 图表实例
+ newProps?: T | null, // 新事件属性
+ prevProps?: T | null, // 旧事件属性
+ supportedEvents: Record = REACT_TO_VCHART_EVENTS // 事件映射表
+) => {
+ // 安全检查:排除无效调用
+ if ((!newProps && !prevProps) || !chart) {
+ return false;
+ }
+
+ // 新旧事件属性过滤(通过之前分析的 findEventProps 方法)
+ const prevEventProps = prevProps ? findEventProps(prevProps, supportedEvents) : null;
+ const newEventProps = newProps ? findEventProps(newProps, supportedEvents) : null;
+
+ // 解绑阶段:清理过期事件监听
+ if (prevEventProps) {
+ Object.keys(prevEventProps).forEach(eventKey => {
+ // 差异判断:新属性不存在该事件 或 事件处理器发生变化
+ if (!newEventProps || !newEventProps[eventKey] || newEventProps[eventKey] !== prevEventProps[eventKey]) {
+ chart.off(supportedEvents[eventKey], prevProps[eventKey]); // 解除旧监听
+ }
+ });
+ }
+
+ // 绑定阶段:注册新事件监听
+ if (newEventProps) {
+ Object.keys(newEventProps).forEach(eventKey => {
+ // 差异判断:旧属性不存在该事件 或 事件处理器发生变化
+ if (!prevEventProps || !prevEventProps[eventKey] || prevEventProps[eventKey] !== newEventProps[eventKey]) {
+ chart.on(supportedEvents[eventKey], newEventProps[eventKey]); // 注册新监听
+ }
+ });
+ }
+
+ return true; // 标识操作完成
+};
+
+```
+
+
+# Six, Global Communication
+
+> packages/openinula-vchart/src/context
+
+
+
+## chartContext
+
+
+```Typescript
+export function withChartInstance(Component: typeof React.Component) {
+ // 1. 创建转发引用组件
+ const Com = React.forwardRef((props: T, ref) => {
+ // 2. 消费图表上下文
+ return (
+
+ {(ctx: ChartContextType) =>
+ // 3. 注入图表实例到被包裹组件
+
+ }
+
+ );
+ });
+
+ // 增强调试信息
+ Com.displayName = Component.name;
+ return Com;
+}
+
+```
+This context is mainly used to share the VChart instance:
+
+Use ChartContext.Consumer to obtain the chart instance from the context and inject it into the target component as a prop, allowing the wrapped component to directly access this.props.chart to obtain the chart instance.
+
+## viewContext
+
+
+```xml
+export function withView(Component: typeof React.Component) {
+ // 1. 创建带ref转发的组件
+ const Com = React.forwardRef((props: T, ref) => {
+ // 2. 消费视图上下文
+ return (
+
+ {/* 3. 注入视图实例到被包裹组件 */}
+ {ctx =>
+
+ }
+
+ );
+ });
+
+ // 增强调试信息
+ Com.displayName = Component.name;
+ return Com;
+}
+
+```
+This context is mainly used to share the VGrammar instance:
+
+Obtain the VGrammar view instance passed from `ViewContext.Provider` through `ViewContext.Consumer`.
+
+## stageContext
+
+
+```Typescript
+export function withStage(Component: typeof React.Component) {
+ // 1. 创建支持ref转发的组件包装器
+ const Com = React.forwardRef((props: T, ref) => {
+ // 2. 消费stage上下文
+ return (
+
+ {/* 3. 将stage实例注入被包装组件 */}
+ {ctx =>
+
+ }
+
+ );
+ });
+
+ // 4. 保留原始组件名称便于调试
+ Com.displayName = Component.name;
+ return Com;
+}
+
+```
+This context is mainly used to share the VRender instance:
+
+Obtain the VRender view instance passed from `StageContext.Provider` through `StageContext.Consumer`.
+
+
+
+# This document was revised and organized by
+[玄魂](https://github.com/xuanhun)
\ No newline at end of file
diff --git a/docs/assets/contributing/en/sourcecode/14.7.1-harmony-vchart-introduction.md b/docs/assets/contributing/en/sourcecode/14.7.1-harmony-vchart-introduction.md
new file mode 100644
index 0000000000..29b1bb2618
--- /dev/null
+++ b/docs/assets/contributing/en/sourcecode/14.7.1-harmony-vchart-introduction.md
@@ -0,0 +1,31 @@
+---
+title: 14.7.1 Harmony-VChart Introduction
+
+key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM
+---
+## Overview
+
+harmony-vchart is the HarmonyOS encapsulated version of VChart, providing a version of VChart encapsulated for the HarmonyOS environment.
+
+* For more information about the HarmonyOS environment, please refer to the official documentation: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/application-dev-guide
+
+## Core Code Structure
+
+The core implementation of the harmony-vchart package consists of two parts:
+
+* Harmony environment-related adaptation:
+
+* The component encapsulation logic for the Harmony environment is located in the `packages/harmony_vchart/library/src/main/ets/ChartComponent.ets` directory, which includes components encapsulated based on the Harmony environment.
+
+* Event compatibility logic is in the `packages/harmony_vchart/library/src/main/ets/event.ets` directory.
+
+* Animation Ticker logic is in the `packages/harmony_vchart/library/src/main/ets/ticker.ets` directory.
+
+* VChart products: The capabilities related to the vchart chart library directly reference the packaged products of VChart, and their content is stored in `packages/harmony_vchart/library/src/main/ets/index-harmony.es.min.js`.
+
+
+
+In the following chapters, we will analyze the encapsulation of the Harmony-VChart component in detail.
+
+ # This document was revised and organized by the following personnel
+ [Xuanhun](https://github.com/xuanhun)
\ No newline at end of file
diff --git a/docs/assets/contributing/en/sourcecode/14.7.2-harmony-vchart-source-code-analysis.md b/docs/assets/contributing/en/sourcecode/14.7.2-harmony-vchart-source-code-analysis.md
new file mode 100644
index 0000000000..fbb24e6f42
--- /dev/null
+++ b/docs/assets/contributing/en/sourcecode/14.7.2-harmony-vchart-source-code-analysis.md
@@ -0,0 +1,69 @@
+---
+title: 14.7.2 Harmony-VChart Source Code Explanation
+
+key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM
+---
+## Compatibility with Host Environment
+
+The HarmonyOS provides the capability to create custom components, where the `@Component` decorator can only decorate data structures declared with the struct keyword. Once a struct is decorated with `@Component`, it gains the ability to be a component. Starting from API version 9, this decorator supports usage in ArkTS cards. (https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V14/arkts-create-custom-components-V14#component).
+
+
+
+### Component Declaration
+
+1. To ensure the VChart capability in the Harmony environment, the native Canvas in the Harmony environment has been encapsulated to provide the interface of the browser's Canvas2D.
+
+* The component encapsulation logic in the harmony environment is located in the `packages/harmony_vchart/library/src/main/ets/ChartComponent.ets` directory, which includes components encapsulated based on the harmony environment.
+
+1. The events of Harmony have been re-encapsulated to be compatible with the browser's event interface.
+
+
+```xml
+export class HTMLTouchEvent {
+ type: string = '';
+ touches: TouchItem[] = [];
+ changedTouches: TouchItem[] = [];
+ target: Object | null = null;
+
+ constructor(harmonyTouchEvent: TouchEvent) {
+ if (harmonyTouchEvent.type === TouchType.Down) {
+ this.type = 'touchstart';
+ } else if (harmonyTouchEvent.type === TouchType.Up || harmonyTouchEvent.type === TouchType.Cancel) {
+ this.type = 'touchend';
+ } else if (harmonyTouchEvent.type === TouchType.Move) {
+ this.type = 'touchmove';
+ }
+ this.touches = harmonyTouchEvent.touches.map(t => new TouchItem(t));
+ this.changedTouches = harmonyTouchEvent.touches.map(t => new TouchItem(t));
+ }
+}
+
+```
+* The event compatibility logic is located in the `packages/harmony_vchart/library/src/main/ets/event.ets` directory.
+
+1. Since there is no RequestAnimationFrame interface in the Harmony environment, a custom Ticker, HarmonyTickHandler, is implemented based on Harmony's own animation API.
+
+* The animation Ticker logic is located in the `packages/harmony_vchart/library/src/main/ets/ticker.ets` directory.
+
+
+
+### Component Registration
+
+The registration of components includes properties and necessary lifecycle declarations.
+
+**Component Properties:**
+
+* spec: Same as the spec configuration of VChart
+
+* initOption: Same as the initOption configuration of VChart;
+
+**Component Methods:**
+
+* onChartInitCb: Provides a callback for when initialization is complete
+
+* onChartReadyCb: Provides a callback for when the chart is ready to be drawn
+
+
+
+ # This document was revised and organized by the following personnel
+ [Xuanhun](https://github.com/xuanhun)
\ No newline at end of file
diff --git a/docs/assets/contributing/en/sourcecode/14.8.1-vchart-svg-plugin-introduction.md b/docs/assets/contributing/en/sourcecode/14.8.1-vchart-svg-plugin-introduction.md
new file mode 100644
index 0000000000..492a22d5d5
--- /dev/null
+++ b/docs/assets/contributing/en/sourcecode/14.8.1-vchart-svg-plugin-introduction.md
@@ -0,0 +1,53 @@
+---
+title: 14.8.1 vchart-svg-plugin Introduction
+
+key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM
+---
+## Overview
+
+vchart-svg-plugin is a plugin that converts vchart rendering content into an SVG string, mainly used for printing, server-side rendering, and other scenarios;
+
+
+
+## Basic Principles
+
+Before reading the specific code, we first need to know some implementation principles of vchart. Vchart is rendered based on canvas and relies on the canvas rendering engine library @visactor/vrender at the bottom layer. Vrender generates a graphic scene tree stage based on the chart configuration of vchart:
+
+
+
+The relationship of graphics-related classes in vrender is as follows:
+
+
+
+In other words, through the `vchart` instance, we can obtain the root node `stage` of the scene tree. By recursively traversing the child nodes of `stage`, we can get all the rendered graphics. In the implementation of vrender, all graphics have an `attribute` property to maintain the display configuration of the graphics. Therefore, the task is broken down into two parts:
+
+* Construct the child nodes of the svg based on the child nodes of `stage`
+
+* Convert the `attribute` of vrender graphic elements into the corresponding attributes of svg nodes
+
+## Core File Structure
+
+```plaintext
+src/svg/
+├── convert.ts - 转换入口,处理图表到SVG的转换
+├── graphic.ts - 图形元素转换的核心实现
+├── util.ts - 通用工具函数集合
+├── pattern.ts - 纹理属性转换
+├── shadow.ts - shadow属性转换
+├── arc.ts - 圆弧图形相关转换
+├── area.ts - 区域图形相关转换
+├── line.ts - 线图形相关转换
+├── polygon.ts - 多边形图形相关转换
+├── rect.ts - 矩形图形相关转换
+└── symbol.ts - symbol图形相关转换
+
+
+```
+In the following chapters, we will describe in detail some core code implementations
+
+
+
+
+
+ # This document was revised and organized by the following personnel
+ [玄魂](https://github.com/xuanhun)
\ No newline at end of file
diff --git a/docs/assets/contributing/en/sourcecode/14.8.2-vchart-svg-plugin-source-code-analysis.md b/docs/assets/contributing/en/sourcecode/14.8.2-vchart-svg-plugin-source-code-analysis.md
new file mode 100644
index 0000000000..38d040a791
--- /dev/null
+++ b/docs/assets/contributing/en/sourcecode/14.8.2-vchart-svg-plugin-source-code-analysis.md
@@ -0,0 +1,191 @@
+---
+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.
+
+```xml
+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 ``;
+};
+
+```
+## 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.
+
+```xml
+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 `
+ ${children.map(child => parseGroup(child)).join("")}
+ `;
+ }
+
+ // 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
+
+
+```xml
+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
+
+
+```xml
+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
+[玄魂](https://github.com/xuanhun)
\ No newline at end of file
diff --git a/docs/assets/contributing/en/sourcecode/3-how-to-assemble-a-vchart.md b/docs/assets/contributing/en/sourcecode/3-how-to-assemble-a-vchart.md
new file mode 100644
index 0000000000..f6fc15e70d
--- /dev/null
+++ b/docs/assets/contributing/en/sourcecode/3-how-to-assemble-a-vchart.md
@@ -0,0 +1,1158 @@
+---
+title: 3 How to "assemble" a VChart chart
+
+key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM
+---
+In the previous chapters, we talked about the composition and basic principles of charts. Now let's see how to assemble a VChart chart using declarative syntax.
+
+# 3.1 Interface Definition
+
+A basic spec needs to include the following parts:
+
+* `type` Chart type
+
+* `data` Data source
+
+* Data mapping, in most cases in a Cartesian coordinate system as `xField` and `yField`, in a polar coordinate system as `categoryField` and `valueField`
+
+* Series configuration, VChart charts are composed of series, which include elements and labels. The configuration of elements and labels is in the series configuration
+
+* Component configuration, such as `legends`, `axes`, etc. Except for composite charts that must configure `axes`, the configuration of components for other charts is actually optional and can be configured as needed
+
+## 3.1.1 Chart Type
+
+In the spec, we first need to decide the chart type, for example:
+
+
+```Typescript
+{
+ "type": "bar"
+}
+
+```
+Common chart types include `bar`, `line`, `pie`, and more chart types can be referenced in the API documentation: https://www.visactor.io/vchart/option
+
+Note that there is a special chart type called `common`, which is a composite chart type series. Examples will be provided later.
+
+## 3.1.2 Data Source
+
+Data is the foundation of chart visualization, and we need to specify the data source in the spec. Typically, data is represented in JSON format, using the `data` field to specify it. For example, we can specify the data source in the following format:
+
+```Typescript
+{
+ "data": [
+ {
+ "id": "barData",
+ "values": [
+ { "type": "A", "year": "1930", "value": 129 },
+ { "type": "A", "year": "1940", "value": 133 },
+ { "type": "A", "year": "1950", "value": 130 },
+ { "type": "A", "year": "1960", "value": 126 },
+ { "type": "A", "year": "1970", "value": 117 },
+ { "type": "A", "year": "1980", "value": 114 },
+ { "type": "A", "year": "1990", "value": 111 },
+ { "type": "A", "year": "2000", "value": 89 },
+ { "type": "A", "year": "2010", "value": 80 },
+ { "type": "A", "year": "2018", "value": 80 },
+ { "type": "B", "year": "1930", "value": 22 },
+ { "type": "B", "year": "1940", "value": 13 },
+ { "type": "B", "year": "1950", "value": 25 },
+ { "type": "B", "year": "1960", "value": 29 },
+ { "type": "B", "year": "1970", "value": 38 },
+ { "type": "B", "year": "1980", "value": 41 },
+ { "type": "B", "year": "1990", "value": 57 },
+ { "type": "B", "year": "2000", "value": 87 },
+ { "type": "B", "year": "2010", "value": 98 },
+ { "type": "B", "year": "2018", "value": 99 }
+ ]
+ }
+ ]
+}
+
+```
+The `id` field is used to identify the data source, and the `values` field is used to specify the data of the data source.
+
+In VChart, in most cases, we expect to use `flattened` data objects. The difference between `flattened` and `non-flattened` data objects is shown in the example below
+
+```Typescript
+// 非展平数据对象
+[
+ {date: "Monday", class No.1: 20, class No.2: 30},
+ {date: "Tuesday", class No.1: 25, class No.2: 28},
+]
+// 展平数据对象
+[
+ { date: "Monday", class: "class No.1", score: 20 },
+ { date: "Monday", class: "class No.2", score: 30 },
+
+ { date: "Tuesday", class: "class No.1", score: 25 },
+ { date: "Tuesday", class: "class No.2", score: 28 },
+]
+
+```
+The most important significance of flattening data is that it allows for a one-to-one correspondence between data and graphics.
+
+## 3.1.3 Data Mapping
+
+Next, we need to map the data to the basic graphical elements (marks) of the chart. For the grouped bar chart in this tutorial, we specify `xField`, `yField`, and `seriesField`. Here, `xField` and `yField` are used for position mapping, and `seriesField` is used for color mapping
+
+```Typescript
+{
+ "xField": ["year", "type"],
+ "yField": "value",
+ "seriesField": "type"
+}
+
+```
+## 3.1.4 Series Configuration
+
+A series refers to the main body of the chart in the image, such as the line in a line chart, which will be introduced in more detail later.
+
+
+
+
+## 3.1.5 Component Configuration
+
+VChart also supports configuring various components of the chart, such as axes, legends, crosshair, and tooltip. Currently, the components supported by VChart are:
+
+# 3.2 Series
+
+## 3.2.1 Concept and Types
+
+In VChart, Series are the core building blocks of visual charts, responsible for mapping data into visual expressions. A series represents a set of related data items that share the same visual representation (such as line, bar, etc.). Series are converters from data to graphics, including data processing, coordinate mapping, visual encoding, and other functions. Each series type corresponds to a specific visual representation form, with unique data structure requirements and visual mapping rules.
+
+### Basic and Coordinate System Classes
+
+* base: Basic implementation of series, providing common functions for all series
+
+* cartesian: Cartesian coordinate system base class, used for X-Y axis series
+
+* polar: Polar coordinate system base class, used for circular and radial series
+
+* geo: Geographic coordinate system base class, used for map-related series
+
+### Cartesian Coordinate System Series
+
+* bar: Bar chart, used for category data comparison
+
+* line: Line chart, showing data trends and changes
+
+* area: Area chart, emphasizing cumulative changes in data volume
+
+* scatter: Scatter plot, showing the distribution of data points
+
+* box-plot: Box plot, displaying data distribution and outliers
+
+* dot: Dot plot, simplified scatter plot
+
+* heatmap: Heatmap, using color intensity to represent value size
+
+* range-area: Range area chart, showing upper and lower boundary areas
+
+* range-column: Range column chart, showing data range
+
+* waterfall: Waterfall chart, showing cumulative effects
+
+### Polar Coordinate System Series
+
+* pie: Pie chart, showing the relationship between part and whole
+
+* rose: Rose chart, circular display of multidimensional data
+
+* radar: Radar chart, radial display of multivariable data
+
+### Hierarchical Series
+
+* treemap: Treemap, nested rectangle display of hierarchical structure
+
+* sunburst: Sunburst chart, circular display of hierarchical data
+
+* circle-packing: Circle packing chart, nested circle display of hierarchical structure
+
+### Relational Series
+
+* sankey: Sankey diagram, showing flow and conversion relationships
+
+* correlation: Correlation chart, showing correlations between different dimensions
+
+* venn: Venn diagram, showing intersection relationships between sets
+
+* link: Link chart, showing connections between entities
+
+### Special Series
+
+* funnel: Funnel chart, showing conversion rates of multi-stage processes
+
+* gauge: Gauge chart, showing the achievement of a single indicator
+
+* liquid: Liquid chart, using liquid fill effect to show progress
+
+* map: Map series, displaying data in geographic space
+
+* mosaic: Mosaic chart, using rectangle area to display multidimensional data relationships
+
+* pictogram: Pictogram chart, using icons to represent data
+
+* progress: Progress bar, linear display of completion
+
+* word-cloud: Word cloud chart, displaying text data based on word frequency
+
+## 3.2.2 Series Data Management
+
+
+
+
+### Initialization Phase
+
+```Typescript
+// packages/vchart/src/series/base/base-series.ts
+ protected initData(): void {
+ const d = this._spec.data ?? this._option.getSeriesData(this._spec.dataId, this._spec.dataIndex);
+ if (d) {
+ this._rawData = dataToDataView(d, this._dataSet, this._option.sourceDataList);
+ }
+ this._rawData?.target?.addListener('change', this.rawDataUpdate.bind(this));
+ this._addDataIndexAndKey();
+ // 初始化viewData
+ if (this._rawData) {
+ if (this.getStack()) {
+ // 初始化viewDataFilter
+ this._viewDataFilter = dataViewFromDataView(this._rawData, this._dataSet, {
+ name: `${this.type}_${this.id}_viewDataFilter`
+ });
+ }
+
+ // 初始化viewData
+ const viewData = dataViewFromDataView(this.getStack() ? this._viewDataFilter : this._rawData, this._dataSet, {
+ name: `${this.type}_${this.id}_viewData`
+ });
+ this._data = new SeriesData(this._option, viewData);
+
+ if (this.getStack()) {
+ this._viewDataFilter.target.removeListener('change', viewData.reRunAllTransform);
+ }
+ }
+
+ this.initInvalidDataTransform();
+ }
+
+```
+1. Extract data from the spec's data or option and convert it into a DataView
+
+1. Then register a Listener, which triggers the rawDataUpdate function when the data changes
+
+1. Add index and key to the Data
+
+1. Then we will generate DataViews of different levels
+
+1. If stacked data is needed, we create an intermediate DataView
+
+1. If stacked data is not needed, directly create viewData, which is used by the chart for statistics and rendering
+
+
What is a DataView?
+It is a view encapsulation of a data set, providing a series of operations and capabilities to transform data. You can think of a DataView as an "intelligent data container" that not only stores data but also processes and transforms it in various ways.
+
+```Typescript
+// packages/vchart/src/series/base/base-series.ts
+protected _statisticViewData() {
+ registerDataSetInstanceTransform(this._dataSet, 'dimensionStatistics', dimensionStatistics);
+ const viewDataStatisticsName = `${this.type}_${this.id}_viewDataStatic`;
+ this._viewDataStatistics = new DataView(this._dataSet, { name: viewDataStatisticsName });
+ this._viewDataStatistics.parse([this._data.getDataView()], {
+ type: 'dataview'
+ });
+ this._viewDataStatistics.transform(
+ {
+ type: 'dimensionStatistics',
+ options: {
+ fields: () => {
+ const fields = this.getStatisticFields();
+ if (this._seriesField) {
+ mergeFields(fields, [
+ {
+ key: this._seriesField,
+ operations: ['values']
+ }
+ ]);
+ }
+ return fields;
+ },
+ target: 'latest'
+ }
+ },
+ false
+ );
+ // ...
+}
+
+```
+Create a series of statistics, such as maximum, minimum, etc. The statistics generated by different types of charts may vary. The specific chart's series class will implement this `abstract function getStatisticFields` to control what Statistics are generated.
+
+
+```xml
+ abstract getStatisticFields(): {
+ key: string;
+ operations: StatisticOperations;
+ }[];
+
+```
+### Update Data
+
+#### Data Layer
+
+
+```Typescript
+// 1. 原始数据视图
+protected _rawData!: DataView;
+
+// 2. 原始数据统计视图
+protected _rawDataStatistics?: DataView;
+
+// 3. 原始数据统计缓存
+protected _rawStatisticsCache: Record;
+
+// 4. 更新原始数据
+updateRawData(d: any): void {
+ if (!this._rawData) {
+ return;
+ }
+ this._rawData.updateRawData(d);
+}
+
+// 5. 原始数据更新处理
+rawDataUpdate(d: DataView): void {
+ // 重新计算统计信息
+ this._rawDataStatistics?.reRunAllTransform();
+ // 清空缓存
+ this._rawStatisticsCache = null;
+ // 触发事件
+ this.event.emit(ChartEvent.rawDataUpdate, { model: this });
+}
+
+```
+#### Filter Layer
+
+
+```Typescript
+// 1. 数据过滤视图
+protected _viewDataFilter: DataView = null;
+
+// 2. 过滤完成处理
+viewDataFilterOver(d: DataView): void {
+ this.event.emit(ChartEvent.viewDataFilterOver, { model: this });
+}
+
+// 3. 添加数据过滤
+addViewDataFilter(option: ITransformOptions) {
+ (this._viewDataFilter ?? this.getViewData())?.transform(option, false);
+}
+
+// 4. 重新过滤数据
+reFilterViewData() {
+ (this._viewDataFilter ?? this.getViewData())?.reRunAllTransform();
+}
+
+```
+#### View Layer
+
+
+```Typescript
+// 1. 视图数据
+protected _data: SeriesData = null;
+
+// 2. 视图数据统计
+protected _viewDataStatistics!: DataView;
+
+// 3. 视图数据更新处理
+viewDataUpdate(d: DataView): void {
+ this.event.emit(ChartEvent.viewDataUpdate, { model: this });
+ this._data?.updateData();
+ this._viewDataStatistics && this._viewDataStatistics.reRunAllTransform();
+}
+
+// 4. 统计信息更新处理
+viewDataStatisticsUpdate(d: DataView): void {
+ this.event.emit(ChartEvent.viewDataStatisticsUpdate, { model: this });
+}
+
+```
+### Release Phase
+
+Mainly divided into the following processes:
+
+
+```Typescript
+release(): void {
+ super.release();
+
+ // 1. 清理视图数据映射
+ this._viewDataMap.clear();
+
+ // 2. 清理原始数据转换
+ const transformIndex = this._rawData?.transformsArr?.findIndex(t => t.type === 'addVChartProperty');
+ if (transformIndex >= 0) {
+ this._rawData.transformsArr.splice(transformIndex, 1);
+ }
+
+ // 3. 释放系列数据
+ this._data?.release();
+
+ // 4. 清空数据引用
+ this._dataSet = null;
+ this._data = null;
+ this._rawData = null;
+ this._rawDataStatistics = null;
+ this._viewDataStatistics = null;
+ this._viewStackData = null;
+}
+
+```
+## 3.2.3 Creation of Series Primitives
+
+1. Root Primitive:
+
+* Function: Acts as a container to organize and manage other primitives
+
+* Characteristics: Must be of group type
+
+* Position: Topmost level
+
+1. Series Primitive:
+
+* Function: Implements the core visualization functionality of the chart, used for drawing series
+
+* Characteristics: Related to specific chart types
+
+* Position: Main primitive under the root primitive
+
+1. Extension Primitive:
+
+* Function: Provides additional functional support
+
+* Characteristics: Optional, used to enhance chart functionality, such as labels
+
+* Position: Auxiliary primitive under the root primitive
+
+
+
+
+### Create Entry
+
+```Typescript
+// BaseSeries 中的 created 方法
+created(): void {
+ super.created();
+
+ // 1. 构建图元属性上下文
+ this._buildMarkAttributeContext();
+
+ // 2. 初始化数据
+ this.initData();
+ this.initGroups();
+ this.initStatisticalData();
+
+ // 3. 初始化图元
+ this.initRootMark();
+ this.initMark();
+
+ // 4. 初始化扩展图元
+ const hasAnimation = isAnimationEnabledForSeries(this);
+ this._initExtensionMark({ hasAnimation });
+
+ // 5. 初始化样式和状态
+ this.initMarkStyle();
+ this.initMarkState();
+
+ // 6. 初始化动画
+ if (hasAnimation) {
+ this.initAnimation();
+ }
+
+ // 7. 初始化交互
+ if (!this._option.disableTriggerEvent) {
+ this.initInteraction();
+ }
+
+ this.afterInitMark();
+}
+
+```
+### Root Element Creation
+
+
+```Typescript
+initRootMark() {
+ // 1. 创建根图元
+ this._rootMark = this._createMark(
+ {
+ type: MarkTypeEnum.group,
+ name: `seriesGroup_${this.type}_${this.id}`
+ },
+ {
+ parent: this._region.getGroupMark?.(),
+ dataView: false
+ }
+ ) as IGroupMark;
+
+ // 2. 设置层级
+ this._rootMark.setMarkConfig({
+ zIndex: this._spec.zIndex ?? this.layoutZIndex
+ });
+}
+
+```
+### Series Primitive Creation
+
+
+```Typescript
+// 创建图元的通用方法
+protected _createMark(
+ markInfo: ISeriesMarkInfo,
+ option: ISeriesMarkInitOption = {},
+ config: ICompileMarkConfig = {}
+) {
+ const {
+ key,
+ groupKey,
+ skipBeforeLayouted,
+ themeSpec = {},
+ markSpec,
+ dataView,
+ dataProductId,
+ parent,
+ isSeriesMark,
+ depend,
+ stateSort,
+ noSeparateStyle = false
+ } = option;
+
+ // 1. 创建图元
+ const m = super._createMark(markInfo, {
+ key: key ?? this._getDataIdKey(),
+ seriesId: this.id,
+ attributeContext: this._markAttributeContext,
+ componentType: option.componentType,
+ noSeparateStyle
+ });
+
+ if (isValid(m)) {
+ // 2. 添加到图元集合
+ this._marks.addMark(m, { name: markInfo.name });
+
+ // 3. 设置系列图元
+ if (isSeriesMark) {
+ this._seriesMark = m;
+ }
+
+ // 4. 设置父级关系
+ if (isNil(parent)) {
+ this._rootMark?.addMark(m);
+ } else if (parent !== false) {
+ parent.addMark(m);
+ }
+
+ // 5. 设置数据视图
+ if (isNil(dataView)) {
+ m.setDataView(this.getViewData(), this.getViewDataProductId());
+ m.setSkipBeforeLayouted(true);
+ } else if (dataView !== false) {
+ m.setDataView(dataView, dataProductId);
+ }
+
+ // 6. 设置其他属性
+ if (isBoolean(skipBeforeLayouted)) {
+ m.setSkipBeforeLayouted(skipBeforeLayouted);
+ }
+
+ if (isValid(depend)) {
+ m.setDepend(...array(depend));
+ }
+
+ if (!isNil(groupKey)) {
+ m.setGroupKey(groupKey);
+ }
+
+ if (stateSort) {
+ m.setStateSortCallback(stateSort);
+ }
+
+ // 7. 设置图元配置
+ const markConfig: IMarkConfig = {
+ ...config,
+ morph: config.morph ?? false,
+ support3d: is3DMark(markInfo.type as MarkTypeEnum) ||
+ (config.support3d ?? (spec.support3d || !!(spec as any).zField)),
+ morphKey: spec.morph?.morphKey || `${this.getSpecIndex()}_${this.getMarks().length}`,
+ morphElementKey: spec.morph?.morphElementKey ?? config.morphElementKey
+ };
+
+ m.setMarkConfig(markConfig);
+
+ // 8. 初始化样式
+ this.initMarkStyleWithSpec(m, mergeSpec({}, themeSpec, markSpec || spec[m.name]));
+ }
+ return m;
+}
+
+```
+### Extended Primitive Initialization
+
+
+```Typescript
+protected _initExtensionMark(options: { hasAnimation: boolean; depend?: IMark[] }) {
+ if (!this._spec.extensionMark) {
+ return;
+ }
+
+ const mainMarks = this.getMarksWithoutRoot();
+ options.depend = mainMarks;
+
+ // 创建扩展图元
+ this._spec.extensionMark?.forEach((m, i) => {
+ this._createExtensionMark(
+ m,
+ null,
+ this._getExtensionMarkNamePrefix(),
+ i,
+ options
+ );
+ });
+}
+
+private _createExtensionMark(
+ spec: IExtensionMarkSpec> | IExtensionGroupMarkSpec,
+ parentMark: null | IGroupMark,
+ namePrefix: string,
+ index: number,
+ options: { hasAnimation: boolean; depend?: IMark[] }
+) {
+ // 1. 创建扩展图元
+ const mark = this._createMark(
+ {
+ type: spec.type,
+ name: isValid(spec.name) ? `${spec.name}` : `${namePrefix}_${index}`
+ },
+ {
+ skipBeforeLayouted: true,
+ markSpec: spec,
+ parent: parentMark,
+ dataView: false,
+ componentType: spec.componentType,
+ depend: options.depend,
+ key: spec.dataKey
+ },
+ {
+ setCustomizedShape: spec?.customShape
+ }
+ ) as IGroupMark;
+
+ if (!mark) {
+ return;
+ }
+
+ // 2. 设置用户ID
+ if (isValid(spec.id)) {
+ mark.setUserId(spec.id);
+ }
+
+ // 3. 设置动画
+ if (options.hasAnimation) {
+ const config = animationConfig(
+ {},
+ userAnimationConfig(spec.type, spec as any, this._markAttributeContext)
+ );
+ mark.setAnimationConfig(config);
+ }
+
+ // 4. 处理子图元
+ if (spec.type === 'group') {
+ namePrefix = `${namePrefix}_${index}`;
+ spec.children?.forEach((s, i) => {
+ this._createExtensionMark(s as any, mark, namePrefix, i, options);
+ });
+ }
+ // 5. 设置数据视图
+ else if (!parentMark && (!isNil(spec.dataId) || !isNil(spec.dataIndex))) {
+ const dataView = this._option.getSeriesData(spec.dataId, spec.dataIndex);
+ if (dataView === this._rawData) {
+ mark.setDataView(this.getViewData(), this.getViewDataProductId());
+ } else {
+ mark.setDataView(dataView);
+ dataView.target.addListener('change', () => {
+ mark.getData().updateData();
+ });
+ }
+ }
+}
+
+```
+## 3.2.4 Relationship between Series and `Region`
+
+Region is an important concept in VChart, representing an area in the chart used to organize and layout different chart components. Each Region can contain multiple Series and is responsible for managing the layout and rendering of these Series.
+
+Series use the information of the Region to layout:
+
+
+```Typescript
+// packages/vchart/src/series/base/base-series.ts
+export abstract class BaseSeries extends BaseModel implements ISeries {
+ // Region 引用
+ protected _region: IRegion = null as unknown as IRegion;
+
+ // 获取关联的 Region
+ getRegion(): IRegion {
+ return this._region;
+ }
+
+ // 构造函数中设置 Region
+ constructor(spec: T, options: ISeriesOption) {
+ super(spec, options);
+ this._region = options.region;
+ this._dataSet = options.dataSet;
+ this._spec?.name && (this.name = this._spec.name);
+ }
+
+ // 获取布局起始点
+ getLayoutStartPoint(): ILayoutPoint {
+ return this._region.getLayoutStartPoint();
+ }
+
+ // 获取布局矩形
+ getLayoutRect: () => ILayoutRect = () => {
+ return {
+ width: this._layoutRect.width ?? this._region.getLayoutRect().width,
+ height: this._layoutRect.height ?? this._region.getLayoutRect().height
+ };
+ };
+}
+
+```
+Region can add or remove Series \r\n\r
+```Typescript
+// packages/vchart/src/region/base/base-region.ts
+export abstract class BaseRegion extends BaseModel implements IRegion {
+ protected _series: ISeries[] = [];
+ protected _groupMark: IGroupMark;
+
+ // 添加系列
+ addSeries(series: ISeries): void {
+ this._series.push(series);
+ }
+
+ // 移除系列
+ removeSeries(series: ISeries): void {
+ const index = this._series.indexOf(series);
+ if (index > -1) {
+ this._series.splice(index, 1);
+ }
+ }
+
+ // 获取所有系列
+ getSeries(): ISeries[] {
+ return this._series;
+ }
+
+ // 获取区域组图元
+ getGroupMark(): IGroupMark {
+ return this._groupMark;
+ }
+
+ // 等待所有系列过滤完成
+ async waitAllSeriesFilterOver(): Promise {
+ const promises = this._series.map(series => {
+ return new Promise(resolve => {
+ series.event.on(
+ ChartEvent.viewDataFilterOver,
+ { filter: ({ model }) => model?.id === series.id },
+ () => resolve()
+ );
+ });
+ });
+ await Promise.all(promises);
+ }
+}
+
+```
+# 3.3 Chart Assembly
+
+## 3.3.1 How to Implement a Bar Chart
+
+
+
+
+First, we create a BarChart instance:
+
+```Typescript
+// packages/vchart/src/chart/bar/bar.ts
+export class BarChart extends BaseChart {
+ static readonly type: string = ChartTypeEnum.bar;
+ static readonly seriesType: string = SeriesTypeEnum.bar;
+ static readonly transformerConstructor = BarChartSpecTransformer;
+ readonly transformerConstructor = BarChartSpecTransformer;
+ readonly type: string = ChartTypeEnum.bar;
+ readonly seriesType: string = SeriesTypeEnum.bar;
+}
+
+// 注册 Bar Chart
+export const registerBarChart = () => {
+ registerBarSeries();
+ Factory.registerChart(BarChart.type, BarChart);
+};
+
+```
+Then it will trigger the constructor of BaseChart
+
+```Typescript
+// packages/vchart/src/chart/base/base-chart.ts
+constructor(spec: T, option: IChartOption) {
+ super(option);
+ this._paddingSpec = normalizeLayoutPaddingSpec(spec.padding ?? option.getTheme().padding);
+ this._event = new Event(option.eventDispatcher, option.mode);
+ this._dataSet = option.dataSet;
+ this._chartData = new ChartData(this._dataSet);
+ // ... 其他初始化
+}
+
+```
+### Create Element
+
+Layout
+
+
+```Typescript
+private _createLayout() {
+ this._updateLayoutRect(this._viewBox);
+ this._initLayoutFunc();
+}
+
+private _initLayoutFunc() {
+ this._layoutFunc = this._option.layout;
+ if (!this._layoutFunc) {
+ const constructor = Factory.getLayoutInKey(this._spec.layout?.type ?? 'base');
+ if (constructor) {
+ const layout = new constructor(this._spec.layout, {
+ onError: this._option?.onError
+ });
+ this._layoutFunc = layout.layoutItems.bind(layout);
+ }
+ }
+}
+
+```
+Create Region and Series
+
+```Typescript
+protected _createRegion(constructor: IRegionConstructor, specInfo: IModelSpecInfo) {
+ if (!constructor) return;
+ const { spec, ...others } = specInfo;
+ const region = new constructor(spec, {
+ ...this._modelOption,
+ ...others
+ });
+ if (region) {
+ region.created();
+ this._regions.push(region);
+ }
+}
+
+protected _createSeries(constructor: ISeriesConstructor, specInfo: IModelSpecInfo) {
+ if (!constructor) return;
+ const { spec, ...others } = specInfo;
+
+ // 获取对应的区域
+ let region: IRegion | undefined;
+ if (isValid(spec.regionId)) {
+ region = this.getRegionsInUserId(spec.regionId);
+ } else if (isValid(spec.regionIndex)) {
+ region = this.getRegionsInIndex([spec.regionIndex])[0];
+ }
+
+ if (!region && !(region = this._regions[0])) return;
+
+ // 创建系列
+ const series = new constructor(spec, {
+ ...this._modelOption,
+ ...others,
+ type: spec.type,
+ region,
+ globalScale: this._globalScale,
+ sourceDataList: this._chartData.dataList
+ });
+
+ if (series) {
+ series.created();
+ this._series.push(series);
+ region.addSeries(series);
+ }
+}
+
+```
+Create Component
+
+```xml
+ protected _createComponent(constructor: IComponentConstructor, specInfo: IModelSpecInfo) {
+ const component = constructor.createComponent(specInfo, {
+ ...this._modelOption,
+ type: constructor.type,
+ getAllRegions: this.getAllRegions,
+ getRegionsInIndex: this.getRegionsInIndex,
+ getRegionsInIds: this.getRegionsInIds,
+ getRegionsInUserIdOrIndex: this.getRegionsInUserIdOrIndex,
+ getAllSeries: this.getAllSeries,
+ getSeriesInIndex: this.getSeriesInIndex,
+ getSeriesInIds: this.getSeriesInIds,
+ getSeriesInUserIdOrIndex: this.getSeriesInUserIdOrIndex,
+ getAllComponents: this.getComponents,
+ getComponentByIndex: this.getComponentByIndex,
+ getComponentByUserId: this.getComponentByUserId,
+ getComponentsByKey: this.getComponentsByKey,
+ getComponentsByType: this.getComponentsByType
+ });
+ if (!component) {
+ return;
+ }
+ component.created();
+ this._components.push(component);
+ }
+
+```
+### Other Parts Besides Chart Visual Elements
+
+Initialization Event
+
+
+```Typescript
+ private _initEvent() {
+ [ChartEvent.dataZoomChange, ChartEvent.scrollBarChange].forEach(event => {
+ this._event.on(event, ({ value }) => {
+ this._disableMarkAnimation(['exit', 'update']);
+ const enableMarkAnimate = () => {
+ this._enableMarkAnimation(['exit', 'update']);
+ this._event.off(VGRAMMAR_HOOK_EVENT.AFTER_MARK_RENDER_END, enableMarkAnimate);
+ };
+ this._event.on(VGRAMMAR_HOOK_EVENT.AFTER_MARK_RENDER_END, enableMarkAnimate);
+ });
+ });
+ }
+
+```
+Data Stream Processing
+
+```Typescript
+reDataFlow() {
+ this._series.forEach(s => s.getRawData()?.markRunning());
+ this._series.forEach(s => s.fillData());
+ this.updateGlobalScaleDomain();
+}
+
+```
+Layout Calculation
+
+```xml
+layout(params: ILayoutParams): void {
+ if (this.getLayoutTag()) {
+ this._event.emit(ChartEvent.layoutStart, { chart: this });
+ this.onLayoutStart(params);
+ const elements = this.getLayoutElements();
+ this._layoutFunc(this, elements, this._layoutRect, this._viewBox);
+ this._event.emit(ChartEvent.afterLayout, { elements, chart: this });
+ this.setLayoutTag(false);
+ this.onLayoutEnd(params);
+ this._event.emit(ChartEvent.layoutEnd, { chart: this });
+ }
+}
+
+```
+### Compile Rendering
+
+
+```Typescript
+compile() {
+ this.compileBackground();
+ this.compileLayout();
+ this.compileRegions();
+ this.compileSeries();
+ this.compileComponents();
+}
+
+compileSeries() {
+ this._option.performanceHook?.beforeSeriesCompile?.();
+ this.getAllSeries().forEach(s => {
+ s.compile();
+ });
+ this._option.performanceHook?.afterSeriesCompile?.();
+}
+
+```
+## 3.3.2 Common chart
+
+Common Chart is a general chart type in VChart, which allows users to combine multiple different types of series in one chart. Let me analyze its implementation in detail.
+
+### Create adaptive series type
+
+
+```Typescript
+// packages/vchart/src/chart/common/common.ts
+export class CommonChart extends BaseChart> {
+ static readonly type: string = ChartTypeEnum.common;
+ static readonly transformerConstructor = CommonChartSpecTransformer;
+ readonly transformerConstructor = CommonChartSpecTransformer;
+ readonly type: string = ChartTypeEnum.common;
+}
+
+```
+`AdaptiveSpec`, allows Common Chart to accept any type of series configuration.
+
+### Series Registration Mechanism
+
+```Typescript
+// packages/vchart/src/core/factory.ts
+export class Factory {
+ private static _seriesMap: Map = new Map();
+
+ static registerSeries(type: string, constructor: ISeriesConstructor) {
+ this._seriesMap.set(type, constructor);
+ }
+
+ static getSeries(type: string): ISeriesConstructor {
+ return this._seriesMap.get(type);
+ }
+}
+
+```
+Common Chart achieves dynamic series registration through the Factory pattern, allowing Common Chart to register multiple series.
+
+### Special Handling of Series
+
+We need to take a closer look at the following three functions
+
+```xml
+// packages/vchart/src/chart/common/common-transformer.ts
+protected _getDefaultSeriesSpec(spec: AdaptiveSpec) {
+ const defaultSpec = super._getDefaultSeriesSpec(spec);
+ // 删除默认的 data 配置
+ delete defaultSpec.data;
+ return defaultSpec;
+}
+
+```
+The function's purpose is to:
+
+* Obtain the default configuration of the series
+
+* Inherit the default configuration of the parent class
+
+* Remove the default data configuration
+
+* Reason: In a composite chart, each series needs to decide its own data configuration and cannot use a unified default configuration
+
+```Typescript
+protected _transformAxisSpec(spec: AdaptiveSpec) {
+ if (!spec.axes) return;
+
+ if (!!spec.autoBandSize) {
+ spec.series.forEach((series: any, seriesIndex: number) => {
+ // 只处理柱状图系列
+ if (series.type === 'bar') {
+ // 找到对应的坐标轴
+ const relatedAxis = this._findBandAxisBySeries(series, seriesIndex, spec.axes);
+ if (relatedAxis && !relatedAxis.bandSize && !relatedAxis.maxBandSize && !relatedAxis.minBandSize) {
+ // 处理柱状图的宽度配置
+ const extend = isObject(series.autoBandSize) ? series.autoBandSize.extend ?? 0 : 0;
+ const { barMaxWidth, barMinWidth, barWidth, barGapInGroup } = series;
+ this._applyAxisBandSize(relatedAxis, extend, { barMaxWidth, barMinWidth, barWidth, barGapInGroup });
+ }
+ }
+ });
+ }
+}
+
+```
+The function's purpose is to:
+
+* Handle the configuration of the axes
+
+* Specifically handle the width configuration of bar charts
+
+* When autoBandSize is enabled:
+
+* Iterate over all series
+
+* Find the bar chart series
+
+* Find the corresponding axis
+
+* Calculate and set the width of the bars
+
+* Handle the spacing of the bars
+
+
+```Typescript
+transformSpec(spec: AdaptiveSpec): void {
+ // 1. 调用父类的转换方法
+ super.transformSpec(spec);
+
+ // 2. 处理系列配置
+ if (spec.series && spec.series.length) {
+ const defaultSeriesSpec = this._getDefaultSeriesSpec(spec);
+ spec.series.forEach((s: ISeriesSpec) => {
+ // 验证系列类型
+ if (!this._isValidSeries(s.type)) {
+ return;
+ }
+ // 应用默认配置
+ Object.keys(defaultSeriesSpec).forEach(k => {
+ if (!(k in s)) {
+ s[k] = defaultSeriesSpec[k];
+ }
+ });
+ });
+ }
+
+ // 3. 处理坐标轴配置
+ if (spec.axes && spec.axes.length) {
+ spec.axes.forEach((axis: any) => {
+ // 处理坐标轴内边距
+ if (get(axis, 'trimPadding')) {
+ mergeSpec(axis, getTrimPaddingConfig(this.type, spec));
+ }
+ });
+ }
+
+ // 4. 处理坐标轴的 bandSize 配置
+ this._transformAxisSpec(spec);
+}
+
+```
+This function is the main entry point for conversion, and its functions include:
+
+* Calling the conversion method of the parent class
+
+* Handling series configuration:
+
+* Obtaining default configuration
+
+* Validating series type
+
+* Applying default configuration
+
+* Handling axis configuration:
+
+* Handling padding
+
+* Handling bandSize
+
+These three functions together form the configuration conversion system of Common Chart, mainly solving:
+
+1. Handling of multi-series configuration
+
+1. Handling of special configuration for bar charts
+
+1. Handling of axis configuration
+
+This is the key implementation that distinguishes Common Chart from other chart types.
+
+
+
+# This document was revised and organized by
+[玄魂](https://github.com/xuanhun)
\ No newline at end of file
diff --git a/docs/assets/contributing/en/sourcecode/6.1-primitive-basic-concepts.md b/docs/assets/contributing/en/sourcecode/6.1-primitive-basic-concepts.md
new file mode 100644
index 0000000000..323e88a4e4
--- /dev/null
+++ b/docs/assets/contributing/en/sourcecode/6.1-primitive-basic-concepts.md
@@ -0,0 +1,237 @@
+---
+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:
+
+1. **Constituting Charts**
+
+* Composing various components of a chart, for example, a legend item is composed of `symbol` marks and `text` marks.
+
+1. **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:
+
+
+
+
+
+
+1. 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:
+
+```Typescript
+ // 存储图元的样式状态,包括 normal、hover、selected 等状态的样式配置。
+ declare stateStyle: IMarkStateStyle;
+
+ // 图元的初始化选项,包含上下文、全局缩放、模型等信息。
+ 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:
+
+```Typescript
+// *根据 spec 初始化 style*
+initStyleWithSpec(spec: IMarkSpec, key?: string);
+
+// 设置图元style
+setStyle(style: Partial>,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(key: U, datum: Datum, state: StateValueType = 'normal', opt?: IAttributeOpt);
+
+// 设置属性值
+setAttribute(attr: U,style: MarkInputStyle,state: StateValueType = 'normal',level: number = 0,stateStyle = this.stateStyle);
+
+```
+1. Interface Definition (interface/)
+
+* Core File: `common.ts`
+
+* Key Interfaces:
+
+```Typescript
+// IMarkRaw
+export interface IMarkRaw extends ICompilableMark {
+ // 图元状态样式(例如:hover,selected分别是什么样式)
+ readonly stateStyle: IMarkStateStyle;
+ // 图元属性
+ getAttribute: (key: U, datum: any, state?: StateValueType, opt?: any) => unknown;
+ setAttribute: (attr: U, style: StyleConvert, state?: StateValueType, level?: number) => void;
+ // 图元样式
+ setStyle: (style: Partial>, state?: StateValueType, level?: number) => void;
+ initStyleWithSpec: (spec: any, key?: string) => void;
+}
+
+// IMarkOption 用于初始化和管理图元的上下文、全局映射等信息。
+export interface IMarkOption extends ICompilableMarkOption {
+ model: IModel;
+ map: Map;
+ // 全局映射
+ globalScale: IGlobalScale;
+ // 关联系列编号
+ seriesId?: number;
+ // 组件图元具体类型
+ componentType?: string;
+ attributeContext?: IModelMarkAttributeContext;
+}
+
+
+```
+1. 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:
+
+
+```Typescript
+protected _getDefaultStyle() {
+ const defaultStyle: IMarkStyle = {
+ ...super._getDefaultStyle()
+ // 图元特有的配置
+ };
+ return defaultStyle;
+}
+
+```
+For example, for the line element, the `_getIgnoreAttributes` method has been added to obtain the ignored attributes:
+
+
+```Typescript
+protected _getIgnoreAttributes(): string[] {
+ if (this.model?.type === SeriesTypeEnum.radar && this.model?.coordinate === *'polar'*) {
+ return [];
+ }
+ return [*'fill'*, *'fillOpacity'*];
+}
+
+```
+1. 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
+
+```xml
+export class MarkSet {
+ protected _children: IMark[] = []; // 存储所有 Mark 实例
+ protected _markNameMap: Record = {}; // 名称索引
+ protected readonly _infoMap = new Map(); // 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) {
+ 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
+ [玄魂](https://github.com/xuanhun)
\ No newline at end of file
diff --git a/docs/assets/contributing/en/sourcecode/6.2-visual-channel-mapping.md b/docs/assets/contributing/en/sourcecode/6.2-visual-channel-mapping.md
new file mode 100644
index 0000000000..48e587c0de
--- /dev/null
+++ b/docs/assets/contributing/en/sourcecode/6.2-visual-channel-mapping.md
@@ -0,0 +1,414 @@
+---
+title: 6.2 Visual Channel Mapping
+
+key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM
+---
+# Introduction
+
+**Visual mapping** is the bridge between data and images, mapping the "data model" to the "image model" and selecting suitable visual variables for different types of data. For example, if we use a bar chart to represent the average scores of boys and girls in a class, we can map the gender attribute in the data to the color attribute in the image, and map the score attribute in the data to the height (Y-axis coordinate) attribute of the bar chart in the image. Below, we analyze how data is mapped to the final image through a simple use case.
+
+
+
+# Mapping Process of Graphical Elements
+
+### Usage Example
+
+
+```xml
+const spec = {
+ type: 'line',
+ data: [
+ {
+ id: 'lineData',
+ values: [
+ { date: 'Monday', class: 'class No.1', score: 20 },
+ { date: 'Monday', class: 'class No.2', score: 30 },
+
+ { date: 'Tuesday', class: 'class No.1', score: 25 },
+ { date: 'Tuesday', class: 'class No.2', score: 28 }
+ ]
+ }
+ ],
+ seriesField: 'class',
+ xField: 'date',
+ yField: 'score',
+ point: {
+ style: {
+ fill: 'blue'
+ }
+ }
+};
+
+const vchart = new VChart(spec, { dom: CONTAINER_ID });
+vchart.renderSync();
+
+```
+This example creates a line type glyph series to display 4 data points, where points with the same `class` attribute will be connected into a line. The `date` attribute is mapped to the X-axis coordinate, and the `score` attribute is mapped to the Y-axis coordinate. The effect is as follows:
+
+
+
+
+### Creation of Primitives
+
+Below we analyze through code how `renderSync()` parses the configuration `spec` and generates various primitives on the graph. Overall, `renderSync()` includes the following three stages: pre-rendering, rendering, and post-rendering.
+
+```Typescript
+ // packages/vchart/src/core/vchart.ts
+ protected ***_renderSync*** = (option: IVChartRenderOption = {}) => {
+ const self = this as unknown as IVChart;
+ if (!this.***_beforeRender***(option)) {
+ return self;
+ }
+ this._compiler?.***render***(option.morphConfig);
+ this.***_afterRender***();
+ return self;
+ };
+
+```
+The rendering process belongs to the domain of `VGrammar`, and after rendering, the main focus is on updating the animation state. We mainly focus on the **pre-render preparation** related to the graphics, including initializing chart configurations, instantiating charts, and compiling rendering instructions.
+
+##### 1. Initialize Chart Configurations
+
+
+
+```Typescript
+ // packages/vchart/src/core/vchart.ts
+ private ***_initChartSpec***(spec: any, actionSource: VChartRenderActionSource) {
+ // 如果用户注册了函数,在配置中替换相应函数名为函数内容
+ if (VChart.***getFunctionList***() && VChart.***getFunctionList***().length) {
+ spec = ***functionTransform***(spec, VChart);
+ }
+ this._spec = spec;
+ // 创建图表配置转换器,并转换为common chart的配置
+ if (!this._chartSpecTransformer) {
+ this._chartSpecTransformer = Factory.***createChartSpecTransformer***(
+ this._spec.type,
+ this.***_getChartOption***(this._spec.type)
+ );
+ }
+ this._chartSpecTransformer?.***transformSpec***(this._spec);
+ // 转换模型配置
+ this._specInfo = this._chartSpecTransformer?.***transformModelSpec***(this._spec);
+ }
+
+```
+First, replace the function name registered by the user with the corresponding function entity. Then, according to the chart type, create the corresponding chart configuration converter to convert the configuration of this type of chart into the configuration of the `common` type chart. This includes creating a default `series` based on the chart type and completing the user-defined `series` configuration:
+
+
+```xml
+ // packages/vchart/src/chart/cartesian/cartesian-transformer.ts
+ const defaultSeriesSpec = this.***_getDefaultSeriesSpec***(spec);
+ if (!spec.series || spec.series.length === 0) { // 没有用户定义的系列 采用默认
+ spec.series = [defaultSeriesSpec];
+ } else {
+ spec.series.***forEach***((s: ISeriesSpec) => {
+ if (!this.***_isValidSeries***(s.type)) { // 判断用户定义系列是否有效
+ return;
+ }
+ Object.***keys***(defaultSeriesSpec).***forEach***(k => { // 补全配置
+ if (!(k in s)) {
+ s[k] = defaultSeriesSpec[k];
+ }
+ });
+ });
+ }
+
+```
+
+
+##### 2. Instantiate the Chart
+
+
+
+Next, create a chart object of the corresponding type. The chart object here does not refer to the `VChart` object created below. `VChart` encapsulates the chart, serving as the entry point for user operations, responsible for global management and external interfaces of the chart;
+
+```xml
+const vchart = new VChart(spec, { dom: CONTAINER_ID });
+
+```
+The instantiated chart here is responsible for the specific chart construction (such as creating and managing series, components) and internal logic processing (managing data flow, global mapping, graphic element states, etc.).
+
+```Typescript
+ // packages/vchart/src/core/vchart.ts
+ private ***_initChart***(spec: any) {
+ // 创建真正的图表对象
+ const chart = Factory.***createChart***(spec.type, spec, this.***_getChartOption***(spec.type));
+ this._chart = chart;
+ // 进行图表初始化
+ this._chart.***setCanvasRect***(this._currentSize.width, this._currentSize.height);
+ this._chart.***created***();
+ this._chart.***init***();
+ this._event.***emit***(ChartEvent.initialized, {
+ chart,
+ vchart: this
+ });
+ }
+
+```
+The core steps are `created` and `init`, the former creates various elements according to `spec`, such as `region`, `series`, `components`, and the latter initializes each element. We focus on the graphic elements in the creation of `series`.
+
+```xml
+ // packages/vchart/src/series/base/base-series.ts
+ ***created***(): void {
+ ...
+ this.***initMark***();
+ ...
+ }
+
+```
+Since the type of our chart is `line`, there is a default `line` series. We look at the implementation of `initMark` in the `line-series`:
+
+```xml
+ // packages/vchart/src/series/line/line.ts
+ ***initMark***(): void {
+ ...
+ const seriesMark = this._spec.seriesMark ?? *'line'*;
+ this.***initLineMark***(progressive, seriesMark === *'line'*);
+ this.***initSymbolMark***(progressive, seriesMark === *'point'*);
+ }
+
+```
+It was found that indeed the `line` primitives and `symbol` primitives continued to be created:
+
+
+
+
+After a series of function calls (`LineLikeSeriesMixin.initLineMark` -> `BaseSeries._createMark` -> `BaseModel._createMark` -> `Factory.createMark`), it finally reaches the constructor of the corresponding graphic element, which is the "implementation of specific graphic elements" mentioned earlier.
+
+
+
+##### **3. Compile Rendering Instructions**
+
+Compile various `VChart` models (`region`, `series`, `component`) into renderable `VGrammar` syntax elements, involving the content of the `VGrammar` syntax layer, which will not be analyzed in detail.
+
+
+
+### Mapping of Graphic Element Visual Configuration
+
+In the `BaseMark` class, graphic elements achieve the mapping from data to visual channels through a series of methods and logic. This can be roughly divided into two processes: the storage of attributes and the calculation of attribute values. The former simply parses the user-defined `spec` and stores it in the style sheets of various states of the graphic element, during which some simple conversions are made; the latter is where the user of the graphic element truly obtains and calculates specific attribute values when laying out the graphic element.
+
+
+
+
+
+#### Step1 Store Style
+
+##### 1. Initialize Style
+
+Initialize the default style of the graphic element, call the `setStyle` method to set the default value for the `normal` state:
+
+```xml
+private ***_initStyle***(): void {
+ const defaultStyle = this.***_getDefaultStyle***();
+ this.***setStyle***(defaultStyle, *'normal'*, 0);
+}
+
+```
+* Default styles include `visible`: true, `x`: 0, `y`: 0, etc.
+
+* These default values ensure that the elements render correctly even without user-defined styles.
+
+The `initStyleWithSpec` method initializes styles based on the user-provided `spec`:
+
+```Typescript
+initStyleWithSpec(spec: IMarkSpec, key?: string) {
+ if (!spec) return;
+
+ if (isValid(spec.id)) this._userId = spec.id;
+ if (isBoolean(spec.interactive)) this._markConfig.interactive = spec.interactive;
+ if (isValid(spec.zIndex)) this._markConfig.zIndex = spec.zIndex;
+ if (isBoolean(spec.visible)) this.setVisible(spec.visible);
+
+ this._initSpecStyle(spec, this.stateStyle, key);
+}
+
+```
+* Parse user-defined attributes such as `interactive`, `zIndex`, `visible`, etc.
+
+* Call the `_initSpecStyle` method to handle `style` and `state`. This part mainly involves calling `setStyle` to set the corresponding style for each state (including the initial `normal` state) and storing the state information in the state manager. We explain the state in detail.
+
+
+
+The above methods all call the core function `setStyle`, which is used to set styles for specified states:
+
+
+```Typescript
+ ***setStyle***(
+ style: Partial>, // 样式
+ state: StateValueType = *'normal'*, // 状态
+ level: number = 0, // 状态层级 当处于不同状态产生冲突时 根据层级设置样式
+ stateStyle = this.stateStyle // 存储状态样式
+ ): void {
+ if (***isNil***(style)) {
+ return;
+ }
+ if (stateStyle[state] === undefined) {
+ stateStyle[state] = {};
+ }
+ const isUserLevel = this.***isUserLevel***(level);
+ Object.***keys***(style).***forEach***((attr: string) => {
+ let attrStyle = style[attr] as MarkInputStyle;
+ if (***isNil***(attrStyle)) {
+ return;
+ }
+ // 过滤和转化样式
+ attrStyle = this.***_filterAttribute***(attr as any, attrStyle, state, level, isUserLevel, stateStyle);
+ // 设置样式
+ this.***setAttribute***(attr as any, attrStyle, state, level, stateStyle);
+ /* 在setAttribute中设置属性计算方式/样式
+ stateStyle[state][attr] = {
+ level,
+ style,
+ referer: undefined
+ };
+ */
+ });
+ }
+
+```
+
+
+##### 2. Filter and Transform Styles
+
+The `_filterAttribute` called in `setStyle` is used to filter and transform individual style attributes, ensuring that the style attributes conform to internal usage standards. These transformations are relatively simple, as noted in the comments.
+
+
+```Typescript
+ protected ***_filterAttribute***(
+ attr: U,
+ style: MarkInputStyle,
+ state: StateValueType,
+ level: number,
+ isUserLevel: boolean,
+ stateStyle = this.stateStyle
+ ): StyleConvert {
+ // *** **将visual spec转换为 scale 类型的 mark style** ***
+ // 用于后续计算属性值
+ let newStyle = this.***_styleConvert***(style);
+
+ if (isUserLevel) {
+ switch (attr) {
+ case *'angle'*:
+ // 角度值转弧度值
+ newStyle = this.***convertAngleToRadian***(newStyle);
+ break;
+ case *'innerPadding'*:
+ case *'outerPadding'*:
+ // VRender 的 padding 定义基于 centent-box 盒模型,默认正方向是向外扩,与 VChart 不一致。这里将 padding 符号取反
+ newStyle = this.***_transformStyleValue***(newStyle, (value: number) => -value);
+ break;
+ case *'curveType'*:
+ // 根据direction返回'*monotoneY*'(*Direction.horizontal*)或'*monotoneX*'
+ newStyle = this.***_transformStyleValue***(newStyle, (value: string) =>
+ ***curveTypeTransform***(value, (this._option.model as any).direction)
+ );
+ break;
+ }
+ }
+ return newStyle;
+ }
+
+```
+It is particularly important to note that in `styleConvert`, some styles that need to be converted to `scale` type are transformed for subsequent attribute value calculations. For example, convert `yField: 'score'` to:
+
+```xml
+{
+ scale, // 映射对象,用于数据到视觉通道的映射,可以理解为一个函数,输入数据对应的值,输出视觉通道的值
+ field: 'score', // 数据字段名,表示映射的输入字段。
+ changeDomain: true // 布尔值,表示是否允许动态更新比例尺的定义域(domain)
+};
+
+```
+This is a `scale` type style, where the first field `scale` calculates the value of the data corresponding field `datum['score']` as the `y` coordinate of the graphic element.
+
+
+
+#### Step2 Calculate Attribute Values
+
+`BaseMark` provides an interface `getAttribute` for its users to calculate and obtain attribute values based on actual data.
+
+```xml
+ ***getAttribute***(key: U, datum: Datum, state: StateValueType = *'normal'*, opt?: IAttributeOpt) {
+ return this.***_computeAttribute***(key, state)(datum, opt);
+ }
+
+```
+Here, the `compteAttribute(key, state)` returns a function for calculating an attribute, where `key` is the attribute name and `state` is the current state; `(datum, opt)` is used as the parameter for this function, returning the calculation result, consistent with our above description of **“the method of storing attribute calculations”**.
+
+```Typescript
+ protected ***_computeAttribute***(key: U, state: StateValueType) {
+ let stateStyle = this.stateStyle[state]?.[key];
+ if (!stateStyle) {
+ stateStyle = this.stateStyle.normal[key];
+ }
+ const baseValueFunctor = this.***_computeStateAttribute***(stateStyle, key, state);
+ const hasPostProcess = ***isFunction***(stateStyle?.***postProcess***);
+ const hasExCompute = key in this._computeExChannel;
+ // ...
+ // 叠加后处理函数和额外计算函数
+ // ...
+ return baseValueFunctor;
+ }
+
+```
+Continuing to delve into `computeStateAttribute`, you will find that an attribute calculation function is constructed here. The input of this function is `(datum, opt)`, and the output is the calculated attribute value. If the attribute value is a constant (unrelated to the data, fixed on `spec`), then this constructed function directly returns `style`; what really needs to be calculated are some complex styles and mappings from data to visuals~~(recycling theme)~~.
+
+```Typescript
+ protected ***_computeStateAttribute***(stateStyle: any, key: U, state: StateValueType) {
+ if (!stateStyle) { // 处理空样式
+ return (datum: Datum, opt: IAttributeOpt) => undefined as any;
+ }
+ if (stateStyle.referer) { // 处理引用样式
+ return stateStyle.referer.***_computeAttribute***(key, state);
+ }
+ if (!stateStyle.style) { // 处理空样式
+ return (datum: Datum, opt: IAttributeOpt) => stateStyle.style;
+ }
+ // =====================================================================
+ // **处理函数样式**:如果 stateStyle.style 是函数,调用该函数计算属性值。
+ if (typeof stateStyle.style === *'function'*) {
+ return (datum: Datum, opt: IAttributeOpt) =>
+ stateStyle.***style***(datum, this._attributeContext, opt, this.***getDataView***());
+ }
+ // **渐变色处理**,支持各个属性回调
+ if (GradientType.***includes***(stateStyle.style.gradient)) {
+ return this.***_computeGradientAttr***(stateStyle.style);
+ }
+ // **内外描边处理**,支持各个属性回调
+ if ([*'outerBorder'*, *'innerBorder'*].***includes***(key as string)) {
+ return this.***_computeBorderAttr***(stateStyle.style);
+ }
+ // **处理映射样式**:如果 stateStyle.style 包含映射关系(scale),根据数据字段映射值。
+ if (***isValidScaleType***(stateStyle.style.scale?.type)) {
+ return (datum: Datum, opt: IAttributeOpt) => {
+ let data = datum;
+ if (this.model.modelType === *'series'* && (this.model as ISeries).***getMarkData***) {
+ data = (this.model as ISeries).***getMarkData***(datum);
+ }
+ return stateStyle.style.scale.***scale***(data[stateStyle.style.field]);
+ };
+ }
+ // =====================================================================
+ // **处理常量样式**:如果 stateStyle.style 是常量值,直接返回该值。
+ return (datum: Datum, opt: IAttributeOpt) => {
+ return stateStyle.style;
+ };
+ }
+
+```
+Emphasize the `scale` style, which includes the data-to-visual mapping part. Continuing with the above example, we have already constructed a `scale` style:
+
+```xml
+style: {
+ scale,
+ field: 'score',
+ changeDomain: true,
+}
+
+```
+If we need to calculate the `y` coordinate of the graphic element, first obtain the data bound to the graphic element (see Chapter 5 VChart Data Processing), and then use the `scale` mapping object to input `data['score']` to get the corresponding `y` value. For more information about `scale`, see Chapter 7 VChart Scale.
+
+
+
+# This document was revised and organized by the following personnel
+[玄魂](https://github.com/xuanhun)
\ No newline at end of file
diff --git a/docs/assets/contributing/en/sourcecode/6.3-primitive-interaction-and-state-handling.md b/docs/assets/contributing/en/sourcecode/6.3-primitive-interaction-and-state-handling.md
new file mode 100644
index 0000000000..5b83bd8f2e
--- /dev/null
+++ b/docs/assets/contributing/en/sourcecode/6.3-primitive-interaction-and-state-handling.md
@@ -0,0 +1,383 @@
+---
+title: 6.3 Interaction and State Management of Primitives
+
+key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM
+---
+# Introduction
+
+VChart instances provide methods related to event listening, allowing you to meet business needs and interact with charts by listening to events. For all events supported by VChart, refer to the documentation [event api](https://www.visactor.io/vchart/api/API/event). You can listen to a specific event on a primitive in the following two ways:
+
+* Use `markName` for filtering, such as:
+
+
+```xml
+// 监听 bar 图元 上的 pointerdown 事件
+vchart.on('pointerdown', { markName: 'bar' }, (e: EventParams) => {
+ console.log('bar pointerdown', e);
+});
+
+```
+* Use the "level-type" rule with `{ level: 'mark', type: 'bar' }` for filtering, such as:
+
+```xml
+// 监听 bar 图元 上的 pointerdown 事件
+vchart.on('pointerdown', { level: 'mark', type: 'bar' }, (e: EventParams) => {
+ console.log('bar pointerdown', e);
+});
+
+```
+
+
+# States of Primitives
+
+In VChart, primitives can be in several states, and different states can display different styles. The built-in states are:
+
+* `default` default state;
+
+* `hover` / `hover_reverse` When the mouse hovers over a primitive, it enters the `hover` state, and other primitives enter the `hover_reverse` state;
+
+* `selected` / `selected_reverse` When the mouse clicks on a primitive, it enters the `selected` state, and other primitives enter the `selected_reverse` state;
+
+* `dimension_hover` / `dimension_hover_reverse` Dimension hover state, when the mouse pointer hovers over a certain section of the `x` axis area, the primitives in the area enter the `dimension_hover` state, and other primitives enter the `dimension_hover_reverse` state.
+
+##### State Definition
+
+The state types are defined in `packages/vchart/src/compile/mark/interface.ts` for convenient use later:
+
+```xml
+export enum STATE_VALUE_ENUM {
+ STATE_NORMAL = *'normal'*,
+ STATE_HOVER = *'hover'*,
+ STATE_HOVER_REVERSE = *'hover_reverse'*,
+ STATE_DIMENSION_HOVER = *'dimension_hover'*,
+ STATE_DIMENSION_HOVER_REVERSE = *'dimension_hover_reverse'*,
+ STATE_SELECTED = *'selected'*,
+ STATE_SELECTED_REVERSE = *'selected_reverse'*,
+}
+export enum STATE_VALUE_ENUM_REVERSE {
+ STATE_HOVER_REVERSE = *'hover_reverse'*,
+ STATE_DIMENSION_HOVER_REVERSE = *'dimension_hover_reverse'*,
+ STATE_SELECTED_REVERSE = *'selected_reverse'*
+}
+export type STATE_NORMAL = typeof STATE_VALUE_ENUM.STATE_NORMAL;
+export type STATE_HOVER = typeof STATE_VALUE_ENUM.STATE_HOVER;
+export type STATE_HOVER_REVERSE = typeof STATE_VALUE_ENUM.STATE_HOVER_REVERSE;
+export type STATE_CUSTOM = string;
+export type StateValueNot = STATE_HOVER_REVERSE | STATE_CUSTOM;
+export type StateValue = STATE_NORMAL | STATE_HOVER | STATE_CUSTOM;
+export type StateValueType = StateValue | StateValueNot;
+
+```
+Notice that there is also a `STATE_CUSTOM` state, which is a user-defined state. We will introduce the usage of custom states later.
+
+##### State Style Storage
+
+In order for the graphic elements to display different styles in different states, the structure for storing different state styles is defined in the graphic element interface IMarkRaw:
+
+```Typescript
+export type IMarkStateStyle = Record>>;
+
+export interface IMarkRaw extends ICompilableMark {
+ readonly stateStyle: IMarkStateStyle; // 存储状态样式
+ ...
+
+```
+These styles are defined by the user in `spec` and stored in `stateStyle` after parsing.
+
+
+
+# Interaction and State Switching of Primitives
+
+The states and corresponding styles of the primitives have been defined. So, how can we switch the state of the primitives through event interaction and display different styles? The general process is as follows:
+
+
+
+
+
+
+##### Register Event
+
+The entry point for interactive events is the `on` method of the `Event` class,
+
+```xml
+***on***(
+ eType: Evt,
+ query: EventQuery | EventCallback,
+ ***callback***?: EventCallback
+ )
+
+```
+* `eventType` is the type of event, such as `pointerdown`, `dimensionHover`, etc.
+
+* `query` is the event filter, such as element name, event level, component type, etc.
+
+* `callback` is the callback function triggered by the event.
+
+This will call the core function `register` of `EventDispatcher`:
+
+```xml
+ // vchart/src/event/event-dispatcher.ts
+ ***register***(eType: Evt, handler: EventHandler): this {
+ // 解析 query 配置并生成最终 handler 内容
+ this.***_parseQuery***(handler);
+
+ // 获取相应的bubble对象
+ const bubbles = this.***getEventBubble***(handler.filter?.source || Event_Source_Type.chart);
+ const listeners = this.***getEventListeners***(handler.filter?.source || Event_Source_Type.chart);
+ if (!bubbles.***get***(eType)) {
+ bubbles.***set***(eType, new ***Bubble***());
+ }
+
+ // 挂载事件监听
+ const bubble = bubbles.***get***(eType) as Bubble;
+ bubble.***addHandler***(handler, handler.filter?.level as EventBubbleLevel);
+ if (this.***_isValidEvent***(eType) && !listeners.***has***(eType)) {
+ const ***callback*** = this.***_onDelegate***.***bind***(this);
+ this._compiler.***addEventListener***(handler.filter?.source as EventSourceType, eType, ***callback***);
+ listeners.***set***(eType, ***callback***);
+ } else if (this.***_isInteractionEvent***(eType) && !listeners.***has***(eType)) {
+ const ***callback*** = this.***_onDelegateInteractionEvent***.***bind***(this);
+ this._compiler.***addEventListener***(handler.filter?.source as EventSourceType, eType, ***callback***);
+ listeners.***set***(eType, ***callback***);
+ }
+ return this;
+ }
+
+```
+* Parse the event configuration (`query`) passed by the user and generate the final event filter (`filter`).
+
+* Retrieve the corresponding event `Bubble` object from the internally maintained Map (such as `_viewBubbles`) based on the source (`chart`, `window`, or `canvas`) in the filter; if not present, create a new one.
+
+* Add the event handler (`handler`) to the Bubble; if there is no listener for this event type in the corresponding scenario, register a callback for the underlying syntax layer through the compiler (`this._compiler.addEventListener`).
+
+
**Bubble** is used to manage the collection of handlers for the same event at different bubbling levels (such as Mark, Model, Chart, VChart). It categorizes and stores event handlers according to the bubbling level and provides methods to add, remove, allow, or prohibit handlers, thereby achieving orderly invocation and management of events at each level.
+
+```Typescript
+export type BubbleNode = {
+ handler: EventHandler;
+ level: EventBubbleLevel;
+};
+
+export class Bubble {
+ private _map: Map, BubbleNode> = new ***Map***();
+ private _levelNodes: Map = new ***Map***();
+
+ constructor() {
+ this._levelNodes.***set***(Event_Bubble_Level.vchart, []);
+ this._levelNodes.***set***(Event_Bubble_Level.chart, []);
+ this._levelNodes.***set***(Event_Bubble_Level.model, []);
+ this._levelNodes.***set***(Event_Bubble_Level.mark, []);
+ }
+ ...... // 管理 Map 的增删改方法
+}
+
+```
+
+
+##### Response Event
+
+When an interaction event is triggered, another core function `dispatch` of `EventDispatcher` will be called:
+
+```Typescript
+ // vchart/src/event/event-dispatcher.ts
+ ***dispatch***(eType: Evt, params: EventParamsDefinition[Evt], level?: EventBubbleLevel): this {
+ // 默认事件类别为 view
+ const bubble = this.***getEventBubble***((params as BaseEventParams).source || Event_Source_Type.chart).***get***(
+ eType
+ ) as Bubble;
+ // 没有任何监听事件时,bubble 不存在
+ if (!bubble) {
+ return this;
+ }
+
+ // 事件冒泡逻辑:Mark -> Model -> Chart -> VChart
+ let stopBubble: boolean = false;
+
+ if (level) {
+ // 如果指定了 level,则直接处理,不进行冒泡
+ const handlers = bubble.***getHandlers***(level);
+ stopBubble = this.***_invoke***(handlers, eType, params);
+ } else {
+ const levels = [
+ Event_Bubble_Level.mark,
+ Event_Bubble_Level.model,
+ Event_Bubble_Level.chart,
+ Event_Bubble_Level.vchart
+ ];
+ let i = 0;
+
+ // Mark 级别的事件只包含对语法层代理的基础事件
+ while (!stopBubble && i < levels.length) {
+ stopBubble = this.***_invoke***(bubble.***getHandlers***(levels[i]), eType, params);
+ i++;
+ }
+ }
+
+ return this;
+ }
+
+```
+* Retrieve the corresponding `Bubble Map` based on the event source (source: view, window, canvas), and then extract the `Bubble` corresponding to the event type from it.
+
+* If a `Bubble` is found, obtain the registered handlers (`handlers`) according to the bubbling hierarchy (`Mark`→ `Model`→ `Chart`→ `VChart`) and call the `_invoke` method to execute them.
+
+* The `_invoke` method checks for matches based on the event filter (`filter`), and if it passes, it calls the callback function; if the callback returns a truthy value, it indicates preventing subsequent bubbling processing.
+
+
+
+##### State Switching
+
+Switch the state of the graphic elements in the mounted callback function. By default, vchart mounts handlers for `hover`, `selected`, `dimensionHover`/`dimensionClick` events. The first two are implemented and proxied by the `VGrammar` syntax layer, while events related to `dimension` are implemented in `VChart`. Taking `hover` as an example, first define and register the `dimensionHover` event:
+
+```Typescript
+// packages/vchart/src/event/events/dimension/dimension-hover.ts
+export class DimensionHoverEvent extends DimensionEvent {
+ private _cacheDimensionInfo: IDimensionInfo[] | null = null;
+ ***register***(eType: Evt, handler: EventHandler) {
+ this.***_callback*** = handler.***callback***;
+ this._eventDispatcher.***register***<*'pointermove'*>(*'pointermove'*, {
+ query: { ...handler.query, source: Event_Source_Type.chart },
+ ***callback***: this.***onMouseMove***
+ });
+ ...
+ }
+ private ***onMouseMove*** = (params: BaseEventParams) => {
+ if (!params) {
+ return;
+ }
+ const x = (params.event as any).viewX;
+ const y = (params.event as any).viewY;
+ const targetDimensionInfo = this.***getTargetDimensionInfo***(x, y);
+ if (targetDimensionInfo === null && this._cacheDimensionInfo !== null) {
+ // 鼠标移出某维度
+ this.***_callback***.***call***(null, {
+ ...params,
+ action: *'leave'*,
+ dimensionInfo: this._cacheDimensionInfo.***slice***()
+ });
+ this._cacheDimensionInfo = targetDimensionInfo;
+ } else if (
+ targetDimensionInfo !== null &&
+ (this._cacheDimensionInfo === null ||
+ targetDimensionInfo.length !== this._cacheDimensionInfo.length ||
+ targetDimensionInfo.***some***((info, i) => !***isSameDimensionInfo***(info, this._cacheDimensionInfo![i])))
+ ) {
+ // 鼠标移入某维度
+ this.***_callback***.***call***(null, {
+ ...params,
+ action: *'enter'*,
+ dimensionInfo: targetDimensionInfo.***slice***()
+ });
+ this._cacheDimensionInfo = targetDimensionInfo;
+ } else if (targetDimensionInfo !== null) {
+ // 鼠标在某维度上滑动
+ this.***_callback***.***call***(null, {
+ ...params,
+ action: *'move'*,
+ dimensionInfo: targetDimensionInfo.***slice***()
+ });
+ }
+ };
+
+ private ***onMouseOut*** = (params: BaseEventParams) => {
+ ...
+ }
+}
+
+```
+In `onMouseMove` is a callback function, which is the entry point for subsequent changes to the element state, where `_callback` is as follows:
+
+```Typescript
+ // packages/vchart/src/interaction/dimension-trigger.ts
+ private ***onHover*** = (params: DimensionEventParams) => {
+ switch (params.action) {
+ case *'enter'*:
+ // 清理之前的hover元素
+ const lastHover = this.interaction.***getEventElement***(STATE_VALUE_ENUM.STATE_DIMENSION_HOVER);
+ lastHover.***forEach***(e => this.interaction.***addEventElement***(STATE_VALUE_ENUM.STATE_DIMENSION_HOVER_REVERSE, e));
+ this.interaction.***clearEventElement***(STATE_VALUE_ENUM.STATE_DIMENSION_HOVER, false);
+ // 添加新的hover元素
+ const elements = this.***getEventElement***(params);
+ elements.***forEach***(el => this.interaction.***addEventElement***(STATE_VALUE_ENUM.STATE_DIMENSION_HOVER, el));
+ this.interaction.***reverseEventElement***(STATE_VALUE_ENUM.STATE_DIMENSION_HOVER);
+ break;
+ case *'leave'*:
+ // 清空所有元素
+ this.interaction.***clearEventElement***(STATE_VALUE_ENUM.STATE_DIMENSION_HOVER, true);
+ params = null;
+ break;
+ case *'click'*:
+ case *'move'*:
+ default:
+ break;
+ }
+ };
+
+```
+In simple terms, it involves adding or removing elements under corresponding events, and the specific change in element state is managed and implemented through the `Interaction` class. For example, in `addEventElement`, a new graphic element is added to the specified state and the element is marked for that state.
+
+
+```xml
+ ***addEventElement***(stateValue: StateValue, element: IElement) {
+ if (this._disableTriggerEvent) {
+ return;
+ }
+ if (!element.***getStates***().***includes***(stateValue)) {
+ element.***addState***(stateValue); // 改变元素内部图元样式
+ }
+ const list = this._stateElements.***get***(stateValue) ?? [];
+ list.***push***(element);
+ this._stateElements.***set***(stateValue, list);
+ }
+
+```
+Finally, the element changes the style of the internal graphic elements according to the state through the `addState` function, which calls the interface of the syntax layer `VGrammar`.
+
+
+
+# Custom State and Interaction Example
+
+As mentioned above, we can customize some states of the graphic elements, and `VChart` provides the `updateState` interface to update states, which allows us to achieve more requirements based on this. For example, we want to highlight the neighboring points in another style when `hovering` over a point.
+
+First, define a new state `as_neighbor` for the points in the `spec` and specify its style:
+
+```xml
+point: {
+ ...
+ state: {
+ as_neighbor: {
+ scaleX: 2,
+ scaleY: 2,
+ fill:"red",
+ fillOpacity: 0.5
+ }
+ }
+ ...
+ }
+
+```
+After that, register the event, when `hover` over a point, use `updateState` to set the state of its neighboring points to `as_neighbor`:
+
+```xml
+vchart.***on***(*'pointerover'*, { id: *'point-series'* }, e => {
+ // 找到邻居点
+ const selectedNeighbors: number[] = findNeighbors();
+ // 更新邻居点的状态 使用filter
+ vchart.***updateState***({
+ as_neighbor: {
+ ***filter***: datum => {
+ return selectedNeighbors.***includes***(datum.id);
+ }
+ }
+ });
+});
+
+```
+In this way, the state of the neighboring point is set to `as_neighbor`, and through the above process, the specified style is finally displayed (enlarged to 2 times, 0.5 transparency, and turned red):
+
+
+
+
+
+ # This document was revised and organized by the following person
+ [玄魂](https://github.com/xuanhun)
\ No newline at end of file
diff --git a/docs/assets/contributing/en/sourcecode/6.4-custom-primitives.md b/docs/assets/contributing/en/sourcecode/6.4-custom-primitives.md
new file mode 100644
index 0000000000..ec09e5c01b
--- /dev/null
+++ b/docs/assets/contributing/en/sourcecode/6.4-custom-primitives.md
@@ -0,0 +1,487 @@
+---
+title: 6.4 Custom Marks
+
+key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM
+---
+# Introduction
+
+When we have a large amount of data to display on a chart, we usually need to define a specific type of series (see section 3.2: `series`) and create marks within the series to represent the data. However, if we only need to display a little extra information, such as an image, a title, or a path, and do not want to create a separate series for it, we can use custom marks (`customMark`). Custom marks allow users to add custom annotations to the chart, such as adding some text, images, line segments, etc.
+
+# Types and Examples
+
+Currently, the supported types of custom marks are as follows:
+
+* `symbol`: Point graphic
+
+* `rule`: Line segment
+
+* `text`: Text
+
+* `rect`: Rectangle
+
+* `path`: Path
+
+* `arc`: Sector
+
+* `polygon`: Polygon
+
+* `group`: Group, which can contain other marks
+
+In the following example, in addition to the two data points in the chart (which can be considered a `scatter series`), three custom marks are added above, namely `text`, `symbol`, and `rule`.
+
+