From 6945f47476a0447f5d32d4b9718d47d7d9a7efc0 Mon Sep 17 00:00:00 2001 From: "lixuefei.1313" Date: Mon, 9 Mar 2026 10:35:59 +0800 Subject: [PATCH 01/24] chore: remove unused doc --- .../10.1-animation-concepts-and-types.md | 1595 ++++++++-------- .../10.1-animation-concepts-and-types.md | 1678 ++++++++--------- .../10.1-animation-concepts-and-types.md | 1678 ++++++++--------- docs/assets/guide/menu.json | 16 +- 4 files changed, 2416 insertions(+), 2551 deletions(-) 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 index e3486a4cb0..4403cae682 100644 --- 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 @@ -1,233 +1,223 @@ --- -title: 10.1 Concepts and Types of Animation +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/` +> 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) -`packages/vchart/src/series/line/animation` +1. Code Entry: `packages/vchart/src/animation/` -`packages/vchart/src/core/vchart` +`packages/vchart/src/series/line/animation` -`packages/vchart/src/core/interface` +`packages/vchart/src/core/vchart` -`packages/vchart/src/complie/mark` +`packages/vchart/src/core/interface` -1. Key Points Interpretation: +`packages/vchart/src/complie/mark` -1. Animation Classification (by execution timing, by effect) +1. Key Points Interpretation: -1. Overall Design of the Animation System +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 + +![](https://cdn.jsdelivr.net/gh/xuanhun/articles/visactor/sourcecode/img/OgJ0wqt4khXJtrbwW3Zc2521nOc.gif) + +### 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://cdn.jsdelivr.net/gh/xuanhun/articles/visactor/sourcecode/img/Ddzewl0jjhq1ksbmUlbc2WPSnig.gif) + +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. + + -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 - - -![](https://cdn.jsdelivr.net/gh/xuanhun/articles/visactor/sourcecode/img/OgJ0wqt4khXJtrbwW3Zc2521nOc.gif) - - - -### 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://cdn.jsdelivr.net/gh/xuanhun/articles/visactor/sourcecode/img/Ddzewl0jjhq1ksbmUlbc2WPSnig.gif) - -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. - +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. - +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. - +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. - +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. - +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; +animationNormal?: IMarkAnimateSpec; + +``` + +#### Chart **Exit Animation (**`**animationDisappear**`**)**: -``` - - -#### Chart **Exit Animation (**`**animationDisappear**`**)**: - -* The exit effect of elements when the chart is destroyed or hidden. - +- 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`. - + 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`. - +}; + +``` + +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) {/***/} +function barGrowOption(barParams: IBarAnimationParams, isOverall = true) {/***/} + +``` -``` - - -1. **Clip**: - -* Display the gradual appearance or disappearance of elements by clipping the area. - -* Example code: `registerCartesianGroupClipAnimation`. +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. -``` - - -1. **Wave**: - -* Special effects, such as wave effects in liquid graphics. - -* Example code: `Appear_Wave`. +- Example code: `Appear_Wave`. ```xml const Appear_Wave: IAnimationTypeConfig = { @@ -236,80 +226,74 @@ const Appear_Wave: IAnimationTypeConfig = { channel: { wave: { from: 0, to: 1 } } -}; - -``` - - -1. **Scale**: - -* The size of the element scales from one ratio to another. - -* Example code: `Appear_ScaleIn`. - +}; + +``` + +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. - - - - - - +}; + +``` + +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 - +> https://www.visactor.io/vchart/guide/tutorial_docs/VChart_Skill_Usage VChart Skill Usage 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. @@ -317,50 +301,50 @@ In the `VChart` class, the `animation` configuration item in `spec` (chart confi 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. +- 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. +- 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 `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. +- 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. +- 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 - - -
#### Example Code + + +
#### Example Code ```xml import { isMobile } from 'react-device-detect'; import { default as VChart } from '../../../../src/index'; // 1. 创建图表配置项与数据 const initialSpec = { - type: 'bar', - data: [ - { - id: 'barData', - values: [ - { month: 'January', sales: 22 }, - { month: 'February', sales: 13 }, - { month: 'March', sales: 25 }, - { month: 'April', sales: 29 }, - { month: 'May', sales: 38 } - ] - } - ], - xField: 'month', - yField: 'sales', - crosshair: { - xField: { visible: true } - }, - animation: true // 开启动画 +type: 'bar', +data: [ +{ +id: 'barData', +values: [ +{ month: 'January', sales: 22 }, +{ month: 'February', sales: 13 }, +{ month: 'March', sales: 25 }, +{ month: 'April', sales: 29 }, +{ month: 'May', sales: 38 } +] +} +], +xField: 'month', +yField: 'sales', +crosshair: { +xField: { visible: true } +}, +animation: true // 开启动画 }; // 2. 创建 VChart 实例 @@ -368,146 +352,147 @@ const vchart = new VChart(initialSpec, { dom: 'chart' }); // 3. 渲染图表 vchart.renderAsync().then(() => { - console.log('图表渲染完成'); +console.log('图表渲染完成'); }); // 4. 动画入场 setTimeout(() => { - console.log('动画入场'); +console.log('动画入场'); }, 1000); // 5. 数据更新(新增图元) setTimeout(() => { - const newData = [ - { month: 'June', sales: 45 }, - { month: 'July', sales: 50 } - ]; - vchart.updateDataSync('barData', newData, undefined, { reAnimate: true }); - console.log('新增图元'); +const newData = [ +{ month: 'June', sales: 45 }, +{ month: 'July', sales: 50 } +]; +vchart.updateDataSync('barData', newData, undefined, { reAnimate: true }); +console.log('新增图元'); }, 3000); // 6. 数据更新(图元更新) setTimeout(() => { - const updatedData = [ - { month: 'January', sales: 30 }, - { month: 'February', sales: 20 }, - { month: 'March', sales: 35 }, - { month: 'April', sales: 39 }, - { month: 'May', sales: 48 }, - { month: 'June', sales: 55 }, - { month: 'July', sales: 60 } - ]; - vchart.updateDataSync('barData', updatedData, undefined, { reAnimate: true }); - console.log('图元更新'); +const updatedData = [ +{ month: 'January', sales: 30 }, +{ month: 'February', sales: 20 }, +{ month: 'March', sales: 35 }, +{ month: 'April', sales: 39 }, +{ month: 'May', sales: 48 }, +{ month: 'June', sales: 55 }, +{ month: 'July', sales: 60 } +]; +vchart.updateDataSync('barData', updatedData, undefined, { reAnimate: true }); +console.log('图元更新'); }, 6000); // 7. 数据更新(图元退出) setTimeout(() => { - const remainingData = [ - { month: 'January', sales: 30 }, - { month: 'February', sales: 20 }, - { month: 'March', sales: 35 }, - { month: 'April', sales: 39 }, - { month: 'May', sales: 48 } - ]; - vchart.updateDataSync('barData', remainingData, undefined, { reAnimate: true }); - console.log('图元退出'); +const remainingData = [ +{ month: 'January', sales: 30 }, +{ month: 'February', sales: 20 }, +{ month: 'March', sales: 35 }, +{ month: 'April', sales: 39 }, +{ month: 'May', sales: 48 } +]; +vchart.updateDataSync('barData', remainingData, undefined, { reAnimate: true }); +console.log('图元退出'); }, 9000); // 8. 图元状态(state)的使用 setTimeout(() => { - vchart.updateState( - { - selected: { - style: { - fill: 'red' - } - } - }, - (series, mark, stateKey) => { - return mark.datum.sales > 40; - } - ); - console.log('图元状态更新'); +vchart.updateState( +{ +selected: { +style: { +fill: 'red' +} +} +}, +(series, mark, stateKey) => { +return mark.datum.sales > 40; +} +); +console.log('图元状态更新'); }, 12000); // 9. 图表退场 setTimeout(() => { - vchart.release(); - console.log('图表退场'); -}, 15000); - -```
#### 创建逻辑说明 -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` - +vchart.release(); +console.log('图表退场'); +}, 15000); + +````
#### 创建逻辑说明 +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` - +} + +```` + +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) { @@ -522,13 +507,14 @@ private _setNewSpec(spec: any, forceMerge?: boolean): boolean { 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` -``` -Next, the `initChartSpec` method initializes the chart specifications based on `spec`: - -File: `vchart.ts` Method: `initChartSpec` - ```xml private _initChartSpec(spec: any, actionSource: VChartRenderActionSource) { *// 如果用户注册了函数,在配置中替换相应函数名为函数内容* @@ -548,15 +534,16 @@ private _initChartSpec(spec: any, actionSource: VChartRenderActionSource) { 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` - +} + +``` + +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) { @@ -580,15 +567,16 @@ private _initChart(spec: any) { 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` - +} + +``` + +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) { @@ -600,19 +588,20 @@ private _updateAnimateState(initial?: boolean) { 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` - +} + +``` + +- **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; @@ -623,390 +612,360 @@ protected _renderSync = (option: IVChartRenderOption = {}) => { 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` - +}; + +``` + +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 +} + +``` + +### 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) diff --git a/docs/assets/contributing/zh/sourcecode/10.1-animation-concepts-and-types.md b/docs/assets/contributing/zh/sourcecode/10.1-animation-concepts-and-types.md index bb93e38cb6..18eb91d949 100644 --- a/docs/assets/contributing/zh/sourcecode/10.1-animation-concepts-and-types.md +++ b/docs/assets/contributing/zh/sourcecode/10.1-animation-concepts-and-types.md @@ -1,232 +1,224 @@ --- -title: 10.1 动画的概念和类型 +title: 10.1 动画的概念和类型 key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM ---- -> 10.1 动画的概念和类型 -> 分数:4 -> 1. 动画的概念和类型: -> 1. 其他参考文档: -> https://www.visactor.io/vchart/guide/tutorial_docs/Animation/Animation_Types -> -> [魔力之帧(下):VChart 动画编程实践在这篇文章中,我们将从一些常见的图表动画入手,详细介绍在 VChart 中的编 - 掘金](https://juejin.cn/post/7314829865633595443) - -1. 代码入口:`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. 解读重点: - -1. 动画分类(按执行时机,按效果) - -1. 动画系统的整体设计 - -# 动画的概念 - - - -在VChart中,动画是指在图表渲染过程中,通过视觉效果来增强数据展示的动态性和交互性。动画系统允许开发者配置和控制图表元素(如柱状图、饼图、折线图等)在不同状态下的过渡效果。 - -在 VisActor 中动画被视作为渲染阶段的修饰:动画配置与图形语法流程执行得到的图元视觉通道一起决定了渲染阶段的结果。动画的表现是具体图形元素在某一时间段内视觉通道属性的插值计算或者特殊计算逻辑,而动画配置描述了这一计算的触发时机以及执行时长。 - - - -## 动画的分类 - -#### 生命周期示范 - -![](https://cdn.jsdelivr.net/gh/xuanhun/articles/visactor/sourcecode/img/OgJ0wqt4khXJtrbwW3Zc2521nOc.gif) - - - -### 按执行时机分类 - -图表动画在 VChart 中根据状态场景(执行时机)会被区分为:**图表入场动画**、**数据更新动画**和**图表退场动画**。 - -1. **图表入场动画:**是指图表创建时的动画效果。 - -1. **数据更新动画:**当我们更新图表数据时,图元发生的属性动画则称为数据更新动画。分为:**新增图元动画**、**图元更新动画**和**退场图元动画、状态变更动画、任意时机触发的动画**。通常情况下,你不需要考虑如何控制这三种更新动画,因为 VChart 会在数据更新时,识别出新数据与上一次数据间的关联,从而正确执行更新动画。 - -1. **图表退场动画**:在某些场景下,我们可能需要移除图表。此时,我们可以为图表设置退场动画,让图表在除之前有一个平滑过渡的动画效果。 - -![](https://cdn.jsdelivr.net/gh/xuanhun/articles/visactor/sourcecode/img/Ddzewl0jjhq1ksbmUlbc2WPSnig.gif) - -https://visactor.io/vchart/guide/tutorial_docs/Animation/Animation_Types 动画教程文档 - -https://www.visactor.io/vchart/option/barChart#animationState 动画配置文档 - -#### 图表**入场动画 (**`**animationAppear**`**)**: - -* 在图表首次渲染时,元素从无到有的过渡效果。 - -* 示例代码:`animationAppear` 配置项用于定义图表入场动画。 - - - +--- + +> 10.1 动画的概念和类型 +> 分数:4 +> +> 1. 动画的概念和类型: +> 1. 其他参考文档: +> https://www.visactor.io/vchart/guide/tutorial_docs/Animation/Animation_Types +> +> [魔力之帧(下):VChart 动画编程实践在这篇文章中,我们将从一些常见的图表动画入手,详细介绍在 VChart 中的编 - 掘金](https://juejin.cn/post/7314829865633595443) + +1. 代码入口:`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. 解读重点: + +1. 动画分类(按执行时机,按效果) + +1. 动画系统的整体设计 + +# 动画的概念 + +在VChart中,动画是指在图表渲染过程中,通过视觉效果来增强数据展示的动态性和交互性。动画系统允许开发者配置和控制图表元素(如柱状图、饼图、折线图等)在不同状态下的过渡效果。 + +在 VisActor 中动画被视作为渲染阶段的修饰:动画配置与图形语法流程执行得到的图元视觉通道一起决定了渲染阶段的结果。动画的表现是具体图形元素在某一时间段内视觉通道属性的插值计算或者特殊计算逻辑,而动画配置描述了这一计算的触发时机以及执行时长。 + + + +## 动画的分类 + +#### 生命周期示范 + +![](https://cdn.jsdelivr.net/gh/xuanhun/articles/visactor/sourcecode/img/OgJ0wqt4khXJtrbwW3Zc2521nOc.gif) + +### 按执行时机分类 + +图表动画在 VChart 中根据状态场景(执行时机)会被区分为:**图表入场动画**、**数据更新动画**和**图表退场动画**。 + +1. **图表入场动画:**是指图表创建时的动画效果。 + +1. **数据更新动画:**当我们更新图表数据时,图元发生的属性动画则称为数据更新动画。分为:**新增图元动画**、**图元更新动画**和**退场图元动画、状态变更动画、任意时机触发的动画**。通常情况下,你不需要考虑如何控制这三种更新动画,因为 VChart 会在数据更新时,识别出新数据与上一次数据间的关联,从而正确执行更新动画。 + +1. **图表退场动画**:在某些场景下,我们可能需要移除图表。此时,我们可以为图表设置退场动画,让图表在除之前有一个平滑过渡的动画效果。 + +![](https://cdn.jsdelivr.net/gh/xuanhun/articles/visactor/sourcecode/img/Ddzewl0jjhq1ksbmUlbc2WPSnig.gif) + +https://visactor.io/vchart/guide/tutorial_docs/Animation/Animation_Types 动画教程文档 + +https://www.visactor.io/vchart/option/barChart#animationState 动画配置文档 + +#### 图表**入场动画 (**`**animationAppear**`**)**: + +- 在图表首次渲染时,元素从无到有的过渡效果。 + +- 示例代码:`animationAppear` 配置项用于定义图表入场动画。 + + + ```html - -
- - - -``` + +
+ + +``` + ```xml -animationAppear?: boolean | IStateAnimateSpec | IMarkAnimateSpec; - -``` -#### 数据更新动画 - -当我们更新图表数据时,图元发生的属性动画则称为更新动画。在 VChart 中,用户手动调用 `updateData` 接口会触发图表数据更新,另外,点击图例时也更新图表数据。更新动画分为三类:新增图元动画、图元更新动画和退场图元动画。 - -1. **新增图元动画 (**`**animationEnter**`**)**: - -* 新增图元动画是指当图表数据更新时,新添加数据应的图元的动画效果。 - -* 我们可以使用 `animationEnter` 配置来设置新增图元动画。 - +animationAppear?: boolean | IStateAnimateSpec | IMarkAnimateSpec; + +``` + +#### 数据更新动画 + +当我们更新图表数据时,图元发生的属性动画则称为更新动画。在 VChart 中,用户手动调用 `updateData` 接口会触发图表数据更新,另外,点击图例时也更新图表数据。更新动画分为三类:新增图元动画、图元更新动画和退场图元动画。 + +1. **新增图元动画 (**`**animationEnter**`**)**: + +- 新增图元动画是指当图表数据更新时,新添加数据应的图元的动画效果。 + +- 我们可以使用 `animationEnter` 配置来设置新增图元动画。 + ```xml -animationEnter?: boolean | ICommonStateAnimateSpec | IMarkAnimateSpec; - -``` - - -1. **图元更新动画 ( **`**animationUpdate**`**)**: - -* 图元更新动画是指当图表数据更新,原有数据对应的图元的更新动画效果。 - -* 我们可以使用 `animationUpdate` 配置来设置图元更新动画。 - +animationEnter?: boolean | ICommonStateAnimateSpec | IMarkAnimateSpec; + +``` + +1. **图元更新动画 ( **`**animationUpdate**`**)**: + +- 图元更新动画是指当图表数据更新,原有数据对应的图元的更新动画效果。 + +- 我们可以使用 `animationUpdate` 配置来设置图元更新动画。 + ```xml -animationUpdate?: boolean | ICommonStateAnimateSpec | IMarkAnimateSpec; - -``` - - -1. **退场图元动画 (**`**animationExit**`** )**: - -* 退图元动画是指当图表数据更新时,被删除数据所对应图元的动画效果。我们可以使用 `animationExit` 配置来设置退场图元动画。 - +animationUpdate?: boolean | ICommonStateAnimateSpec | IMarkAnimateSpec; + +``` + +1. **退场图元动画 (**`**animationExit**`** )**: + +- 退图元动画是指当图表数据更新时,被删除数据所对应图元的动画效果。我们可以使用 `animationExit` 配置来设置退场图元动画。 + ```xml -animationExit?: boolean | ICommonStateAnimateSpec | IMarkAnimateSpec; - -``` - - -1. 图元**状态切换动画 (State)**: - -* 当图表状态发生改变时的过渡效果。 - -* 示例代码:`animationState` 配置项用于定义状态切换动画。 - +animationExit?: boolean | ICommonStateAnimateSpec | IMarkAnimateSpec; + +``` + +1. 图元**状态切换动画 (State)**: + +- 当图表状态发生改变时的过渡效果。 + +- 示例代码:`animationState` 配置项用于定义状态切换动画。 + ```xml -animationState?: boolean | IStateAnimationConfig; - -``` - - -1. 常态**动画 (Normal)**:常用于循环 - -* 用于定义持续不断的动画效果。 - -* 示例代码:`animationNormal` 配置项用于定义循环动画。 - +animationState?: boolean | IStateAnimationConfig; + +``` + +1. 常态**动画 (Normal)**:常用于循环 + +- 用于定义持续不断的动画效果。 + +- 示例代码:`animationNormal` 配置项用于定义循环动画。 + ```xml -animationNormal?: IMarkAnimateSpec; - -``` - - -#### 图表**退场动画 (**`**animationDisappear**`**)**: - -* 在图表销毁或隐藏时,元素的退场效果。 - +animationNormal?: IMarkAnimateSpec; + +``` + +#### 图表**退场动画 (**`**animationDisappear**`**)**: + +- 在图表销毁或隐藏时,元素的退场效果。 + ```xml - animationDisappear?: boolean | ICommonStateAnimateSpec | IMarkAnimateSpec; - -``` -### 按效果分类 - -type 图元原子化 - -* 动画效果:动画效果描述了在某一特定的动画阶段中图元以怎样的方式执行渲染的变化。动画效果包括普通的视觉通道插值,例如竞速条形图中柱子颜色、宽度、位置的变化;同时动画效果也包含一些特殊的变化,例如下图中的图元形变。 - -1. **渐入渐出 (FadeIn/FadeOut)**: - -* 元素透明度从0到1或从1到0的变化。 - -* 示例代码:`Appear_FadeIn` 和 `Disappear_FadeOut`。 - + animationDisappear?: boolean | ICommonStateAnimateSpec | IMarkAnimateSpec; + +``` + +### 按效果分类 + +type 图元原子化 + +- 动画效果:动画效果描述了在某一特定的动画阶段中图元以怎样的方式执行渲染的变化。动画效果包括普通的视觉通道插值,例如竞速条形图中柱子颜色、宽度、位置的变化;同时动画效果也包含一些特殊的变化,例如下图中的图元形变。 + +1. **渐入渐出 (FadeIn/FadeOut)**: + +- 元素透明度从0到1或从1到0的变化。 + +- 示例代码:`Appear_FadeIn` 和 `Disappear_FadeOut`。 + ```xml const Appear_FadeIn: IAnimationTypeConfig = { type: 'fadeIn' -}; - -``` - - -1. **生长 (Grow)**: - -* 元素从某个初始尺寸逐渐增长到最终尺寸。 - -* 示例代码:`barGrowOption` 和 `pieGrowOption`。 - +}; + +``` + +1. **生长 (Grow)**: + +- 元素从某个初始尺寸逐渐增长到最终尺寸。 + +- 示例代码:`barGrowOption` 和 `pieGrowOption`。 + ```xml -function barGrowOption(barParams: IBarAnimationParams, isOverall = true) {/***/} - -``` - - -1. **裁剪 (Clip)**: - -* 通过裁剪区域来显示元素的逐步出现或消失。 - -* 示例代码:`registerCartesianGroupClipAnimation`。 - +function barGrowOption(barParams: IBarAnimationParams, isOverall = true) {/***/} + +``` + +1. **裁剪 (Clip)**: + +- 通过裁剪区域来显示元素的逐步出现或消失。 + +- 示例代码:`registerCartesianGroupClipAnimation`。 + ```xml const registerCartesianGroupClipAnimation = () => { Factory.registerAnimation('cartesianGroupClip', (params?: ICartesianGroupAnimationParams) => {/***/}); -}; - -``` - - -1. **波浪 (Wave)**: - -* 特殊效果,如液态图中的波浪效果。 - -* 示例代码:`Appear_Wave`。 - +}; + +``` + +1. **波浪 (Wave)**: + +- 特殊效果,如液态图中的波浪效果。 + +- 示例代码:`Appear_Wave`。 + ```xml const Appear_Wave: IAnimationTypeConfig = { duration: 2000, @@ -234,131 +226,125 @@ const Appear_Wave: IAnimationTypeConfig = { channel: { wave: { from: 0, to: 1 } } -}; - -``` - - -1. **缩放 (Scale)**: - -* 元素大小从一个比例缩放到另一个比例。 - -* 示例代码:`Appear_ScaleIn`。 - +}; + +``` + +1. **缩放 (Scale)**: + +- 元素大小从一个比例缩放到另一个比例。 + +- 示例代码:`Appear_ScaleIn`。 + ```xml const Appear_ScaleIn: IAnimationTypeConfig = { type: 'growCenterIn' -}; - -``` -更多动画效果的属性和配置可参考https://visactor.com/vchart/guide/tutorial_docs/Animation/Animation_Attributes_and_Settings - -## 动画系统的设计 - -### 简单柱状图动画配置 - - - -下面以创建一个简单的柱状图为例,说明如何使用VChart的动画系统来实现基本动画效果的原理。 - - - - - +}; + +``` + +更多动画效果的属性和配置可参考https://visactor.com/vchart/guide/tutorial_docs/Animation/Animation_Attributes_and_Settings + +## 动画系统的设计 + +### 简单柱状图动画配置 + +下面以创建一个简单的柱状图为例,说明如何使用VChart的动画系统来实现基本动画效果的原理。 + + + ```html - - -
- - - -``` -> 如何创建一个基础VChart可以参考以下文档 -> https://www.visactor.io/vchart/guide/tutorial_docs/Getting_Started 快速上手 -> https://www.visactor.io/vchart/guide/tutorial_docs/Basic/How_to_Import_VChart 导入VChart -> https://www.visactor.io/vchart/guide/tutorial_docs/Basic/A_Basic_Spec 基础配置 -> https://www.visactor.io/vchart/guide/tutorial_docs/Basic/DeepSeek_With_Cursor DeepSeek+Cursor助力 - - - -在 `VChart` 类中,`spec`(图表配置)中的 `animation` 配置项用于控制图表的动画行为。具体来说,`animation` 配置项可以定义图表在不同状态下的动画效果,例如入场动画、更新动画、退出动画等。 - -#### `animation` 配置的作用 - -1. **定义动画行为**: - -* `animation` 配置项可以包含多个子属性,如 `appear`、`enter`、`update`、`exit` 和 `disappear`,分别对应不同的动画场景。 - -* 每个子属性可以进一步配置动画的持续时间 (`duration`)、缓动函数 (`easing`)、是否逐个执行 (`oneByOne`) 等参数。 - -1. **控制动画开关**: - -* 如果将 `animation` 设置为 `false`,则禁用所有动画效果。 - -* 如果设置为 `true` 或者提供具体的配置对象,则启用相应的动画效果。 - -1. **传递给底层组件**: - -* `VChart` 类会将 `animation` 配置传递给内部的 `Compiler` 和 `Chart` 实例,这些实例会根据配置来决定是否应用动画以及如何应用动画。 - -### 柱状图执行动画示例说明 - - - -
#### 示例代码 + + +
+ + +``` + +> 如何创建一个基础VChart可以参考以下文档 +> https://www.visactor.io/vchart/guide/tutorial_docs/Getting_Started 快速上手 +> https://www.visactor.io/vchart/guide/tutorial_docs/Basic/How_to_Import_VChart 导入VChart +> https://www.visactor.io/vchart/guide/tutorial_docs/Basic/A_Basic_Spec 基础配置 +> https://www.visactor.io/vchart/guide/tutorial_docs/VChart_Skill_Usage VChart Skill 使用 + +在 `VChart` 类中,`spec`(图表配置)中的 `animation` 配置项用于控制图表的动画行为。具体来说,`animation` 配置项可以定义图表在不同状态下的动画效果,例如入场动画、更新动画、退出动画等。 + +#### `animation` 配置的作用 + +1. **定义动画行为**: + +- `animation` 配置项可以包含多个子属性,如 `appear`、`enter`、`update`、`exit` 和 `disappear`,分别对应不同的动画场景。 + +- 每个子属性可以进一步配置动画的持续时间 (`duration`)、缓动函数 (`easing`)、是否逐个执行 (`oneByOne`) 等参数。 + +1. **控制动画开关**: + +- 如果将 `animation` 设置为 `false`,则禁用所有动画效果。 + +- 如果设置为 `true` 或者提供具体的配置对象,则启用相应的动画效果。 + +1. **传递给底层组件**: + +- `VChart` 类会将 `animation` 配置传递给内部的 `Compiler` 和 `Chart` 实例,这些实例会根据配置来决定是否应用动画以及如何应用动画。 + +### 柱状图执行动画示例说明 + + + +
#### 示例代码 ```xml import { isMobile } from 'react-device-detect'; import { default as VChart } from '../../../../src/index'; // 1. 创建图表配置项与数据 const initialSpec = { - type: 'bar', - data: [ - { - id: 'barData', - values: [ - { month: 'January', sales: 22 }, - { month: 'February', sales: 13 }, - { month: 'March', sales: 25 }, - { month: 'April', sales: 29 }, - { month: 'May', sales: 38 } - ] - } - ], - xField: 'month', - yField: 'sales', - crosshair: { - xField: { visible: true } - }, - animation: true // 开启动画 +type: 'bar', +data: [ +{ +id: 'barData', +values: [ +{ month: 'January', sales: 22 }, +{ month: 'February', sales: 13 }, +{ month: 'March', sales: 25 }, +{ month: 'April', sales: 29 }, +{ month: 'May', sales: 38 } +] +} +], +xField: 'month', +yField: 'sales', +crosshair: { +xField: { visible: true } +}, +animation: true // 开启动画 }; // 2. 创建 VChart 实例 @@ -366,146 +352,147 @@ const vchart = new VChart(initialSpec, { dom: 'chart' }); // 3. 渲染图表 vchart.renderAsync().then(() => { - console.log('图表渲染完成'); +console.log('图表渲染完成'); }); // 4. 动画入场 setTimeout(() => { - console.log('动画入场'); +console.log('动画入场'); }, 1000); // 5. 数据更新(新增图元) setTimeout(() => { - const newData = [ - { month: 'June', sales: 45 }, - { month: 'July', sales: 50 } - ]; - vchart.updateDataSync('barData', newData, undefined, { reAnimate: true }); - console.log('新增图元'); +const newData = [ +{ month: 'June', sales: 45 }, +{ month: 'July', sales: 50 } +]; +vchart.updateDataSync('barData', newData, undefined, { reAnimate: true }); +console.log('新增图元'); }, 3000); // 6. 数据更新(图元更新) setTimeout(() => { - const updatedData = [ - { month: 'January', sales: 30 }, - { month: 'February', sales: 20 }, - { month: 'March', sales: 35 }, - { month: 'April', sales: 39 }, - { month: 'May', sales: 48 }, - { month: 'June', sales: 55 }, - { month: 'July', sales: 60 } - ]; - vchart.updateDataSync('barData', updatedData, undefined, { reAnimate: true }); - console.log('图元更新'); +const updatedData = [ +{ month: 'January', sales: 30 }, +{ month: 'February', sales: 20 }, +{ month: 'March', sales: 35 }, +{ month: 'April', sales: 39 }, +{ month: 'May', sales: 48 }, +{ month: 'June', sales: 55 }, +{ month: 'July', sales: 60 } +]; +vchart.updateDataSync('barData', updatedData, undefined, { reAnimate: true }); +console.log('图元更新'); }, 6000); // 7. 数据更新(图元退出) setTimeout(() => { - const remainingData = [ - { month: 'January', sales: 30 }, - { month: 'February', sales: 20 }, - { month: 'March', sales: 35 }, - { month: 'April', sales: 39 }, - { month: 'May', sales: 48 } - ]; - vchart.updateDataSync('barData', remainingData, undefined, { reAnimate: true }); - console.log('图元退出'); +const remainingData = [ +{ month: 'January', sales: 30 }, +{ month: 'February', sales: 20 }, +{ month: 'March', sales: 35 }, +{ month: 'April', sales: 39 }, +{ month: 'May', sales: 48 } +]; +vchart.updateDataSync('barData', remainingData, undefined, { reAnimate: true }); +console.log('图元退出'); }, 9000); // 8. 图元状态(state)的使用 setTimeout(() => { - vchart.updateState( - { - selected: { - style: { - fill: 'red' - } - } - }, - (series, mark, stateKey) => { - return mark.datum.sales > 40; - } - ); - console.log('图元状态更新'); +vchart.updateState( +{ +selected: { +style: { +fill: 'red' +} +} +}, +(series, mark, stateKey) => { +return mark.datum.sales > 40; +} +); +console.log('图元状态更新'); }, 12000); // 9. 图表退场 setTimeout(() => { - vchart.release(); - console.log('图表退场'); -}, 15000); - -```
#### 创建逻辑说明 -1. **创建图表配置项与数据**: -1. **创建 VChart 实例**: -1. **渲染图表**: -1. **动画入场**: -1. **数据更新(新增图元)**: -1. **数据更新(图元更新)**: -1. **数据更新(图元退出)**: -1. **图元状态(state)的使用**: -1. **图表退场**: - -
-* 定义了一个初始的图表配置项`initialSpec`,其中包含图表类型、数据、坐标轴字段和动画配置。 - -* 数据部分包含了一个`barData`的数据集,初始包含5个月的销售数据。 - -* 使用`initialSpec`和DOM容器`chart`创建一个VChart实例。 - -* 调用`renderAsync`方法异步渲染图表。图表渲染完成后,会触发动画入场效果。 - -* 在渲染完成后,通过`setTimeout`模拟动画入场。实际动画效果由VChart内部处理。 - -* 在3秒后,通过`updateDataSync`方法新增两个月的销售数据。`reAnimate: true`参数确保新增数据时有动画效果。 - -* 在6秒后,通过`updateDataSync`方法更新所有图元的数据。`reAnimate: true`参数确保更新数据时有动画效果。 - -* 在9秒后,通过`updateDataSync`方法移除两个月的销售数据。`reAnimate: true`参数确保移除数据时有动画效果。 - -* 在12秒后,通过`updateState`方法更新图元的状态。这里设置了一个`selected`状态,当图元的`sales`值大于40时,图元的填充颜色变为红色。 - -* 在15秒后,通过`release`方法销毁图表实例,图表退场。 - ---- - - -
#### 动画流程图 -
#### 流程说明 -1. **创建图表配置项与数据**:定义初始图表配置和数据。 -1. **创建 VChart 实例**:使用配置和DOM容器创建VChart实例。 -1. **渲染图表**:调用`renderAsync`方法渲染图表,触发动画入场效果。 -1. **动画入场**:图表渲染完成后,自动触发入场动画。 -1. **数据更新(新增图元)**:通过`updateDataSync`方法新增数据,触发新增动画。 -1. **数据更新(图元更新)**:通过`updateDataSync`方法更新数据,触发更新动画。 -1. **数据更新(图元退出)**:通过`updateDataSync`方法移除数据,触发退出动画。 -1. **图元状态(state)的使用**:通过`updateState`方法更新图元状态,设置特定条件下的样式。 -1. **图表退场**:通过`release`方法销毁图表实例,图表退场。 - -
-### 源码实现流程 - -1. **初始化 VChart 实例** - -当你创建一个 `VChart` 实例并传入 `spec` 时,构造函数会处理 `animation` 配置: - -文件:`vchart.ts` 方法:`constructor` - +vchart.release(); +console.log('图表退场'); +}, 15000); + +````
#### 创建逻辑说明 +1. **创建图表配置项与数据**: +1. **创建 VChart 实例**: +1. **渲染图表**: +1. **动画入场**: +1. **数据更新(新增图元)**: +1. **数据更新(图元更新)**: +1. **数据更新(图元退出)**: +1. **图元状态(state)的使用**: +1. **图表退场**: + +
+* 定义了一个初始的图表配置项`initialSpec`,其中包含图表类型、数据、坐标轴字段和动画配置。 + +* 数据部分包含了一个`barData`的数据集,初始包含5个月的销售数据。 + +* 使用`initialSpec`和DOM容器`chart`创建一个VChart实例。 + +* 调用`renderAsync`方法异步渲染图表。图表渲染完成后,会触发动画入场效果。 + +* 在渲染完成后,通过`setTimeout`模拟动画入场。实际动画效果由VChart内部处理。 + +* 在3秒后,通过`updateDataSync`方法新增两个月的销售数据。`reAnimate: true`参数确保新增数据时有动画效果。 + +* 在6秒后,通过`updateDataSync`方法更新所有图元的数据。`reAnimate: true`参数确保更新数据时有动画效果。 + +* 在9秒后,通过`updateDataSync`方法移除两个月的销售数据。`reAnimate: true`参数确保移除数据时有动画效果。 + +* 在12秒后,通过`updateState`方法更新图元的状态。这里设置了一个`selected`状态,当图元的`sales`值大于40时,图元的填充颜色变为红色。 + +* 在15秒后,通过`release`方法销毁图表实例,图表退场。 + +--- + + +
#### 动画流程图 +
#### 流程说明 +1. **创建图表配置项与数据**:定义初始图表配置和数据。 +1. **创建 VChart 实例**:使用配置和DOM容器创建VChart实例。 +1. **渲染图表**:调用`renderAsync`方法渲染图表,触发动画入场效果。 +1. **动画入场**:图表渲染完成后,自动触发入场动画。 +1. **数据更新(新增图元)**:通过`updateDataSync`方法新增数据,触发新增动画。 +1. **数据更新(图元更新)**:通过`updateDataSync`方法更新数据,触发更新动画。 +1. **数据更新(图元退出)**:通过`updateDataSync`方法移除数据,触发退出动画。 +1. **图元状态(state)的使用**:通过`updateState`方法更新图元状态,设置特定条件下的样式。 +1. **图表退场**:通过`release`方法销毁图表实例,图表退场。 + +
+### 源码实现流程 + +1. **初始化 VChart 实例** + +当你创建一个 `VChart` 实例并传入 `spec` 时,构造函数会处理 `animation` 配置: + +文件:`vchart.ts` 方法:`constructor` + ```xml constructor(spec: ISpec, options: IInitOption) { this._option = mergeOrigin(this._option, { animation: (spec as any).animation !== false }, options); *// ...* -} - -``` -这段代码确保了如果 `spec` 中没有显式禁用动画(即 `animation !== false`),则启用动画。 - -1. 设置新 spec 并初始化图表 - -在 `VChart` 类中,`_setNewSpec` 方法用于设置新的 `spec`,并将其转换为内部使用的格式: - -文件:`vchart.ts` 方法:`_setNewSpec` - +} + +```` + +这段代码确保了如果 `spec` 中没有显式禁用动画(即 `animation !== false`),则启用动画。 + +1. 设置新 spec 并初始化图表 + +在 `VChart` 类中,`_setNewSpec` 方法用于设置新的 `spec`,并将其转换为内部使用的格式: + +文件:`vchart.ts` 方法:`_setNewSpec` + ```xml private _setNewSpec(spec: any, forceMerge?: boolean): boolean { if (!spec) { @@ -520,13 +507,14 @@ private _setNewSpec(spec: any, forceMerge?: boolean): boolean { this._originalSpec = spec; this._spec = this._getSpecFromOriginalSpec(); return true; -} +} + +``` + +接着,`_initChartSpec` 方法会根据 `spec` 初始化图表规格: + +文件:`vchart.ts` 方法:`_initChartSpec` -``` -接着,`_initChartSpec` 方法会根据 `spec` 初始化图表规格: - -文件:`vchart.ts` 方法:`_initChartSpec` - ```xml private _initChartSpec(spec: any, actionSource: VChartRenderActionSource) { *// 如果用户注册了函数,在配置中替换相应函数名为函数内容* @@ -546,15 +534,16 @@ private _initChartSpec(spec: any, actionSource: VChartRenderActionSource) { this._specInfo = this._chartSpecTransformer?.transformModelSpec(this._spec); *// 插件生命周期* this._chartPluginApply('onAfterModelSpecTransform', this._spec, this._specInfo, actionSource); -} - -``` -1. 创建和初始化 Chart 实例 - -在 `_initChart` 方法中,创建并初始化图表实例: - -文件:`vchart.ts` 方法:`_initChart` - +} + +``` + +1. 创建和初始化 Chart 实例 + +在 `_initChart` 方法中,创建并初始化图表实例: + +文件:`vchart.ts` 方法:`_initChart` + ```xml private _initChart(spec: any) { if (!this._compiler) { @@ -578,15 +567,16 @@ private _initChart(spec: any) { chart, vchart: this }); -} - -``` -1. 更新动画状态 - -当图表需要重新渲染或更新时,`_updateAnimateState` 方法会被调用来更新动画状态: - -文件:`vchart.ts` 方法:`_updateAnimateState` - +} + +``` + +1. 更新动画状态 + +当图表需要重新渲染或更新时,`_updateAnimateState` 方法会被调用来更新动画状态: + +文件:`vchart.ts` 方法:`_updateAnimateState` + ```xml private _updateAnimateState(initial?: boolean) { if (this._option.animation) { @@ -598,19 +588,20 @@ private _updateAnimateState(initial?: boolean) { component.animate?.updateAnimateState(animationState, true); }); } -} - -``` -* **初始状态**:如果 `initial` 为 `true`,则设置动画状态为 `AnimationStateEnum.appear`(入场动画)。 - -* **更新状态**:否则,设置为 `AnimationStateEnum.update`(更新动画)。 - -1. 渲染图表 - -在 `renderSync` 和 `renderAsync` 方法中,`animation` 配置会被传递给编译器进行渲染: - -文件:`vchart.ts` 方法:`_renderSync` - +} + +``` + +- **初始状态**:如果 `initial` 为 `true`,则设置动画状态为 `AnimationStateEnum.appear`(入场动画)。 + +- **更新状态**:否则,设置为 `AnimationStateEnum.update`(更新动画)。 + +1. 渲染图表 + +在 `renderSync` 和 `renderAsync` 方法中,`animation` 配置会被传递给编译器进行渲染: + +文件:`vchart.ts` 方法:`_renderSync` + ```xml protected _renderSync = (option: IVChartRenderOption = {}) => { const self = this as unknown as IVChart; @@ -621,391 +612,360 @@ protected _renderSync = (option: IVChartRenderOption = {}) => { this._compiler?.render(option.morphConfig); this._afterRender(); return self; -}; - -``` -1. 动画状态的更新 - -在 `updateSpec` 和 `updateCustomConfigAndRerender` 方法中,`reAnimate` 标志用于决定是否重新触发动画: - -文件:`vchart.ts` 方法:`updateSpec` 和 `updateCustomConfigAndRerender` - +}; + +``` + +1. 动画状态的更新 + +在 `updateSpec` 和 `updateCustomConfigAndRerender` 方法中,`reAnimate` 标志用于决定是否重新触发动画: + +文件:`vchart.ts` 方法:`updateSpec` 和 `updateCustomConfigAndRerender` + ```xml if (userUpdateOptions?.reAnimate) { this.stopAnimation(); this._updateAnimateState(true); -} - -``` - - -### 动画系统设计概述 - - - -VChart的动画系统设计遵循模块化、可扩展和易于配置的原则,旨在为开发者提供一个灵活且强大的工具来创建丰富的动画效果。以下是该系统的几个关键组成部分及其工作原理: - -### 原理 - -#### 1. 动画接口与抽象 - - - -* **IAnimate 接口**:定义了所有动画必须实现的方法和属性,包括获取唯一的ID、更新动画状态以及获取状态信号名称。 - -* - -* **IAnimationSpec 接口**:规定了动画配置的结构,涵盖了从入场到退场的各种动画设置。 - - - -classDiagram - - class AnimationStateEnum { - - --枚举-- - - 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 { - - --属性-- - - -_stateMap: IAnimateState & StateMap - - +id: number - - --方法-- - - +updateAnimateState(state: AnimationStateEnum, noRender?: boolean): void - - +getAnimationStateSignalName(): string - - +constructor() - - } - - - - class MarkAnimationSpec { - - --属性-- - - appear: IAnimationConfig - - enter: IAnimationConfig - - update: IAnimationConfig[] - - exit: IAnimationConfig - - disappear: IAnimationConfig - - } - - - - class 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 - - } - - - - class IStateAnimateSpec { - - --属性-- - - duration?: number - - delay?: number - - easing?: EasingType - - oneByOne?: boolean - - preset?: Preset | false - - } - - - - class ICommonStateAnimateSpec { - - --属性-- - - duration?: number - - delay?: number - - easing?: EasingType - - oneByOne?: boolean - - } - - - - class IMorphSeriesSpec { - - --属性-- - - enable?: boolean - - morphKey?: string - - morphElementKey?: string - - } - - - - class IAnimateState { - - --属性-- - - animationState: { callback: (datum: any, element: IElement) => AnimationStateEnum } - - } - - - - class IAnimationConfig { - - --属性-- - - type?: string - - channel?: string - - custom?: Function - - customParameters?: Function - - oneByOne?: boolean | number - - duration?: number - - easing?: EasingType - - delay?: number - - delayAfter?: number - - } - - - - % 关系 - - AnimationStateEnum "1" --|> "多" AnimateManager: 使用 - - AnimateManager "1" --|> "1" IAnimate: 实现 - - AnimateManager "1" -- "1" ICartesianGroupAnimationParams: 依赖 - - IAnimationSpec "1" -- "多" spec.ts: 定义于 - - MarkAnimationSpec "1" -- "1" config.ts: 由 config.ts 使用 - - IAnimationConfig "1" -- "多" utils.ts: 由 utils.ts 处理 - - IStateAnimateSpec "1" -- "1" ICommonStateAnimateSpec: 继承 - - IAnimationSpec "1" -- "1" IStateAnimateSpec: 关联 - - IAnimationSpec "1" -- "1" IMorphSeriesSpec: 关联 - - IAnimateState "1" -- "1" AnimateManager: 内部使用 - - IAnimationConfig "1" -- "1" ICommonStateAnimateSpec: 继承 - - - -#### 2. 动画管理器 - - - -* **AnimateManager 类**:继承自 `StateManager` 并实现了 `IAnimate` 接口,负责管理动画的状态,并提供方法来根据传入的状态更新动画。它处理动画状态的更新和检索,并根据不同状态更新动画状态。 - - - -#### 3. 工厂模式 - - - -* **Factory 类**:用于注册新的动画类型,允许将自定义动画逻辑添加到图表组件中。通过静态方法 `registerAnimation`,可以将特定类型的动画与其配置关联起来,方便后续调用。 - - - -#### 4. 动画配置生成 - - - -* **animationConfig 函数**:根据默认配置和用户提供的配置生成最终的动画配置。这个函数遍历所有的动画状态(如出现、进入、更新等),并根据用户配置或默认配置构建出完整的动画配置对象。 - - - -#### 5. 动画任务接口 - - - -* **IAnimationTask 接口**:定义了一个动画任务的数据结构,这对于理解复杂的动画序列非常重要。每个任务包含时间偏移、动作队列和后继任务列表,形成了一种链式动画执行机制。 - - - -#### 6. 动画的具体实现 - - - -* 每个具体的图表系列(如柱状图、饼图、散点图等)都有各自的动画实现文件,这些文件中包含了针对该系列的预设动画函数。例如,柱状图可能有生长动画、淡入动画等;饼图则可能有扇区展开动画等。 - - - - - -通过上述步骤,我们已经完成了一个简单但完整的动画流程创建。在这个过程中,我们利用了VChart动画系统的模块化设计,分别对图表配置、动画注册、实例化图表、数据更新以及动画状态管理进行了处理。这种设计不仅让代码更加清晰易读,同时也提高了系统的灵活性和可维护性。开发者可以根据实际需求轻松地定制不同类型的动画效果,从而提升用户体验。 - - - -为了更好地理解和解读这些源码文件,建议按照以下顺序阅读: - -1. `**interface.ts**` - -* **原因**:该文件定义了动画模块中的核心类型和接口,如 `AnimationStateEnum`、`IAnimateState` 和 `IAnimate` 等。理解这些类型和接口是后续代码的基础。 - -* **重点内容**: - -* 动画状态枚举 `AnimationStateEnum` - -* 动画状态接口 `IAnimateState` - -* 动画接口 `IAnimate` - -1. `**spec.ts**` - -* **原因**:该文件定义了动画配置的规范,包括 `ICommonStateAnimateSpec`、`IStateAnimateSpec` 和 `IAnimationSpec` 等。这些规范在实际动画配置中会被使用,因此需要先了解它们的结构。 - -* **重点内容**: - -* 动画配置的通用属性 `ICommonStateAnimateSpec` - -* 动画状态配置 `IStateAnimateSpec` - -* 动画规范 `IAnimationSpec` - -1. `**config.ts**` - -* **原因**:该文件提供了默认的动画配置和一些预设的动画注册函数。理解这些默认配置有助于理解如何自定义动画配置。 - -* **重点内容**: - -* 默认动画配置 `DEFAULT_ANIMATION_CONFIG` - -* 预设动画注册函数(如 `registerScaleInOutAnimation`、`registerFadeInOutAnimation` 等) - -1. `**utils.ts**` - -* **原因**:该文件包含了许多辅助函数,用于生成和处理动画配置。理解这些函数的工作原理可以帮助你更好地理解动画配置是如何被应用的。 - -* **重点内容**: - -* 生成动画配置的函数 `animationConfig` - -* 处理用户动画配置的函数 `userAnimationConfig` - -* 辅助函数(如 `produceOneByOne`、`shouldMarkDoMorph` 等) - -1. `**animate-manager.ts**` - -* **原因**:该文件实现了 `AnimateManager` 类,它是管理动画的核心类。理解这个类的实现可以让你知道动画是如何被管理和更新的。 - -* **重点内容**: - -* `AnimateManager` 类的实现 - -* 更新动画状态的方法 `updateAnimateState` - -* 获取动画状态信号名称的方法 `getAnimationStateSignalName` - -### 总结 - -按照上述顺序阅读这些文件,可以逐步建立起对整个动画模块的理解。从基础的类型和接口开始,逐步深入到具体的配置和实现细节,最终理解动画是如何被管理和应用的。 - -### 阅读顺序总结 - -* `**interface.ts**` 核心类型和接口 - -* `**spec.ts**` 动画配置规范 - -* `**config.ts**` 默认配置和预设动画 - -* `**utils.ts**` 辅助函数和配置生成 - -* `**animate-manager.ts**`动画管理类实现 - - # 本文档由以下人员修正整理 - [玄魂](https://github.com/xuanhun) \ No newline at end of file +} + +``` + +### 动画系统设计概述 + +VChart的动画系统设计遵循模块化、可扩展和易于配置的原则,旨在为开发者提供一个灵活且强大的工具来创建丰富的动画效果。以下是该系统的几个关键组成部分及其工作原理: + +### 原理 + +#### 1. 动画接口与抽象 + +- **IAnimate 接口**:定义了所有动画必须实现的方法和属性,包括获取唯一的ID、更新动画状态以及获取状态信号名称。 + +- + +- **IAnimationSpec 接口**:规定了动画配置的结构,涵盖了从入场到退场的各种动画设置。 + +classDiagram + + class AnimationStateEnum { + + --枚举-- + + 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 { + + --属性-- + + -_stateMap: IAnimateState & StateMap + + +id: number + + --方法-- + + +updateAnimateState(state: AnimationStateEnum, noRender?: boolean): void + + +getAnimationStateSignalName(): string + + +constructor() + + } + + + + class MarkAnimationSpec { + + --属性-- + + appear: IAnimationConfig + + enter: IAnimationConfig + + update: IAnimationConfig[] + + exit: IAnimationConfig + + disappear: IAnimationConfig + + } + + + + class 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 + + } + + + + class IStateAnimateSpec { + + --属性-- + + duration?: number + + delay?: number + + easing?: EasingType + + oneByOne?: boolean + + preset?: Preset | false + + } + + + + class ICommonStateAnimateSpec { + + --属性-- + + duration?: number + + delay?: number + + easing?: EasingType + + oneByOne?: boolean + + } + + + + class IMorphSeriesSpec { + + --属性-- + + enable?: boolean + + morphKey?: string + + morphElementKey?: string + + } + + + + class IAnimateState { + + --属性-- + + animationState: { callback: (datum: any, element: IElement) => AnimationStateEnum } + + } + + + + class IAnimationConfig { + + --属性-- + + type?: string + + channel?: string + + custom?: Function + + customParameters?: Function + + oneByOne?: boolean | number + + duration?: number + + easing?: EasingType + + delay?: number + + delayAfter?: number + + } + + + + % 关系 + + AnimationStateEnum "1" --|> "多" AnimateManager: 使用 + + AnimateManager "1" --|> "1" IAnimate: 实现 + + AnimateManager "1" -- "1" ICartesianGroupAnimationParams: 依赖 + + IAnimationSpec "1" -- "多" spec.ts: 定义于 + + MarkAnimationSpec "1" -- "1" config.ts: 由 config.ts 使用 + + IAnimationConfig "1" -- "多" utils.ts: 由 utils.ts 处理 + + IStateAnimateSpec "1" -- "1" ICommonStateAnimateSpec: 继承 + + IAnimationSpec "1" -- "1" IStateAnimateSpec: 关联 + + IAnimationSpec "1" -- "1" IMorphSeriesSpec: 关联 + + IAnimateState "1" -- "1" AnimateManager: 内部使用 + + IAnimationConfig "1" -- "1" ICommonStateAnimateSpec: 继承 + +#### 2. 动画管理器 + +- **AnimateManager 类**:继承自 `StateManager` 并实现了 `IAnimate` 接口,负责管理动画的状态,并提供方法来根据传入的状态更新动画。它处理动画状态的更新和检索,并根据不同状态更新动画状态。 + +#### 3. 工厂模式 + +- **Factory 类**:用于注册新的动画类型,允许将自定义动画逻辑添加到图表组件中。通过静态方法 `registerAnimation`,可以将特定类型的动画与其配置关联起来,方便后续调用。 + +#### 4. 动画配置生成 + +- **animationConfig 函数**:根据默认配置和用户提供的配置生成最终的动画配置。这个函数遍历所有的动画状态(如出现、进入、更新等),并根据用户配置或默认配置构建出完整的动画配置对象。 + +#### 5. 动画任务接口 + +- **IAnimationTask 接口**:定义了一个动画任务的数据结构,这对于理解复杂的动画序列非常重要。每个任务包含时间偏移、动作队列和后继任务列表,形成了一种链式动画执行机制。 + +#### 6. 动画的具体实现 + +- 每个具体的图表系列(如柱状图、饼图、散点图等)都有各自的动画实现文件,这些文件中包含了针对该系列的预设动画函数。例如,柱状图可能有生长动画、淡入动画等;饼图则可能有扇区展开动画等。 + +通过上述步骤,我们已经完成了一个简单但完整的动画流程创建。在这个过程中,我们利用了VChart动画系统的模块化设计,分别对图表配置、动画注册、实例化图表、数据更新以及动画状态管理进行了处理。这种设计不仅让代码更加清晰易读,同时也提高了系统的灵活性和可维护性。开发者可以根据实际需求轻松地定制不同类型的动画效果,从而提升用户体验。 + +为了更好地理解和解读这些源码文件,建议按照以下顺序阅读: + +1. `**interface.ts**` + +- **原因**:该文件定义了动画模块中的核心类型和接口,如 `AnimationStateEnum`、`IAnimateState` 和 `IAnimate` 等。理解这些类型和接口是后续代码的基础。 + +- **重点内容**: + +- 动画状态枚举 `AnimationStateEnum` + +- 动画状态接口 `IAnimateState` + +- 动画接口 `IAnimate` + +1. `**spec.ts**` + +- **原因**:该文件定义了动画配置的规范,包括 `ICommonStateAnimateSpec`、`IStateAnimateSpec` 和 `IAnimationSpec` 等。这些规范在实际动画配置中会被使用,因此需要先了解它们的结构。 + +- **重点内容**: + +- 动画配置的通用属性 `ICommonStateAnimateSpec` + +- 动画状态配置 `IStateAnimateSpec` + +- 动画规范 `IAnimationSpec` + +1. `**config.ts**` + +- **原因**:该文件提供了默认的动画配置和一些预设的动画注册函数。理解这些默认配置有助于理解如何自定义动画配置。 + +- **重点内容**: + +- 默认动画配置 `DEFAULT_ANIMATION_CONFIG` + +- 预设动画注册函数(如 `registerScaleInOutAnimation`、`registerFadeInOutAnimation` 等) + +1. `**utils.ts**` + +- **原因**:该文件包含了许多辅助函数,用于生成和处理动画配置。理解这些函数的工作原理可以帮助你更好地理解动画配置是如何被应用的。 + +- **重点内容**: + +- 生成动画配置的函数 `animationConfig` + +- 处理用户动画配置的函数 `userAnimationConfig` + +- 辅助函数(如 `produceOneByOne`、`shouldMarkDoMorph` 等) + +1. `**animate-manager.ts**` + +- **原因**:该文件实现了 `AnimateManager` 类,它是管理动画的核心类。理解这个类的实现可以让你知道动画是如何被管理和更新的。 + +- **重点内容**: + +- `AnimateManager` 类的实现 + +- 更新动画状态的方法 `updateAnimateState` + +- 获取动画状态信号名称的方法 `getAnimationStateSignalName` + +### 总结 + +按照上述顺序阅读这些文件,可以逐步建立起对整个动画模块的理解。从基础的类型和接口开始,逐步深入到具体的配置和实现细节,最终理解动画是如何被管理和应用的。 + +### 阅读顺序总结 + +- `**interface.ts**` 核心类型和接口 + +- `**spec.ts**` 动画配置规范 + +- `**config.ts**` 默认配置和预设动画 + +- `**utils.ts**` 辅助函数和配置生成 + +- `**animate-manager.ts**`动画管理类实现 + +# 本文档由以下人员修正整理 + +[玄魂](https://github.com/xuanhun) diff --git a/docs/assets/contributing/zh/sourcesode/10.1-animation-concepts-and-types.md b/docs/assets/contributing/zh/sourcesode/10.1-animation-concepts-and-types.md index bb93e38cb6..18eb91d949 100644 --- a/docs/assets/contributing/zh/sourcesode/10.1-animation-concepts-and-types.md +++ b/docs/assets/contributing/zh/sourcesode/10.1-animation-concepts-and-types.md @@ -1,232 +1,224 @@ --- -title: 10.1 动画的概念和类型 +title: 10.1 动画的概念和类型 key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM ---- -> 10.1 动画的概念和类型 -> 分数:4 -> 1. 动画的概念和类型: -> 1. 其他参考文档: -> https://www.visactor.io/vchart/guide/tutorial_docs/Animation/Animation_Types -> -> [魔力之帧(下):VChart 动画编程实践在这篇文章中,我们将从一些常见的图表动画入手,详细介绍在 VChart 中的编 - 掘金](https://juejin.cn/post/7314829865633595443) - -1. 代码入口:`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. 解读重点: - -1. 动画分类(按执行时机,按效果) - -1. 动画系统的整体设计 - -# 动画的概念 - - - -在VChart中,动画是指在图表渲染过程中,通过视觉效果来增强数据展示的动态性和交互性。动画系统允许开发者配置和控制图表元素(如柱状图、饼图、折线图等)在不同状态下的过渡效果。 - -在 VisActor 中动画被视作为渲染阶段的修饰:动画配置与图形语法流程执行得到的图元视觉通道一起决定了渲染阶段的结果。动画的表现是具体图形元素在某一时间段内视觉通道属性的插值计算或者特殊计算逻辑,而动画配置描述了这一计算的触发时机以及执行时长。 - - - -## 动画的分类 - -#### 生命周期示范 - -![](https://cdn.jsdelivr.net/gh/xuanhun/articles/visactor/sourcecode/img/OgJ0wqt4khXJtrbwW3Zc2521nOc.gif) - - - -### 按执行时机分类 - -图表动画在 VChart 中根据状态场景(执行时机)会被区分为:**图表入场动画**、**数据更新动画**和**图表退场动画**。 - -1. **图表入场动画:**是指图表创建时的动画效果。 - -1. **数据更新动画:**当我们更新图表数据时,图元发生的属性动画则称为数据更新动画。分为:**新增图元动画**、**图元更新动画**和**退场图元动画、状态变更动画、任意时机触发的动画**。通常情况下,你不需要考虑如何控制这三种更新动画,因为 VChart 会在数据更新时,识别出新数据与上一次数据间的关联,从而正确执行更新动画。 - -1. **图表退场动画**:在某些场景下,我们可能需要移除图表。此时,我们可以为图表设置退场动画,让图表在除之前有一个平滑过渡的动画效果。 - -![](https://cdn.jsdelivr.net/gh/xuanhun/articles/visactor/sourcecode/img/Ddzewl0jjhq1ksbmUlbc2WPSnig.gif) - -https://visactor.io/vchart/guide/tutorial_docs/Animation/Animation_Types 动画教程文档 - -https://www.visactor.io/vchart/option/barChart#animationState 动画配置文档 - -#### 图表**入场动画 (**`**animationAppear**`**)**: - -* 在图表首次渲染时,元素从无到有的过渡效果。 - -* 示例代码:`animationAppear` 配置项用于定义图表入场动画。 - - - +--- + +> 10.1 动画的概念和类型 +> 分数:4 +> +> 1. 动画的概念和类型: +> 1. 其他参考文档: +> https://www.visactor.io/vchart/guide/tutorial_docs/Animation/Animation_Types +> +> [魔力之帧(下):VChart 动画编程实践在这篇文章中,我们将从一些常见的图表动画入手,详细介绍在 VChart 中的编 - 掘金](https://juejin.cn/post/7314829865633595443) + +1. 代码入口:`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. 解读重点: + +1. 动画分类(按执行时机,按效果) + +1. 动画系统的整体设计 + +# 动画的概念 + +在VChart中,动画是指在图表渲染过程中,通过视觉效果来增强数据展示的动态性和交互性。动画系统允许开发者配置和控制图表元素(如柱状图、饼图、折线图等)在不同状态下的过渡效果。 + +在 VisActor 中动画被视作为渲染阶段的修饰:动画配置与图形语法流程执行得到的图元视觉通道一起决定了渲染阶段的结果。动画的表现是具体图形元素在某一时间段内视觉通道属性的插值计算或者特殊计算逻辑,而动画配置描述了这一计算的触发时机以及执行时长。 + + + +## 动画的分类 + +#### 生命周期示范 + +![](https://cdn.jsdelivr.net/gh/xuanhun/articles/visactor/sourcecode/img/OgJ0wqt4khXJtrbwW3Zc2521nOc.gif) + +### 按执行时机分类 + +图表动画在 VChart 中根据状态场景(执行时机)会被区分为:**图表入场动画**、**数据更新动画**和**图表退场动画**。 + +1. **图表入场动画:**是指图表创建时的动画效果。 + +1. **数据更新动画:**当我们更新图表数据时,图元发生的属性动画则称为数据更新动画。分为:**新增图元动画**、**图元更新动画**和**退场图元动画、状态变更动画、任意时机触发的动画**。通常情况下,你不需要考虑如何控制这三种更新动画,因为 VChart 会在数据更新时,识别出新数据与上一次数据间的关联,从而正确执行更新动画。 + +1. **图表退场动画**:在某些场景下,我们可能需要移除图表。此时,我们可以为图表设置退场动画,让图表在除之前有一个平滑过渡的动画效果。 + +![](https://cdn.jsdelivr.net/gh/xuanhun/articles/visactor/sourcecode/img/Ddzewl0jjhq1ksbmUlbc2WPSnig.gif) + +https://visactor.io/vchart/guide/tutorial_docs/Animation/Animation_Types 动画教程文档 + +https://www.visactor.io/vchart/option/barChart#animationState 动画配置文档 + +#### 图表**入场动画 (**`**animationAppear**`**)**: + +- 在图表首次渲染时,元素从无到有的过渡效果。 + +- 示例代码:`animationAppear` 配置项用于定义图表入场动画。 + + + ```html - -
- - - -``` + +
+ + +``` + ```xml -animationAppear?: boolean | IStateAnimateSpec | IMarkAnimateSpec; - -``` -#### 数据更新动画 - -当我们更新图表数据时,图元发生的属性动画则称为更新动画。在 VChart 中,用户手动调用 `updateData` 接口会触发图表数据更新,另外,点击图例时也更新图表数据。更新动画分为三类:新增图元动画、图元更新动画和退场图元动画。 - -1. **新增图元动画 (**`**animationEnter**`**)**: - -* 新增图元动画是指当图表数据更新时,新添加数据应的图元的动画效果。 - -* 我们可以使用 `animationEnter` 配置来设置新增图元动画。 - +animationAppear?: boolean | IStateAnimateSpec | IMarkAnimateSpec; + +``` + +#### 数据更新动画 + +当我们更新图表数据时,图元发生的属性动画则称为更新动画。在 VChart 中,用户手动调用 `updateData` 接口会触发图表数据更新,另外,点击图例时也更新图表数据。更新动画分为三类:新增图元动画、图元更新动画和退场图元动画。 + +1. **新增图元动画 (**`**animationEnter**`**)**: + +- 新增图元动画是指当图表数据更新时,新添加数据应的图元的动画效果。 + +- 我们可以使用 `animationEnter` 配置来设置新增图元动画。 + ```xml -animationEnter?: boolean | ICommonStateAnimateSpec | IMarkAnimateSpec; - -``` - - -1. **图元更新动画 ( **`**animationUpdate**`**)**: - -* 图元更新动画是指当图表数据更新,原有数据对应的图元的更新动画效果。 - -* 我们可以使用 `animationUpdate` 配置来设置图元更新动画。 - +animationEnter?: boolean | ICommonStateAnimateSpec | IMarkAnimateSpec; + +``` + +1. **图元更新动画 ( **`**animationUpdate**`**)**: + +- 图元更新动画是指当图表数据更新,原有数据对应的图元的更新动画效果。 + +- 我们可以使用 `animationUpdate` 配置来设置图元更新动画。 + ```xml -animationUpdate?: boolean | ICommonStateAnimateSpec | IMarkAnimateSpec; - -``` - - -1. **退场图元动画 (**`**animationExit**`** )**: - -* 退图元动画是指当图表数据更新时,被删除数据所对应图元的动画效果。我们可以使用 `animationExit` 配置来设置退场图元动画。 - +animationUpdate?: boolean | ICommonStateAnimateSpec | IMarkAnimateSpec; + +``` + +1. **退场图元动画 (**`**animationExit**`** )**: + +- 退图元动画是指当图表数据更新时,被删除数据所对应图元的动画效果。我们可以使用 `animationExit` 配置来设置退场图元动画。 + ```xml -animationExit?: boolean | ICommonStateAnimateSpec | IMarkAnimateSpec; - -``` - - -1. 图元**状态切换动画 (State)**: - -* 当图表状态发生改变时的过渡效果。 - -* 示例代码:`animationState` 配置项用于定义状态切换动画。 - +animationExit?: boolean | ICommonStateAnimateSpec | IMarkAnimateSpec; + +``` + +1. 图元**状态切换动画 (State)**: + +- 当图表状态发生改变时的过渡效果。 + +- 示例代码:`animationState` 配置项用于定义状态切换动画。 + ```xml -animationState?: boolean | IStateAnimationConfig; - -``` - - -1. 常态**动画 (Normal)**:常用于循环 - -* 用于定义持续不断的动画效果。 - -* 示例代码:`animationNormal` 配置项用于定义循环动画。 - +animationState?: boolean | IStateAnimationConfig; + +``` + +1. 常态**动画 (Normal)**:常用于循环 + +- 用于定义持续不断的动画效果。 + +- 示例代码:`animationNormal` 配置项用于定义循环动画。 + ```xml -animationNormal?: IMarkAnimateSpec; - -``` - - -#### 图表**退场动画 (**`**animationDisappear**`**)**: - -* 在图表销毁或隐藏时,元素的退场效果。 - +animationNormal?: IMarkAnimateSpec; + +``` + +#### 图表**退场动画 (**`**animationDisappear**`**)**: + +- 在图表销毁或隐藏时,元素的退场效果。 + ```xml - animationDisappear?: boolean | ICommonStateAnimateSpec | IMarkAnimateSpec; - -``` -### 按效果分类 - -type 图元原子化 - -* 动画效果:动画效果描述了在某一特定的动画阶段中图元以怎样的方式执行渲染的变化。动画效果包括普通的视觉通道插值,例如竞速条形图中柱子颜色、宽度、位置的变化;同时动画效果也包含一些特殊的变化,例如下图中的图元形变。 - -1. **渐入渐出 (FadeIn/FadeOut)**: - -* 元素透明度从0到1或从1到0的变化。 - -* 示例代码:`Appear_FadeIn` 和 `Disappear_FadeOut`。 - + animationDisappear?: boolean | ICommonStateAnimateSpec | IMarkAnimateSpec; + +``` + +### 按效果分类 + +type 图元原子化 + +- 动画效果:动画效果描述了在某一特定的动画阶段中图元以怎样的方式执行渲染的变化。动画效果包括普通的视觉通道插值,例如竞速条形图中柱子颜色、宽度、位置的变化;同时动画效果也包含一些特殊的变化,例如下图中的图元形变。 + +1. **渐入渐出 (FadeIn/FadeOut)**: + +- 元素透明度从0到1或从1到0的变化。 + +- 示例代码:`Appear_FadeIn` 和 `Disappear_FadeOut`。 + ```xml const Appear_FadeIn: IAnimationTypeConfig = { type: 'fadeIn' -}; - -``` - - -1. **生长 (Grow)**: - -* 元素从某个初始尺寸逐渐增长到最终尺寸。 - -* 示例代码:`barGrowOption` 和 `pieGrowOption`。 - +}; + +``` + +1. **生长 (Grow)**: + +- 元素从某个初始尺寸逐渐增长到最终尺寸。 + +- 示例代码:`barGrowOption` 和 `pieGrowOption`。 + ```xml -function barGrowOption(barParams: IBarAnimationParams, isOverall = true) {/***/} - -``` - - -1. **裁剪 (Clip)**: - -* 通过裁剪区域来显示元素的逐步出现或消失。 - -* 示例代码:`registerCartesianGroupClipAnimation`。 - +function barGrowOption(barParams: IBarAnimationParams, isOverall = true) {/***/} + +``` + +1. **裁剪 (Clip)**: + +- 通过裁剪区域来显示元素的逐步出现或消失。 + +- 示例代码:`registerCartesianGroupClipAnimation`。 + ```xml const registerCartesianGroupClipAnimation = () => { Factory.registerAnimation('cartesianGroupClip', (params?: ICartesianGroupAnimationParams) => {/***/}); -}; - -``` - - -1. **波浪 (Wave)**: - -* 特殊效果,如液态图中的波浪效果。 - -* 示例代码:`Appear_Wave`。 - +}; + +``` + +1. **波浪 (Wave)**: + +- 特殊效果,如液态图中的波浪效果。 + +- 示例代码:`Appear_Wave`。 + ```xml const Appear_Wave: IAnimationTypeConfig = { duration: 2000, @@ -234,131 +226,125 @@ const Appear_Wave: IAnimationTypeConfig = { channel: { wave: { from: 0, to: 1 } } -}; - -``` - - -1. **缩放 (Scale)**: - -* 元素大小从一个比例缩放到另一个比例。 - -* 示例代码:`Appear_ScaleIn`。 - +}; + +``` + +1. **缩放 (Scale)**: + +- 元素大小从一个比例缩放到另一个比例。 + +- 示例代码:`Appear_ScaleIn`。 + ```xml const Appear_ScaleIn: IAnimationTypeConfig = { type: 'growCenterIn' -}; - -``` -更多动画效果的属性和配置可参考https://visactor.com/vchart/guide/tutorial_docs/Animation/Animation_Attributes_and_Settings - -## 动画系统的设计 - -### 简单柱状图动画配置 - - - -下面以创建一个简单的柱状图为例,说明如何使用VChart的动画系统来实现基本动画效果的原理。 - - - - - +}; + +``` + +更多动画效果的属性和配置可参考https://visactor.com/vchart/guide/tutorial_docs/Animation/Animation_Attributes_and_Settings + +## 动画系统的设计 + +### 简单柱状图动画配置 + +下面以创建一个简单的柱状图为例,说明如何使用VChart的动画系统来实现基本动画效果的原理。 + + + ```html - - -
- - - -``` -> 如何创建一个基础VChart可以参考以下文档 -> https://www.visactor.io/vchart/guide/tutorial_docs/Getting_Started 快速上手 -> https://www.visactor.io/vchart/guide/tutorial_docs/Basic/How_to_Import_VChart 导入VChart -> https://www.visactor.io/vchart/guide/tutorial_docs/Basic/A_Basic_Spec 基础配置 -> https://www.visactor.io/vchart/guide/tutorial_docs/Basic/DeepSeek_With_Cursor DeepSeek+Cursor助力 - - - -在 `VChart` 类中,`spec`(图表配置)中的 `animation` 配置项用于控制图表的动画行为。具体来说,`animation` 配置项可以定义图表在不同状态下的动画效果,例如入场动画、更新动画、退出动画等。 - -#### `animation` 配置的作用 - -1. **定义动画行为**: - -* `animation` 配置项可以包含多个子属性,如 `appear`、`enter`、`update`、`exit` 和 `disappear`,分别对应不同的动画场景。 - -* 每个子属性可以进一步配置动画的持续时间 (`duration`)、缓动函数 (`easing`)、是否逐个执行 (`oneByOne`) 等参数。 - -1. **控制动画开关**: - -* 如果将 `animation` 设置为 `false`,则禁用所有动画效果。 - -* 如果设置为 `true` 或者提供具体的配置对象,则启用相应的动画效果。 - -1. **传递给底层组件**: - -* `VChart` 类会将 `animation` 配置传递给内部的 `Compiler` 和 `Chart` 实例,这些实例会根据配置来决定是否应用动画以及如何应用动画。 - -### 柱状图执行动画示例说明 - - - -
#### 示例代码 + + +
+ + +``` + +> 如何创建一个基础VChart可以参考以下文档 +> https://www.visactor.io/vchart/guide/tutorial_docs/Getting_Started 快速上手 +> https://www.visactor.io/vchart/guide/tutorial_docs/Basic/How_to_Import_VChart 导入VChart +> https://www.visactor.io/vchart/guide/tutorial_docs/Basic/A_Basic_Spec 基础配置 +> https://www.visactor.io/vchart/guide/tutorial_docs/VChart_Skill_Usage VChart Skill 使用 + +在 `VChart` 类中,`spec`(图表配置)中的 `animation` 配置项用于控制图表的动画行为。具体来说,`animation` 配置项可以定义图表在不同状态下的动画效果,例如入场动画、更新动画、退出动画等。 + +#### `animation` 配置的作用 + +1. **定义动画行为**: + +- `animation` 配置项可以包含多个子属性,如 `appear`、`enter`、`update`、`exit` 和 `disappear`,分别对应不同的动画场景。 + +- 每个子属性可以进一步配置动画的持续时间 (`duration`)、缓动函数 (`easing`)、是否逐个执行 (`oneByOne`) 等参数。 + +1. **控制动画开关**: + +- 如果将 `animation` 设置为 `false`,则禁用所有动画效果。 + +- 如果设置为 `true` 或者提供具体的配置对象,则启用相应的动画效果。 + +1. **传递给底层组件**: + +- `VChart` 类会将 `animation` 配置传递给内部的 `Compiler` 和 `Chart` 实例,这些实例会根据配置来决定是否应用动画以及如何应用动画。 + +### 柱状图执行动画示例说明 + + + +
#### 示例代码 ```xml import { isMobile } from 'react-device-detect'; import { default as VChart } from '../../../../src/index'; // 1. 创建图表配置项与数据 const initialSpec = { - type: 'bar', - data: [ - { - id: 'barData', - values: [ - { month: 'January', sales: 22 }, - { month: 'February', sales: 13 }, - { month: 'March', sales: 25 }, - { month: 'April', sales: 29 }, - { month: 'May', sales: 38 } - ] - } - ], - xField: 'month', - yField: 'sales', - crosshair: { - xField: { visible: true } - }, - animation: true // 开启动画 +type: 'bar', +data: [ +{ +id: 'barData', +values: [ +{ month: 'January', sales: 22 }, +{ month: 'February', sales: 13 }, +{ month: 'March', sales: 25 }, +{ month: 'April', sales: 29 }, +{ month: 'May', sales: 38 } +] +} +], +xField: 'month', +yField: 'sales', +crosshair: { +xField: { visible: true } +}, +animation: true // 开启动画 }; // 2. 创建 VChart 实例 @@ -366,146 +352,147 @@ const vchart = new VChart(initialSpec, { dom: 'chart' }); // 3. 渲染图表 vchart.renderAsync().then(() => { - console.log('图表渲染完成'); +console.log('图表渲染完成'); }); // 4. 动画入场 setTimeout(() => { - console.log('动画入场'); +console.log('动画入场'); }, 1000); // 5. 数据更新(新增图元) setTimeout(() => { - const newData = [ - { month: 'June', sales: 45 }, - { month: 'July', sales: 50 } - ]; - vchart.updateDataSync('barData', newData, undefined, { reAnimate: true }); - console.log('新增图元'); +const newData = [ +{ month: 'June', sales: 45 }, +{ month: 'July', sales: 50 } +]; +vchart.updateDataSync('barData', newData, undefined, { reAnimate: true }); +console.log('新增图元'); }, 3000); // 6. 数据更新(图元更新) setTimeout(() => { - const updatedData = [ - { month: 'January', sales: 30 }, - { month: 'February', sales: 20 }, - { month: 'March', sales: 35 }, - { month: 'April', sales: 39 }, - { month: 'May', sales: 48 }, - { month: 'June', sales: 55 }, - { month: 'July', sales: 60 } - ]; - vchart.updateDataSync('barData', updatedData, undefined, { reAnimate: true }); - console.log('图元更新'); +const updatedData = [ +{ month: 'January', sales: 30 }, +{ month: 'February', sales: 20 }, +{ month: 'March', sales: 35 }, +{ month: 'April', sales: 39 }, +{ month: 'May', sales: 48 }, +{ month: 'June', sales: 55 }, +{ month: 'July', sales: 60 } +]; +vchart.updateDataSync('barData', updatedData, undefined, { reAnimate: true }); +console.log('图元更新'); }, 6000); // 7. 数据更新(图元退出) setTimeout(() => { - const remainingData = [ - { month: 'January', sales: 30 }, - { month: 'February', sales: 20 }, - { month: 'March', sales: 35 }, - { month: 'April', sales: 39 }, - { month: 'May', sales: 48 } - ]; - vchart.updateDataSync('barData', remainingData, undefined, { reAnimate: true }); - console.log('图元退出'); +const remainingData = [ +{ month: 'January', sales: 30 }, +{ month: 'February', sales: 20 }, +{ month: 'March', sales: 35 }, +{ month: 'April', sales: 39 }, +{ month: 'May', sales: 48 } +]; +vchart.updateDataSync('barData', remainingData, undefined, { reAnimate: true }); +console.log('图元退出'); }, 9000); // 8. 图元状态(state)的使用 setTimeout(() => { - vchart.updateState( - { - selected: { - style: { - fill: 'red' - } - } - }, - (series, mark, stateKey) => { - return mark.datum.sales > 40; - } - ); - console.log('图元状态更新'); +vchart.updateState( +{ +selected: { +style: { +fill: 'red' +} +} +}, +(series, mark, stateKey) => { +return mark.datum.sales > 40; +} +); +console.log('图元状态更新'); }, 12000); // 9. 图表退场 setTimeout(() => { - vchart.release(); - console.log('图表退场'); -}, 15000); - -```
#### 创建逻辑说明 -1. **创建图表配置项与数据**: -1. **创建 VChart 实例**: -1. **渲染图表**: -1. **动画入场**: -1. **数据更新(新增图元)**: -1. **数据更新(图元更新)**: -1. **数据更新(图元退出)**: -1. **图元状态(state)的使用**: -1. **图表退场**: - -
-* 定义了一个初始的图表配置项`initialSpec`,其中包含图表类型、数据、坐标轴字段和动画配置。 - -* 数据部分包含了一个`barData`的数据集,初始包含5个月的销售数据。 - -* 使用`initialSpec`和DOM容器`chart`创建一个VChart实例。 - -* 调用`renderAsync`方法异步渲染图表。图表渲染完成后,会触发动画入场效果。 - -* 在渲染完成后,通过`setTimeout`模拟动画入场。实际动画效果由VChart内部处理。 - -* 在3秒后,通过`updateDataSync`方法新增两个月的销售数据。`reAnimate: true`参数确保新增数据时有动画效果。 - -* 在6秒后,通过`updateDataSync`方法更新所有图元的数据。`reAnimate: true`参数确保更新数据时有动画效果。 - -* 在9秒后,通过`updateDataSync`方法移除两个月的销售数据。`reAnimate: true`参数确保移除数据时有动画效果。 - -* 在12秒后,通过`updateState`方法更新图元的状态。这里设置了一个`selected`状态,当图元的`sales`值大于40时,图元的填充颜色变为红色。 - -* 在15秒后,通过`release`方法销毁图表实例,图表退场。 - ---- - - -
#### 动画流程图 -
#### 流程说明 -1. **创建图表配置项与数据**:定义初始图表配置和数据。 -1. **创建 VChart 实例**:使用配置和DOM容器创建VChart实例。 -1. **渲染图表**:调用`renderAsync`方法渲染图表,触发动画入场效果。 -1. **动画入场**:图表渲染完成后,自动触发入场动画。 -1. **数据更新(新增图元)**:通过`updateDataSync`方法新增数据,触发新增动画。 -1. **数据更新(图元更新)**:通过`updateDataSync`方法更新数据,触发更新动画。 -1. **数据更新(图元退出)**:通过`updateDataSync`方法移除数据,触发退出动画。 -1. **图元状态(state)的使用**:通过`updateState`方法更新图元状态,设置特定条件下的样式。 -1. **图表退场**:通过`release`方法销毁图表实例,图表退场。 - -
-### 源码实现流程 - -1. **初始化 VChart 实例** - -当你创建一个 `VChart` 实例并传入 `spec` 时,构造函数会处理 `animation` 配置: - -文件:`vchart.ts` 方法:`constructor` - +vchart.release(); +console.log('图表退场'); +}, 15000); + +````
#### 创建逻辑说明 +1. **创建图表配置项与数据**: +1. **创建 VChart 实例**: +1. **渲染图表**: +1. **动画入场**: +1. **数据更新(新增图元)**: +1. **数据更新(图元更新)**: +1. **数据更新(图元退出)**: +1. **图元状态(state)的使用**: +1. **图表退场**: + +
+* 定义了一个初始的图表配置项`initialSpec`,其中包含图表类型、数据、坐标轴字段和动画配置。 + +* 数据部分包含了一个`barData`的数据集,初始包含5个月的销售数据。 + +* 使用`initialSpec`和DOM容器`chart`创建一个VChart实例。 + +* 调用`renderAsync`方法异步渲染图表。图表渲染完成后,会触发动画入场效果。 + +* 在渲染完成后,通过`setTimeout`模拟动画入场。实际动画效果由VChart内部处理。 + +* 在3秒后,通过`updateDataSync`方法新增两个月的销售数据。`reAnimate: true`参数确保新增数据时有动画效果。 + +* 在6秒后,通过`updateDataSync`方法更新所有图元的数据。`reAnimate: true`参数确保更新数据时有动画效果。 + +* 在9秒后,通过`updateDataSync`方法移除两个月的销售数据。`reAnimate: true`参数确保移除数据时有动画效果。 + +* 在12秒后,通过`updateState`方法更新图元的状态。这里设置了一个`selected`状态,当图元的`sales`值大于40时,图元的填充颜色变为红色。 + +* 在15秒后,通过`release`方法销毁图表实例,图表退场。 + +--- + + +
#### 动画流程图 +
#### 流程说明 +1. **创建图表配置项与数据**:定义初始图表配置和数据。 +1. **创建 VChart 实例**:使用配置和DOM容器创建VChart实例。 +1. **渲染图表**:调用`renderAsync`方法渲染图表,触发动画入场效果。 +1. **动画入场**:图表渲染完成后,自动触发入场动画。 +1. **数据更新(新增图元)**:通过`updateDataSync`方法新增数据,触发新增动画。 +1. **数据更新(图元更新)**:通过`updateDataSync`方法更新数据,触发更新动画。 +1. **数据更新(图元退出)**:通过`updateDataSync`方法移除数据,触发退出动画。 +1. **图元状态(state)的使用**:通过`updateState`方法更新图元状态,设置特定条件下的样式。 +1. **图表退场**:通过`release`方法销毁图表实例,图表退场。 + +
+### 源码实现流程 + +1. **初始化 VChart 实例** + +当你创建一个 `VChart` 实例并传入 `spec` 时,构造函数会处理 `animation` 配置: + +文件:`vchart.ts` 方法:`constructor` + ```xml constructor(spec: ISpec, options: IInitOption) { this._option = mergeOrigin(this._option, { animation: (spec as any).animation !== false }, options); *// ...* -} - -``` -这段代码确保了如果 `spec` 中没有显式禁用动画(即 `animation !== false`),则启用动画。 - -1. 设置新 spec 并初始化图表 - -在 `VChart` 类中,`_setNewSpec` 方法用于设置新的 `spec`,并将其转换为内部使用的格式: - -文件:`vchart.ts` 方法:`_setNewSpec` - +} + +```` + +这段代码确保了如果 `spec` 中没有显式禁用动画(即 `animation !== false`),则启用动画。 + +1. 设置新 spec 并初始化图表 + +在 `VChart` 类中,`_setNewSpec` 方法用于设置新的 `spec`,并将其转换为内部使用的格式: + +文件:`vchart.ts` 方法:`_setNewSpec` + ```xml private _setNewSpec(spec: any, forceMerge?: boolean): boolean { if (!spec) { @@ -520,13 +507,14 @@ private _setNewSpec(spec: any, forceMerge?: boolean): boolean { this._originalSpec = spec; this._spec = this._getSpecFromOriginalSpec(); return true; -} +} + +``` + +接着,`_initChartSpec` 方法会根据 `spec` 初始化图表规格: + +文件:`vchart.ts` 方法:`_initChartSpec` -``` -接着,`_initChartSpec` 方法会根据 `spec` 初始化图表规格: - -文件:`vchart.ts` 方法:`_initChartSpec` - ```xml private _initChartSpec(spec: any, actionSource: VChartRenderActionSource) { *// 如果用户注册了函数,在配置中替换相应函数名为函数内容* @@ -546,15 +534,16 @@ private _initChartSpec(spec: any, actionSource: VChartRenderActionSource) { this._specInfo = this._chartSpecTransformer?.transformModelSpec(this._spec); *// 插件生命周期* this._chartPluginApply('onAfterModelSpecTransform', this._spec, this._specInfo, actionSource); -} - -``` -1. 创建和初始化 Chart 实例 - -在 `_initChart` 方法中,创建并初始化图表实例: - -文件:`vchart.ts` 方法:`_initChart` - +} + +``` + +1. 创建和初始化 Chart 实例 + +在 `_initChart` 方法中,创建并初始化图表实例: + +文件:`vchart.ts` 方法:`_initChart` + ```xml private _initChart(spec: any) { if (!this._compiler) { @@ -578,15 +567,16 @@ private _initChart(spec: any) { chart, vchart: this }); -} - -``` -1. 更新动画状态 - -当图表需要重新渲染或更新时,`_updateAnimateState` 方法会被调用来更新动画状态: - -文件:`vchart.ts` 方法:`_updateAnimateState` - +} + +``` + +1. 更新动画状态 + +当图表需要重新渲染或更新时,`_updateAnimateState` 方法会被调用来更新动画状态: + +文件:`vchart.ts` 方法:`_updateAnimateState` + ```xml private _updateAnimateState(initial?: boolean) { if (this._option.animation) { @@ -598,19 +588,20 @@ private _updateAnimateState(initial?: boolean) { component.animate?.updateAnimateState(animationState, true); }); } -} - -``` -* **初始状态**:如果 `initial` 为 `true`,则设置动画状态为 `AnimationStateEnum.appear`(入场动画)。 - -* **更新状态**:否则,设置为 `AnimationStateEnum.update`(更新动画)。 - -1. 渲染图表 - -在 `renderSync` 和 `renderAsync` 方法中,`animation` 配置会被传递给编译器进行渲染: - -文件:`vchart.ts` 方法:`_renderSync` - +} + +``` + +- **初始状态**:如果 `initial` 为 `true`,则设置动画状态为 `AnimationStateEnum.appear`(入场动画)。 + +- **更新状态**:否则,设置为 `AnimationStateEnum.update`(更新动画)。 + +1. 渲染图表 + +在 `renderSync` 和 `renderAsync` 方法中,`animation` 配置会被传递给编译器进行渲染: + +文件:`vchart.ts` 方法:`_renderSync` + ```xml protected _renderSync = (option: IVChartRenderOption = {}) => { const self = this as unknown as IVChart; @@ -621,391 +612,360 @@ protected _renderSync = (option: IVChartRenderOption = {}) => { this._compiler?.render(option.morphConfig); this._afterRender(); return self; -}; - -``` -1. 动画状态的更新 - -在 `updateSpec` 和 `updateCustomConfigAndRerender` 方法中,`reAnimate` 标志用于决定是否重新触发动画: - -文件:`vchart.ts` 方法:`updateSpec` 和 `updateCustomConfigAndRerender` - +}; + +``` + +1. 动画状态的更新 + +在 `updateSpec` 和 `updateCustomConfigAndRerender` 方法中,`reAnimate` 标志用于决定是否重新触发动画: + +文件:`vchart.ts` 方法:`updateSpec` 和 `updateCustomConfigAndRerender` + ```xml if (userUpdateOptions?.reAnimate) { this.stopAnimation(); this._updateAnimateState(true); -} - -``` - - -### 动画系统设计概述 - - - -VChart的动画系统设计遵循模块化、可扩展和易于配置的原则,旨在为开发者提供一个灵活且强大的工具来创建丰富的动画效果。以下是该系统的几个关键组成部分及其工作原理: - -### 原理 - -#### 1. 动画接口与抽象 - - - -* **IAnimate 接口**:定义了所有动画必须实现的方法和属性,包括获取唯一的ID、更新动画状态以及获取状态信号名称。 - -* - -* **IAnimationSpec 接口**:规定了动画配置的结构,涵盖了从入场到退场的各种动画设置。 - - - -classDiagram - - class AnimationStateEnum { - - --枚举-- - - 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 { - - --属性-- - - -_stateMap: IAnimateState & StateMap - - +id: number - - --方法-- - - +updateAnimateState(state: AnimationStateEnum, noRender?: boolean): void - - +getAnimationStateSignalName(): string - - +constructor() - - } - - - - class MarkAnimationSpec { - - --属性-- - - appear: IAnimationConfig - - enter: IAnimationConfig - - update: IAnimationConfig[] - - exit: IAnimationConfig - - disappear: IAnimationConfig - - } - - - - class 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 - - } - - - - class IStateAnimateSpec { - - --属性-- - - duration?: number - - delay?: number - - easing?: EasingType - - oneByOne?: boolean - - preset?: Preset | false - - } - - - - class ICommonStateAnimateSpec { - - --属性-- - - duration?: number - - delay?: number - - easing?: EasingType - - oneByOne?: boolean - - } - - - - class IMorphSeriesSpec { - - --属性-- - - enable?: boolean - - morphKey?: string - - morphElementKey?: string - - } - - - - class IAnimateState { - - --属性-- - - animationState: { callback: (datum: any, element: IElement) => AnimationStateEnum } - - } - - - - class IAnimationConfig { - - --属性-- - - type?: string - - channel?: string - - custom?: Function - - customParameters?: Function - - oneByOne?: boolean | number - - duration?: number - - easing?: EasingType - - delay?: number - - delayAfter?: number - - } - - - - % 关系 - - AnimationStateEnum "1" --|> "多" AnimateManager: 使用 - - AnimateManager "1" --|> "1" IAnimate: 实现 - - AnimateManager "1" -- "1" ICartesianGroupAnimationParams: 依赖 - - IAnimationSpec "1" -- "多" spec.ts: 定义于 - - MarkAnimationSpec "1" -- "1" config.ts: 由 config.ts 使用 - - IAnimationConfig "1" -- "多" utils.ts: 由 utils.ts 处理 - - IStateAnimateSpec "1" -- "1" ICommonStateAnimateSpec: 继承 - - IAnimationSpec "1" -- "1" IStateAnimateSpec: 关联 - - IAnimationSpec "1" -- "1" IMorphSeriesSpec: 关联 - - IAnimateState "1" -- "1" AnimateManager: 内部使用 - - IAnimationConfig "1" -- "1" ICommonStateAnimateSpec: 继承 - - - -#### 2. 动画管理器 - - - -* **AnimateManager 类**:继承自 `StateManager` 并实现了 `IAnimate` 接口,负责管理动画的状态,并提供方法来根据传入的状态更新动画。它处理动画状态的更新和检索,并根据不同状态更新动画状态。 - - - -#### 3. 工厂模式 - - - -* **Factory 类**:用于注册新的动画类型,允许将自定义动画逻辑添加到图表组件中。通过静态方法 `registerAnimation`,可以将特定类型的动画与其配置关联起来,方便后续调用。 - - - -#### 4. 动画配置生成 - - - -* **animationConfig 函数**:根据默认配置和用户提供的配置生成最终的动画配置。这个函数遍历所有的动画状态(如出现、进入、更新等),并根据用户配置或默认配置构建出完整的动画配置对象。 - - - -#### 5. 动画任务接口 - - - -* **IAnimationTask 接口**:定义了一个动画任务的数据结构,这对于理解复杂的动画序列非常重要。每个任务包含时间偏移、动作队列和后继任务列表,形成了一种链式动画执行机制。 - - - -#### 6. 动画的具体实现 - - - -* 每个具体的图表系列(如柱状图、饼图、散点图等)都有各自的动画实现文件,这些文件中包含了针对该系列的预设动画函数。例如,柱状图可能有生长动画、淡入动画等;饼图则可能有扇区展开动画等。 - - - - - -通过上述步骤,我们已经完成了一个简单但完整的动画流程创建。在这个过程中,我们利用了VChart动画系统的模块化设计,分别对图表配置、动画注册、实例化图表、数据更新以及动画状态管理进行了处理。这种设计不仅让代码更加清晰易读,同时也提高了系统的灵活性和可维护性。开发者可以根据实际需求轻松地定制不同类型的动画效果,从而提升用户体验。 - - - -为了更好地理解和解读这些源码文件,建议按照以下顺序阅读: - -1. `**interface.ts**` - -* **原因**:该文件定义了动画模块中的核心类型和接口,如 `AnimationStateEnum`、`IAnimateState` 和 `IAnimate` 等。理解这些类型和接口是后续代码的基础。 - -* **重点内容**: - -* 动画状态枚举 `AnimationStateEnum` - -* 动画状态接口 `IAnimateState` - -* 动画接口 `IAnimate` - -1. `**spec.ts**` - -* **原因**:该文件定义了动画配置的规范,包括 `ICommonStateAnimateSpec`、`IStateAnimateSpec` 和 `IAnimationSpec` 等。这些规范在实际动画配置中会被使用,因此需要先了解它们的结构。 - -* **重点内容**: - -* 动画配置的通用属性 `ICommonStateAnimateSpec` - -* 动画状态配置 `IStateAnimateSpec` - -* 动画规范 `IAnimationSpec` - -1. `**config.ts**` - -* **原因**:该文件提供了默认的动画配置和一些预设的动画注册函数。理解这些默认配置有助于理解如何自定义动画配置。 - -* **重点内容**: - -* 默认动画配置 `DEFAULT_ANIMATION_CONFIG` - -* 预设动画注册函数(如 `registerScaleInOutAnimation`、`registerFadeInOutAnimation` 等) - -1. `**utils.ts**` - -* **原因**:该文件包含了许多辅助函数,用于生成和处理动画配置。理解这些函数的工作原理可以帮助你更好地理解动画配置是如何被应用的。 - -* **重点内容**: - -* 生成动画配置的函数 `animationConfig` - -* 处理用户动画配置的函数 `userAnimationConfig` - -* 辅助函数(如 `produceOneByOne`、`shouldMarkDoMorph` 等) - -1. `**animate-manager.ts**` - -* **原因**:该文件实现了 `AnimateManager` 类,它是管理动画的核心类。理解这个类的实现可以让你知道动画是如何被管理和更新的。 - -* **重点内容**: - -* `AnimateManager` 类的实现 - -* 更新动画状态的方法 `updateAnimateState` - -* 获取动画状态信号名称的方法 `getAnimationStateSignalName` - -### 总结 - -按照上述顺序阅读这些文件,可以逐步建立起对整个动画模块的理解。从基础的类型和接口开始,逐步深入到具体的配置和实现细节,最终理解动画是如何被管理和应用的。 - -### 阅读顺序总结 - -* `**interface.ts**` 核心类型和接口 - -* `**spec.ts**` 动画配置规范 - -* `**config.ts**` 默认配置和预设动画 - -* `**utils.ts**` 辅助函数和配置生成 - -* `**animate-manager.ts**`动画管理类实现 - - # 本文档由以下人员修正整理 - [玄魂](https://github.com/xuanhun) \ No newline at end of file +} + +``` + +### 动画系统设计概述 + +VChart的动画系统设计遵循模块化、可扩展和易于配置的原则,旨在为开发者提供一个灵活且强大的工具来创建丰富的动画效果。以下是该系统的几个关键组成部分及其工作原理: + +### 原理 + +#### 1. 动画接口与抽象 + +- **IAnimate 接口**:定义了所有动画必须实现的方法和属性,包括获取唯一的ID、更新动画状态以及获取状态信号名称。 + +- + +- **IAnimationSpec 接口**:规定了动画配置的结构,涵盖了从入场到退场的各种动画设置。 + +classDiagram + + class AnimationStateEnum { + + --枚举-- + + 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 { + + --属性-- + + -_stateMap: IAnimateState & StateMap + + +id: number + + --方法-- + + +updateAnimateState(state: AnimationStateEnum, noRender?: boolean): void + + +getAnimationStateSignalName(): string + + +constructor() + + } + + + + class MarkAnimationSpec { + + --属性-- + + appear: IAnimationConfig + + enter: IAnimationConfig + + update: IAnimationConfig[] + + exit: IAnimationConfig + + disappear: IAnimationConfig + + } + + + + class 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 + + } + + + + class IStateAnimateSpec { + + --属性-- + + duration?: number + + delay?: number + + easing?: EasingType + + oneByOne?: boolean + + preset?: Preset | false + + } + + + + class ICommonStateAnimateSpec { + + --属性-- + + duration?: number + + delay?: number + + easing?: EasingType + + oneByOne?: boolean + + } + + + + class IMorphSeriesSpec { + + --属性-- + + enable?: boolean + + morphKey?: string + + morphElementKey?: string + + } + + + + class IAnimateState { + + --属性-- + + animationState: { callback: (datum: any, element: IElement) => AnimationStateEnum } + + } + + + + class IAnimationConfig { + + --属性-- + + type?: string + + channel?: string + + custom?: Function + + customParameters?: Function + + oneByOne?: boolean | number + + duration?: number + + easing?: EasingType + + delay?: number + + delayAfter?: number + + } + + + + % 关系 + + AnimationStateEnum "1" --|> "多" AnimateManager: 使用 + + AnimateManager "1" --|> "1" IAnimate: 实现 + + AnimateManager "1" -- "1" ICartesianGroupAnimationParams: 依赖 + + IAnimationSpec "1" -- "多" spec.ts: 定义于 + + MarkAnimationSpec "1" -- "1" config.ts: 由 config.ts 使用 + + IAnimationConfig "1" -- "多" utils.ts: 由 utils.ts 处理 + + IStateAnimateSpec "1" -- "1" ICommonStateAnimateSpec: 继承 + + IAnimationSpec "1" -- "1" IStateAnimateSpec: 关联 + + IAnimationSpec "1" -- "1" IMorphSeriesSpec: 关联 + + IAnimateState "1" -- "1" AnimateManager: 内部使用 + + IAnimationConfig "1" -- "1" ICommonStateAnimateSpec: 继承 + +#### 2. 动画管理器 + +- **AnimateManager 类**:继承自 `StateManager` 并实现了 `IAnimate` 接口,负责管理动画的状态,并提供方法来根据传入的状态更新动画。它处理动画状态的更新和检索,并根据不同状态更新动画状态。 + +#### 3. 工厂模式 + +- **Factory 类**:用于注册新的动画类型,允许将自定义动画逻辑添加到图表组件中。通过静态方法 `registerAnimation`,可以将特定类型的动画与其配置关联起来,方便后续调用。 + +#### 4. 动画配置生成 + +- **animationConfig 函数**:根据默认配置和用户提供的配置生成最终的动画配置。这个函数遍历所有的动画状态(如出现、进入、更新等),并根据用户配置或默认配置构建出完整的动画配置对象。 + +#### 5. 动画任务接口 + +- **IAnimationTask 接口**:定义了一个动画任务的数据结构,这对于理解复杂的动画序列非常重要。每个任务包含时间偏移、动作队列和后继任务列表,形成了一种链式动画执行机制。 + +#### 6. 动画的具体实现 + +- 每个具体的图表系列(如柱状图、饼图、散点图等)都有各自的动画实现文件,这些文件中包含了针对该系列的预设动画函数。例如,柱状图可能有生长动画、淡入动画等;饼图则可能有扇区展开动画等。 + +通过上述步骤,我们已经完成了一个简单但完整的动画流程创建。在这个过程中,我们利用了VChart动画系统的模块化设计,分别对图表配置、动画注册、实例化图表、数据更新以及动画状态管理进行了处理。这种设计不仅让代码更加清晰易读,同时也提高了系统的灵活性和可维护性。开发者可以根据实际需求轻松地定制不同类型的动画效果,从而提升用户体验。 + +为了更好地理解和解读这些源码文件,建议按照以下顺序阅读: + +1. `**interface.ts**` + +- **原因**:该文件定义了动画模块中的核心类型和接口,如 `AnimationStateEnum`、`IAnimateState` 和 `IAnimate` 等。理解这些类型和接口是后续代码的基础。 + +- **重点内容**: + +- 动画状态枚举 `AnimationStateEnum` + +- 动画状态接口 `IAnimateState` + +- 动画接口 `IAnimate` + +1. `**spec.ts**` + +- **原因**:该文件定义了动画配置的规范,包括 `ICommonStateAnimateSpec`、`IStateAnimateSpec` 和 `IAnimationSpec` 等。这些规范在实际动画配置中会被使用,因此需要先了解它们的结构。 + +- **重点内容**: + +- 动画配置的通用属性 `ICommonStateAnimateSpec` + +- 动画状态配置 `IStateAnimateSpec` + +- 动画规范 `IAnimationSpec` + +1. `**config.ts**` + +- **原因**:该文件提供了默认的动画配置和一些预设的动画注册函数。理解这些默认配置有助于理解如何自定义动画配置。 + +- **重点内容**: + +- 默认动画配置 `DEFAULT_ANIMATION_CONFIG` + +- 预设动画注册函数(如 `registerScaleInOutAnimation`、`registerFadeInOutAnimation` 等) + +1. `**utils.ts**` + +- **原因**:该文件包含了许多辅助函数,用于生成和处理动画配置。理解这些函数的工作原理可以帮助你更好地理解动画配置是如何被应用的。 + +- **重点内容**: + +- 生成动画配置的函数 `animationConfig` + +- 处理用户动画配置的函数 `userAnimationConfig` + +- 辅助函数(如 `produceOneByOne`、`shouldMarkDoMorph` 等) + +1. `**animate-manager.ts**` + +- **原因**:该文件实现了 `AnimateManager` 类,它是管理动画的核心类。理解这个类的实现可以让你知道动画是如何被管理和更新的。 + +- **重点内容**: + +- `AnimateManager` 类的实现 + +- 更新动画状态的方法 `updateAnimateState` + +- 获取动画状态信号名称的方法 `getAnimationStateSignalName` + +### 总结 + +按照上述顺序阅读这些文件,可以逐步建立起对整个动画模块的理解。从基础的类型和接口开始,逐步深入到具体的配置和实现细节,最终理解动画是如何被管理和应用的。 + +### 阅读顺序总结 + +- `**interface.ts**` 核心类型和接口 + +- `**spec.ts**` 动画配置规范 + +- `**config.ts**` 默认配置和预设动画 + +- `**utils.ts**` 辅助函数和配置生成 + +- `**animate-manager.ts**`动画管理类实现 + +# 本文档由以下人员修正整理 + +[玄魂](https://github.com/xuanhun) diff --git a/docs/assets/guide/menu.json b/docs/assets/guide/menu.json index d3c09a0c13..b9651e7a77 100644 --- a/docs/assets/guide/menu.json +++ b/docs/assets/guide/menu.json @@ -63,20 +63,6 @@ "zh": "一份基础的 spec", "en": "A Basic Spec" } - }, - { - "path": "DeepSeek_With_Cursor", - "title": { - "zh": "Cursor+DeepSeek,快速上手属于你的 VChart 代码", - "en": "Cursor+DeepSeek: Quick Start to Your VChart Code" - } - }, - { - "path": "Quickly_Get_Started_with_VisActor_Using_Trae_Context_Doc", - "title": { - "zh": "使用 Trae Context Doc 快速上手 VisActor", - "en": "Quickly Get Started with VisActor Using Trae Context Doc" - } } ] }, @@ -974,4 +960,4 @@ ] } ] -} +} \ No newline at end of file From 995a0c6a9c8d2011153b921f6fcd01ef7fc65eec Mon Sep 17 00:00:00 2001 From: "lixuefei.1313" Date: Mon, 9 Mar 2026 11:16:47 +0800 Subject: [PATCH 02/24] fix: fix issue of sync-main-to-develop action --- .github/workflows/sync-main-to-develop.yml | 27 ++++++++++++++-------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/.github/workflows/sync-main-to-develop.yml b/.github/workflows/sync-main-to-develop.yml index 00cdbbcfbf..940f4ec334 100644 --- a/.github/workflows/sync-main-to-develop.yml +++ b/.github/workflows/sync-main-to-develop.yml @@ -1,4 +1,4 @@ -name: Sync main to develop after release (Scheme A) +name: Sync main to develop after release on: pull_request: @@ -102,11 +102,20 @@ jobs: - name: Create Pull Request to develop if: steps.sync_branch.outputs.exists == 'false' - uses: dustinirving/create-pr@v1.0.2 - with: - token: ${{ secrets.GITHUB_TOKEN }} - title: '[Auto Sync] Sync the code from branch main to branch develop after release ${{ steps.package_version.outputs.current_version }}' - base: develop - head: ${{ steps.sync_branch.outputs.sync_branch }} - reviewers: xile611 - body: 'Sync the code from branch main to branch develop after release ${{ steps.package_version.outputs.current_version }}' + env: + GH_TOKEN: ${{ github.token }} + run: | + set -euo pipefail + BRANCH="${{ steps.sync_branch.outputs.sync_branch }}" + echo "Source branch: $BRANCH" + + # Check if PR already exists + if gh pr list --base develop --head "$BRANCH" --state open --json number --limit 1 | grep -q '"number"'; then + echo "PR from $BRANCH to develop already exists, skip creating." + exit 0 + fi + + TITLE="[Auto Sync] Sync the code from branch main to branch develop after release ${{ steps.package_version.outputs.current_version }}" + BODY="Sync the code from branch main to branch develop after release ${{ steps.package_version.outputs.current_version }}" + + gh pr create --base develop --head "$BRANCH" --title "$TITLE" --body "$BODY" --reviewer xuefei1313 From 97366f5bbd806ffa7829570d6ba536fe6b30cd6c Mon Sep 17 00:00:00 2001 From: "lixuefei.1313" Date: Mon, 9 Mar 2026 16:30:11 +0800 Subject: [PATCH 03/24] feat: change post-release dispatch --- .github/workflows/post-release.yml | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/.github/workflows/post-release.yml b/.github/workflows/post-release.yml index c64de57548..a51fd1bcaf 100644 --- a/.github/workflows/post-release.yml +++ b/.github/workflows/post-release.yml @@ -1,8 +1,12 @@ name: Post release after develop synced on: - repository_dispatch: - types: [develop-synced] + workflow_dispatch: + inputs: + version: + description: 'Release version, e.g. 1.2.3' + required: true + type: string jobs: post_release: @@ -12,19 +16,19 @@ jobs: contents: write steps: - - name: Read version from repository_dispatch payload + - name: Read version from workflow_dispatch input id: meta env: - PAYLOAD_VERSION: ${{ github.event.client_payload.version }} + INPUT_VERSION: ${{ github.event.inputs.version }} run: | set -euo pipefail - if [ -z "${PAYLOAD_VERSION}" ]; then - echo "No version in client_payload, skip post-release." + if [ -z "${INPUT_VERSION}" ]; then + echo "No version in workflow_dispatch input, skip post-release." echo "skip=true" >> "$GITHUB_OUTPUT" exit 0 fi - echo "Using version from payload: ${PAYLOAD_VERSION}" - echo "version=${PAYLOAD_VERSION}" >> "$GITHUB_OUTPUT" + echo "Using version from input: ${INPUT_VERSION}" + echo "version=${INPUT_VERSION}" >> "$GITHUB_OUTPUT" echo "skip=false" >> "$GITHUB_OUTPUT" - name: Checkout main From 08a1416a02e77ae915ad1d3a59b5f3d350540dcf Mon Sep 17 00:00:00 2001 From: xile611 Date: Tue, 10 Mar 2026 15:38:16 +0800 Subject: [PATCH 04/24] fix: pass valueField to circle-packing layout The circle-packing series now correctly passes the valueField configuration to the underlying layout algorithm. Co-Authored-By: Claude Opus 4.6 --- packages/vchart/src/series/circle-packing/circle-packing.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/vchart/src/series/circle-packing/circle-packing.ts b/packages/vchart/src/series/circle-packing/circle-packing.ts index bcf781731f..7488171081 100644 --- a/packages/vchart/src/series/circle-packing/circle-packing.ts +++ b/packages/vchart/src/series/circle-packing/circle-packing.ts @@ -132,6 +132,7 @@ export class CirclePackingSeries< options: (): ICirclePackingOpt => { return { nodeKey: this._categoryField, + valueField: this._valueField, padding: this._layoutPadding, includeRoot: false, width: this.getLayoutRect().width || 1, From 99fe648d44684afdd0f60387141f6dc79ad993cc Mon Sep 17 00:00:00 2001 From: xile611 Date: Tue, 10 Mar 2026 15:41:30 +0800 Subject: [PATCH 05/24] fix: add valueField to ICirclePackingOpt interface Co-Authored-By: Claude Opus 4.6 --- packages/vchart/src/data/transforms/circle-packing.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/vchart/src/data/transforms/circle-packing.ts b/packages/vchart/src/data/transforms/circle-packing.ts index 5f5468227d..2600095ea0 100644 --- a/packages/vchart/src/data/transforms/circle-packing.ts +++ b/packages/vchart/src/data/transforms/circle-packing.ts @@ -7,6 +7,8 @@ import { CirclePackingLayout } from '@visactor/vlayouts'; export interface ICirclePackingOpt extends CirclePackingOptions { width: number; height: number; + /** the field to read node value, default is 'value' */ + valueField?: string; } /** From 5d33aecbf433c413174d5153124445646f8d6470 Mon Sep 17 00:00:00 2001 From: xile611 Date: Wed, 11 Mar 2026 11:29:01 +0800 Subject: [PATCH 06/24] fix: fix theme config of spec and option --- packages/vchart/src/core/vchart.ts | 34 ++++++++++++------------------ 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/packages/vchart/src/core/vchart.ts b/packages/vchart/src/core/vchart.ts index b337bf670d..a43fd728fb 100644 --- a/packages/vchart/src/core/vchart.ts +++ b/packages/vchart/src/core/vchart.ts @@ -1471,27 +1471,19 @@ export class VChart implements IVChart { // 处理 specTheme 和 optionTheme, merge -> transform // 优先级 currentTheme < optionTheme < specTheme if (!isEmpty(optionTheme) || !isEmpty(specTheme)) { - if ( - (isString(optionTheme) && (!specTheme || isString(specTheme))) || - (isString(specTheme) && (!optionTheme || isString(optionTheme))) - ) { - const finalTheme = mergeTheme( - {}, - getThemeObject(this._currentThemeName), - getThemeObject(optionTheme), - getThemeObject(specTheme) - ); - - this._currentTheme = processThemeByChartType(chartType, finalTheme); - } else { - const finalTheme = mergeTheme( - {}, - getThemeObject(this._currentThemeName), - getThemeObject(optionTheme), - getThemeObject(specTheme) - ); - this._currentTheme = processThemeByChartType(chartType, finalTheme); - } + const finalTheme = mergeTheme( + {}, + getThemeObject( + isObject(specTheme) && specTheme.type + ? specTheme.type + : isObject(optionTheme) && optionTheme.type + ? optionTheme.type + : this._currentThemeName + ), + getThemeObject(optionTheme), + getThemeObject(specTheme) + ); + this._currentTheme = processThemeByChartType(chartType, finalTheme); } else { currentTheme = getThemeObject(this._currentThemeName); this._currentTheme = processThemeByChartType(chartType, currentTheme); From 7632f9b445df80aecdb5eaccc4e641bd1fccc93f Mon Sep 17 00:00:00 2001 From: xile611 Date: Wed, 11 Mar 2026 11:30:21 +0800 Subject: [PATCH 07/24] docs: update changlog of rush --- .../@visactor/vchart/develop_2026-03-11-03-30.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 common/changes/@visactor/vchart/develop_2026-03-11-03-30.json diff --git a/common/changes/@visactor/vchart/develop_2026-03-11-03-30.json b/common/changes/@visactor/vchart/develop_2026-03-11-03-30.json new file mode 100644 index 0000000000..5f5bc535a7 --- /dev/null +++ b/common/changes/@visactor/vchart/develop_2026-03-11-03-30.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "fix: fix theme config of spec and option\n\n", + "type": "none", + "packageName": "@visactor/vchart" + } + ], + "packageName": "@visactor/vchart", + "email": "dingling112@gmail.com" +} \ No newline at end of file From e2fa68a3a66e008759efaed0285b189aa14e55da Mon Sep 17 00:00:00 2001 From: "lixuefei.1313" Date: Wed, 11 Mar 2026 15:09:16 +0800 Subject: [PATCH 08/24] feat: optimiz skill, add user manual --- skills/vchart-development-assistant/README.md | 66 +++++++++++++ skills/vchart-development-assistant/SKILL.md | 94 +++++++++++++------ 2 files changed, 132 insertions(+), 28 deletions(-) create mode 100644 skills/vchart-development-assistant/README.md diff --git a/skills/vchart-development-assistant/README.md b/skills/vchart-development-assistant/README.md new file mode 100644 index 0000000000..dc8d0f3b02 --- /dev/null +++ b/skills/vchart-development-assistant/README.md @@ -0,0 +1,66 @@ +# VChart Development Assistant - 用户使用说明 + +## 这个助手适合什么场景 + +- 从 0 到 1 生成图表(柱状图、折线图、饼图等) +- 修改已有图表样式(颜色、标签、图例、tooltip、坐标轴) +- 排查图表问题(不显示、报错、交互不生效、数据映射错误) +- 从截图/Figma 还原图表 +- 增加交互能力(点击事件、动态更新、联动高亮、导出图片、主题切换) + +## 如何提问效果最好 + +建议一次性提供以下信息: + +- 使用环境:原生 JS / React-VChart(`@visactor/react-vchart`)/ 其他框架 +- 目标:你想实现什么图表或效果 +- 数据:至少给 5~10 条样例数据(或字段结构) +- 当前代码:如果是改造/排错,贴出当前 spec 或关键代码 +- 期望与现状:预期效果 + 实际问题(报错信息/截图) + +推荐提问模板: + +```text +请用 VChart 帮我实现一个[图表类型]。 +技术栈:[JS / React-VChart] +数据样例:[粘贴数据] +需求:[例如:显示标签、点击柱子后打印数据、支持主题切换] +当前代码(可选):[粘贴 spec/组件代码] +问题(可选):[例如:图表空白、tooltip 不显示] +请给我可直接运行的完整 HTML(或 React 组件)并解释关键配置。 +``` + +## 可直接使用的示例 Prompt + +```text +用 VChart 生成一个基础柱状图,包含 xField、yField,并给出最小可运行示例。 +``` + +```text +在我现有柱状图基础上优化颜色、标签样式和图例可读性,保持数据结构不变。 +``` + +```text +帮我检查当前 VChart spec 的配置错误,指出问题位置并给出可直接替换的修复版本。 +``` + +## 你会得到什么输出 + +- 可直接运行的完整代码(默认包含完整 HTML) +- 关键配置说明(为什么这么配) +- 如果是排错场景:问题定位 + 修复建议 + 修复后代码 +- 如果有交互需求:同时给出 API 事件/状态/数据更新代码 + +## 常见问题建议 + +- 图表空白时,先检查 `xField` / `yField` 是否与数据字段名完全一致 +- 检查数据结构是否符合 VChart 要求(尤其是 `data` 和 `values`) +- 如果是 React 场景,确认依赖版本和组件导入方式正确 +- 问题无法复现时,优先提供最小复现代码和报错截图 + +## 参考文档 + +- VChart Skill Usage:`https://www.visactor.io/vchart/guide/tutorial_docs/VChart_Skill_Usage` +- VChart Quick Start:`https://www.visactor.io/vchart/guide/tutorial_docs/Getting_Started` +- VChart 配置项文档:`https://www.visactor.io/vchart/option` +- VChart API 文档:`https://www.visactor.io/vchart/api/API/vchart` diff --git a/skills/vchart-development-assistant/SKILL.md b/skills/vchart-development-assistant/SKILL.md index 378824164b..b7d068f7c0 100644 --- a/skills/vchart-development-assistant/SKILL.md +++ b/skills/vchart-development-assistant/SKILL.md @@ -5,6 +5,42 @@ description: VChart图表库专家助手,擅长创建、配置和调试VChart # VChart 图表开发助手 Skill +## 自我介绍策略 + +当用户询问本助手的能力范围(如"你能做什么"、"这个助手是什么"、"有什么功能")时,用第一人称简要概括: + +> 我是 VChart 图表开发助手,基于 VChart 2.0.0+ 版本,可以帮你: +> +> - 从零生成图表配置(柱状图、折线图、饼图等) +> - 诊断和修复图表问题(不显示、报错、交互不生效) +> - 从截图或 Figma 设计稿还原图表样式 +> - 实现交互功能(点击事件、动态更新、联动高亮、导出图片、主题切换) +> - 支持原生 JS 和 React-VChart(`@visactor/react-vchart`) + +如用户需要更详细的入门指引,推荐查阅官方教程:https://www.visactor.io/vchart/guide/tutorial_docs/Getting_Started + +**不要**在用户未询问时主动输出上述介绍。 + +--- + +## 信息不足时的引导策略 + +当用户首次提问信息不足时(缺少技术栈、数据样例、当前代码等),用一句话自然地引导补充,优先询问最关键的 1-2 个缺失信息,不要一次罗列所有问题。 + +引导优先级: + +1. **技术栈**(JS / React-VChart)— 影响模板选择和代码风格 +2. **数据样例或字段结构** — 影响字段映射,是最高频错误源 +3. **当前代码**(如果是排错/改造场景)— 影响诊断准确性 +4. **期望效果与实际问题** — 影响场景识别 + +示例引导话术: + +- "请问您是用原生 JS 还是 React-VChart?另外能否提供一份数据样例?" +- "方便贴一下当前的 spec 配置吗?我来帮您定位问题。" + +--- + ## 角色定义 你是一位 VChart 图表库专家助手,专门帮助用户解决 VChart 2.0.0+ 版本的图表开发问题。你具备以下能力: @@ -18,6 +54,8 @@ description: VChart图表库专家助手,擅长创建、配置和调试VChart - **主动发现问题**:生成代码后主动自检,提前预警潜在风险(如字段映射错误) - **快速响应反馈**:当用户反馈问题时,立即切换到诊断模式而非继续生成 +--- + ## 核心知识库 本 Skill 依赖以下结构化知识库: @@ -134,14 +172,14 @@ python3 scripts/generate_diagnosis_react_html.py \ **API 能力分类**: -| 能力类型 | 典型需求 | API 文档 | -|---------|---------|---------| -| 事件监听 | 点击响应、hover 效果 | `references/api/event-api.md` | -| 数据操作 | 动态更新、实时刷新 | `references/api/data-api.md` | -| 状态管理 | 高亮、选中 | `references/api/state-api.md` | -| 交互控制 | 手动触发 tooltip | `references/api/interaction-api.md` | -| 导出功能 | 下载图片 | `references/api/export-api.md` | -| 主题切换 | 深色模式 | `references/api/theme-api.md` | +| 能力类型 | 典型需求 | API 文档 | +| -------- | -------------------- | ----------------------------------- | +| 事件监听 | 点击响应、hover 效果 | `references/api/event-api.md` | +| 数据操作 | 动态更新、实时刷新 | `references/api/data-api.md` | +| 状态管理 | 高亮、选中 | `references/api/state-api.md` | +| 交互控制 | 手动触发 tooltip | `references/api/interaction-api.md` | +| 导出功能 | 下载图片 | `references/api/export-api.md` | +| 主题切换 | 深色模式 | `references/api/theme-api.md` | --- @@ -163,13 +201,13 @@ python3 scripts/generate_diagnosis_react_html.py \ **在当前场景中检测到 API 需求时,不切换场景,而是增强输出**: -| 当前场景 | 检测到 API 需求 | 增强动作 | -| -------- | ------------------- | ------------------------------ | -| 场景2 | "点击后获取数据" | 输出 Spec + 事件监听代码 | -| 场景2 | "动态更新数据" | 输出 Spec + 数据更新函数 | -| 场景3 | "联动高亮" | 输出 Spec + 状态管理代码 | -| 场景3 | "导出图片" | 输出 Spec + 导出按钮和函数 | -| 场景1 | API 代码报错 | 同时诊断 Spec 和 API 代码 | +| 当前场景 | 检测到 API 需求 | 增强动作 | +| -------- | ---------------- | -------------------------- | +| 场景2 | "点击后获取数据" | 输出 Spec + 事件监听代码 | +| 场景2 | "动态更新数据" | 输出 Spec + 数据更新函数 | +| 场景3 | "联动高亮" | 输出 Spec + 状态管理代码 | +| 场景3 | "导出图片" | 输出 Spec + 导出按钮和函数 | +| 场景1 | API 代码报错 | 同时诊断 Spec 和 API 代码 | #### 切换要点 @@ -192,7 +230,7 @@ python3 scripts/generate_diagnosis_react_html.py \ ### 主动提示 -发现风险��告知用户: +发现风险时告知用户: ``` 已生成配置 @@ -262,18 +300,18 @@ python3 scripts/generate_diagnosis_react_html.py \ **快速索引**:`references/api/API_INDEX.md` -| 用户需求 | 查询文档 | -| ---------------- | -------------------------------------- | -| 更新图表数据 | `references/api/data-api.md` | -| 响应点击/hover | `references/api/event-api.md` | -| 高亮/选中图元 | `references/api/state-api.md` | -| 手动触发tooltip | `references/api/interaction-api.md` | -| 切换主题 | `references/api/theme-api.md` | -| 导出图片 | `references/api/export-api.md` | -| 控制动画 | `references/api/animation-api.md` | -| 坐标位置转换 | `references/api/coordinate-api.md` | -| 控制图例 | `references/api/legend-api.md` | -| 调整尺寸 | `references/api/layout-api.md` | +| 用户需求 | 查询文档 | +| --------------- | ----------------------------------- | +| 更新图表数据 | `references/api/data-api.md` | +| 响应点击/hover | `references/api/event-api.md` | +| 高亮/选中图元 | `references/api/state-api.md` | +| 手动触发tooltip | `references/api/interaction-api.md` | +| 切换主题 | `references/api/theme-api.md` | +| 导出图片 | `references/api/export-api.md` | +| 控制动画 | `references/api/animation-api.md` | +| 坐标位置转换 | `references/api/coordinate-api.md` | +| 控制图例 | `references/api/legend-api.md` | +| 调整尺寸 | `references/api/layout-api.md` | **API 查询流程**: From a7785be834c1fb76fa89b868368af47de5c2473f Mon Sep 17 00:00:00 2001 From: xile611 Date: Thu, 12 Mar 2026 17:26:36 +0800 Subject: [PATCH 09/24] chore: upgrade vutils, vdataset, vscale, vlayouts to ~1.0.23 Co-Authored-By: Claude Opus 4.6 --- common/config/rush/pnpm-lock.yaml | 148 ++++++++++++------------- docs/package.json | 2 +- packages/openinula-vchart/package.json | 2 +- packages/react-vchart/package.json | 2 +- packages/vchart-extension/package.json | 6 +- packages/vchart/package.json | 8 +- packages/vutils-extension/package.json | 4 +- pnpm-lock.yaml | 39 ++++--- tools/story-player/package.json | 2 +- 9 files changed, 110 insertions(+), 103 deletions(-) diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index acff09fa49..fd6a870992 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -55,8 +55,8 @@ importers: specifier: 1.19.0-alpha.0 version: 1.19.0-alpha.0 '@visactor/vutils': - specifier: ~1.0.22 - version: 1.0.22 + specifier: ~1.0.23 + version: 1.0.23 axios: specifier: ^1.4.0 version: 1.13.2 @@ -209,8 +209,8 @@ importers: specifier: ~1.0.41 version: 1.0.41 '@visactor/vutils': - specifier: ~1.0.22 - version: 1.0.22 + specifier: ~1.0.23 + version: 1.0.23 react-is: specifier: ^18.2.0 version: 18.3.1 @@ -300,8 +300,8 @@ importers: specifier: ~1.0.41 version: 1.0.41 '@visactor/vutils': - specifier: ~1.0.22 - version: 1.0.22 + specifier: ~1.0.23 + version: 1.0.23 react-is: specifier: ^18.2.0 version: 18.3.1 @@ -523,11 +523,11 @@ importers: ../../packages/vchart: dependencies: '@visactor/vdataset': - specifier: ~1.0.22 - version: 1.0.22 + specifier: ~1.0.23 + version: 1.0.23 '@visactor/vlayouts': - specifier: ~1.0.22 - version: 1.0.22 + specifier: ~1.0.23 + version: 1.0.23 '@visactor/vrender-animate': specifier: ~1.0.41 version: 1.0.41 @@ -541,11 +541,11 @@ importers: specifier: ~1.0.41 version: 1.0.41 '@visactor/vscale': - specifier: ~1.0.22 - version: 1.0.22 + specifier: ~1.0.23 + version: 1.0.23 '@visactor/vutils': - specifier: ~1.0.22 - version: 1.0.22 + specifier: ~1.0.23 + version: 1.0.23 '@visactor/vutils-extension': specifier: workspace:2.0.19 version: link:../vutils-extension @@ -686,11 +686,11 @@ importers: specifier: workspace:2.0.19 version: link:../vchart '@visactor/vdataset': - specifier: ~1.0.22 - version: 1.0.22 + specifier: ~1.0.23 + version: 1.0.23 '@visactor/vlayouts': - specifier: ~1.0.22 - version: 1.0.22 + specifier: ~1.0.23 + version: 1.0.23 '@visactor/vrender-animate': specifier: ~1.0.41 version: 1.0.41 @@ -704,8 +704,8 @@ importers: specifier: ~1.0.41 version: 1.0.41 '@visactor/vutils': - specifier: ~1.0.22 - version: 1.0.22 + specifier: ~1.0.23 + version: 1.0.23 devDependencies: '@internal/bundler': specifier: workspace:* @@ -834,11 +834,11 @@ importers: ../../packages/vutils-extension: dependencies: '@visactor/vdataset': - specifier: ~1.0.22 - version: 1.0.22 + specifier: ~1.0.23 + version: 1.0.23 '@visactor/vutils': - specifier: ~1.0.22 - version: 1.0.22 + specifier: ~1.0.23 + version: 1.0.23 devDependencies: '@internal/bundler': specifier: workspace:* @@ -1098,7 +1098,7 @@ importers: version: 5.3.2 debug: specifier: 4.3.4 - version: 4.3.4(supports-color@9.4.0) + version: 4.3.4(supports-color@6.1.0) fs-extra: specifier: 10.1.0 version: 10.1.0 @@ -1269,8 +1269,8 @@ importers: specifier: ~1.0.41 version: 1.0.41 '@visactor/vutils': - specifier: ~1.0.22 - version: 1.0.22 + specifier: ~1.0.23 + version: 1.0.23 devDependencies: '@internal/bundler': specifier: workspace:* @@ -3061,11 +3061,11 @@ packages: '@visactor/vdataset@0.18.18': resolution: {integrity: sha512-lye23zpineMKV42JmuJaOY3fgl7aWhyDIwK9dWooqZzP14AFukPoK7ZvUeuKZihLrHxqtCg2VWEjovnh9O1RUg==} - '@visactor/vdataset@1.0.22': - resolution: {integrity: sha512-B+Xd7UuXNNLWRsH0ySd9LsvFFBz/S+lFN7ha7GU7SdTYr9P0ZExYyumQPntaa5iOMLxKysFxJw7t/Or70ZA6hQ==} + '@visactor/vdataset@1.0.23': + resolution: {integrity: sha512-zrLk9FBUWJoW6b30XnPKzXwAXl8USdLDfed6QZLsmdkylRU8V7yZeXE2aKwU8Lg1U4HmQngqmqOx7/QlbX44Tg==} - '@visactor/vlayouts@1.0.22': - resolution: {integrity: sha512-iTPJeROqmwBOBDoewDHYdEAe6MlDPgJ/1V1j+FcWr3zWGPDOSduoIDyjhB/FpkLaUQyhYCTCfCH3p2BDs3Wy4g==} + '@visactor/vlayouts@1.0.23': + resolution: {integrity: sha512-fK1f5LmuumhYanLArk5yrT4BZxu4IAmdc8WMwfB/KAvV+2dTPFuBUMWbWnDl0siQoU9SX9l/bLozUnI9n7BwBQ==} '@visactor/vmind@1.2.4-alpha.5': resolution: {integrity: sha512-8Z/MFLN0bMLUMofurQ4175AHA5+Yln9CwA6ub1pMzsa+xTjGKALj3D7SseHUi4LSKSB3UGFwckqhKlKynrOfsA==} @@ -3100,8 +3100,8 @@ packages: '@visactor/vscale@0.18.18': resolution: {integrity: sha512-iRG4kv+5Fv4KX3AxEfV95XU3I6OmF0QizyAhqHxKa7L1MaT+MRvDDk5zHWf1E8gialLbL2xDe3GnT6g/4u5jhA==} - '@visactor/vscale@1.0.22': - resolution: {integrity: sha512-DCCqBA9gBZexCsfYmUjRZM1OBp2Qr8dRIGOqWcFerINIDtpQatSS4c8Ah2r8pqkgiizSNeKgDoXOtsiPe9zqBQ==} + '@visactor/vscale@1.0.23': + resolution: {integrity: sha512-XePhYuRoNAp+8MeSMuEOOvhVAlOwvM1sDT2yFxE6zdwVB2GjZk8mH+5N2xQGQWk75YmGJjlJASFtgwjlb1yWxw==} '@visactor/vscale@1.0.4': resolution: {integrity: sha512-mXuX0gbQ5dmsU+dOfrDfFT45ijTZrFh1wYeIY44cdMhFo4v+tVdeihN0F+3CEI7oSZiZENbpJ7dXvxnu04xG/g==} @@ -3130,8 +3130,8 @@ packages: '@visactor/vutils@0.19.7': resolution: {integrity: sha512-1SSnkZgX1p/rSVIFEibrpN6rDdLfdETSI6lJI5JwV8I2paluM1mqz3jEeT3McmWygd/wyUVKAyoRxGXFKAsKEw==} - '@visactor/vutils@1.0.22': - resolution: {integrity: sha512-n+lKEeSQl1wGqRG829oQ4SwU6UysUiP9rpp0K87TwmERVMupSy6C0KcM2SGXGBLvnp1Cyjjciw5ZtYQXv3ZfKQ==} + '@visactor/vutils@1.0.23': + resolution: {integrity: sha512-M8SLqgdHhKN8QmQKTWD1gzEaHptpIV9pvMYvC6+VeOsqYvZZ6UdhSCAAczTYVo+m/uwcEC2JHSUspbrs8rzlRQ==} '@visactor/vutils@1.0.4': resolution: {integrity: sha512-GE149SM5WAc9DMNV7bGtPD4xHP68vbHMRuxGPJ3ndzAGLC/KuXpClteMw6bTY1fRX1vDLY/tQ/GVthgeOx4kDw==} @@ -12449,7 +12449,7 @@ snapshots: '@babel/traverse': 7.28.5 '@babel/types': 7.28.5 convert-source-map: 1.9.0 - debug: 4.3.4(supports-color@9.4.0) + debug: 4.3.4(supports-color@6.1.0) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -12516,7 +12516,7 @@ snapshots: '@babel/core': 7.20.12 '@babel/helper-compilation-targets': 7.27.2 '@babel/helper-plugin-utils': 7.27.1 - debug: 4.3.4(supports-color@9.4.0) + debug: 4.3.4(supports-color@6.1.0) lodash.debounce: 4.0.8 resolve: 1.22.11 semver: 6.3.1 @@ -13364,7 +13364,7 @@ snapshots: '@babel/parser': 7.28.5 '@babel/template': 7.27.2 '@babel/types': 7.28.5 - debug: 4.3.4(supports-color@9.4.0) + debug: 4.3.4(supports-color@6.1.0) transitivePeerDependencies: - supports-color @@ -13392,7 +13392,7 @@ snapshots: '@electron/get@1.14.1': dependencies: - debug: 4.3.4(supports-color@9.4.0) + debug: 4.3.4(supports-color@6.1.0) env-paths: 2.2.1 fs-extra: 8.1.0 got: 9.6.0 @@ -13424,7 +13424,7 @@ snapshots: '@eslint/eslintrc@1.4.1': dependencies: ajv: 6.12.6 - debug: 4.3.4(supports-color@9.4.0) + debug: 4.3.4(supports-color@6.1.0) espree: 9.6.1 globals: 13.24.0 ignore: 5.3.2 @@ -13494,7 +13494,7 @@ snapshots: '@humanwhocodes/config-array@0.9.5': dependencies: '@humanwhocodes/object-schema': 1.2.1 - debug: 4.3.4(supports-color@9.4.0) + debug: 4.3.4(supports-color@6.1.0) minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -14801,7 +14801,7 @@ snapshots: '@typescript-eslint/scope-manager': 5.30.0 '@typescript-eslint/type-utils': 5.30.0(eslint@8.18.0)(typescript@4.9.5) '@typescript-eslint/utils': 5.30.0(eslint@8.18.0)(typescript@4.9.5) - debug: 4.3.4(supports-color@9.4.0) + debug: 4.3.4(supports-color@6.1.0) eslint: 8.18.0 functional-red-black-tree: 1.0.1 ignore: 5.3.2 @@ -14818,7 +14818,7 @@ snapshots: '@typescript-eslint/scope-manager': 4.33.0 '@typescript-eslint/types': 4.33.0 '@typescript-eslint/typescript-estree': 4.33.0(typescript@4.9.5) - debug: 4.3.4(supports-color@9.4.0) + debug: 4.3.4(supports-color@6.1.0) eslint: 6.8.0 optionalDependencies: typescript: 4.9.5 @@ -14830,7 +14830,7 @@ snapshots: '@typescript-eslint/scope-manager': 4.33.0 '@typescript-eslint/types': 4.33.0 '@typescript-eslint/typescript-estree': 4.33.0(typescript@4.9.5) - debug: 4.3.4(supports-color@9.4.0) + debug: 4.3.4(supports-color@6.1.0) eslint: 8.18.0 optionalDependencies: typescript: 4.9.5 @@ -14842,7 +14842,7 @@ snapshots: '@typescript-eslint/scope-manager': 5.30.0 '@typescript-eslint/types': 5.30.0 '@typescript-eslint/typescript-estree': 5.30.0(typescript@4.9.5) - debug: 4.3.4(supports-color@9.4.0) + debug: 4.3.4(supports-color@6.1.0) eslint: 8.18.0 optionalDependencies: typescript: 4.9.5 @@ -14862,7 +14862,7 @@ snapshots: '@typescript-eslint/type-utils@5.30.0(eslint@8.18.0)(typescript@4.9.5)': dependencies: '@typescript-eslint/utils': 5.30.0(eslint@8.18.0)(typescript@4.9.5) - debug: 4.3.4(supports-color@9.4.0) + debug: 4.3.4(supports-color@6.1.0) eslint: 8.18.0 tsutils: 3.21.0(typescript@4.9.5) optionalDependencies: @@ -14878,7 +14878,7 @@ snapshots: dependencies: '@typescript-eslint/types': 4.33.0 '@typescript-eslint/visitor-keys': 4.33.0 - debug: 4.3.4(supports-color@9.4.0) + debug: 4.3.4(supports-color@6.1.0) globby: 11.1.0 is-glob: 4.0.3 semver: 7.7.3 @@ -14892,7 +14892,7 @@ snapshots: dependencies: '@typescript-eslint/types': 5.30.0 '@typescript-eslint/visitor-keys': 5.30.0 - debug: 4.3.4(supports-color@9.4.0) + debug: 4.3.4(supports-color@6.1.0) globby: 11.1.0 is-glob: 4.0.3 semver: 7.7.3 @@ -14977,12 +14977,12 @@ snapshots: simplify-geojson: 1.0.5 topojson-client: 3.1.0 - '@visactor/vdataset@1.0.22': + '@visactor/vdataset@1.0.23': dependencies: '@turf/flatten': 6.5.0 '@turf/helpers': 6.5.0 '@turf/rewind': 6.5.0 - '@visactor/vutils': 1.0.22 + '@visactor/vutils': 1.0.23 d3-dsv: 2.0.0 d3-geo: 1.12.1 d3-hexbin: 0.2.2 @@ -14997,12 +14997,12 @@ snapshots: simplify-geojson: 1.0.5 topojson-client: 3.1.0 - '@visactor/vlayouts@1.0.22': + '@visactor/vlayouts@1.0.23': dependencies: '@turf/helpers': 6.5.0 '@turf/invariant': 6.5.0 - '@visactor/vscale': 1.0.22 - '@visactor/vutils': 1.0.22 + '@visactor/vscale': 1.0.23 + '@visactor/vutils': 1.0.23 eventemitter3: 4.0.7 '@visactor/vmind@1.2.4-alpha.5': @@ -15029,7 +15029,7 @@ snapshots: '@visactor/vrender-animate@1.0.41': dependencies: '@visactor/vrender-core': 1.0.41 - '@visactor/vutils': 1.0.22 + '@visactor/vutils': 1.0.23 '@visactor/vrender-components@1.0.0-alpha.18': dependencies: @@ -15044,8 +15044,8 @@ snapshots: '@visactor/vrender-animate': 1.0.41 '@visactor/vrender-core': 1.0.41 '@visactor/vrender-kits': 1.0.41 - '@visactor/vscale': 1.0.22 - '@visactor/vutils': 1.0.22 + '@visactor/vscale': 1.0.23 + '@visactor/vutils': 1.0.23 '@visactor/vrender-core@1.0.0-alpha.18': dependencies: @@ -15054,7 +15054,7 @@ snapshots: '@visactor/vrender-core@1.0.41': dependencies: - '@visactor/vutils': 1.0.22 + '@visactor/vutils': 1.0.23 color-convert: 2.0.1 '@visactor/vrender-kits@1.0.0-alpha.18': @@ -15070,7 +15070,7 @@ snapshots: dependencies: '@resvg/resvg-js': 2.4.1 '@visactor/vrender-core': 1.0.41 - '@visactor/vutils': 1.0.22 + '@visactor/vutils': 1.0.23 gifuct-js: 2.1.2 lottie-web: 5.13.0 roughjs: 4.6.6 @@ -15086,9 +15086,9 @@ snapshots: dependencies: '@visactor/vutils': 0.18.18 - '@visactor/vscale@1.0.22': + '@visactor/vscale@1.0.23': dependencies: - '@visactor/vutils': 1.0.22 + '@visactor/vutils': 1.0.23 '@visactor/vscale@1.0.4': dependencies: @@ -15149,7 +15149,7 @@ snapshots: '@turf/invariant': 6.5.0 eventemitter3: 4.0.7 - '@visactor/vutils@1.0.22': + '@visactor/vutils@1.0.23': dependencies: '@turf/helpers': 6.5.0 '@turf/invariant': 6.5.0 @@ -15495,7 +15495,7 @@ snapshots: agent-base@6.0.2: dependencies: - debug: 4.3.4(supports-color@9.4.0) + debug: 4.3.4(supports-color@6.1.0) transitivePeerDependencies: - supports-color @@ -18601,7 +18601,7 @@ snapshots: ajv: 6.12.6 chalk: 2.4.2 cross-spawn: 6.0.6 - debug: 4.3.4(supports-color@9.4.0) + debug: 4.3.4(supports-color@6.1.0) doctrine: 3.0.0 eslint-scope: 4.0.3 eslint-utils: 1.4.3 @@ -18642,7 +18642,7 @@ snapshots: ajv: 6.12.6 chalk: 2.4.2 cross-spawn: 6.0.6 - debug: 4.3.4(supports-color@9.4.0) + debug: 4.3.4(supports-color@6.1.0) doctrine: 3.0.0 eslint-scope: 5.1.1 eslint-utils: 1.4.3 @@ -18685,7 +18685,7 @@ snapshots: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.6 - debug: 4.3.4(supports-color@9.4.0) + debug: 4.3.4(supports-color@6.1.0) doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.2.2 @@ -20136,7 +20136,7 @@ snapshots: dependencies: '@tootallnate/once': 1.1.2 agent-base: 6.0.2 - debug: 4.3.4(supports-color@9.4.0) + debug: 4.3.4(supports-color@6.1.0) transitivePeerDependencies: - supports-color @@ -20168,7 +20168,7 @@ snapshots: https-proxy-agent@5.0.1: dependencies: agent-base: 6.0.2 - debug: 4.3.4(supports-color@9.4.0) + debug: 4.3.4(supports-color@6.1.0) transitivePeerDependencies: - supports-color @@ -20762,7 +20762,7 @@ snapshots: istanbul-lib-source-maps@4.0.1: dependencies: - debug: 4.3.4(supports-color@9.4.0) + debug: 4.3.4(supports-color@6.1.0) istanbul-lib-coverage: 3.2.2 source-map: 0.6.1 transitivePeerDependencies: @@ -22390,7 +22390,7 @@ snapshots: micromark@2.11.4: dependencies: - debug: 4.3.4(supports-color@9.4.0) + debug: 4.3.4(supports-color@6.1.0) parse-entities: 2.0.0 transitivePeerDependencies: - supports-color @@ -25375,7 +25375,7 @@ snapshots: balanced-match: 1.0.2 chalk: 4.1.2 cosmiconfig: 6.0.0 - debug: 4.3.4(supports-color@9.4.0) + debug: 4.3.4(supports-color@6.1.0) execall: 2.0.0 file-entry-cache: 5.0.1 get-stdin: 8.0.0 @@ -25512,7 +25512,7 @@ snapshots: sumchecker@3.0.1: dependencies: - debug: 4.3.4(supports-color@9.4.0) + debug: 4.3.4(supports-color@6.1.0) transitivePeerDependencies: - supports-color @@ -26483,7 +26483,7 @@ snapshots: vite-node@0.30.1(@types/node@20.14.10)(less@4.1.3)(sass@1.32.11)(stylus@0.54.8)(sugarss@2.0.0)(terser@5.17.1): dependencies: cac: 6.7.14 - debug: 4.3.4(supports-color@9.4.0) + debug: 4.3.4(supports-color@6.1.0) mlly: 1.8.0 pathe: 1.1.2 picocolors: 1.1.1 @@ -26527,7 +26527,7 @@ snapshots: cac: 6.7.14 chai: 4.5.0 concordance: 5.0.4 - debug: 4.3.4(supports-color@9.4.0) + debug: 4.3.4(supports-color@6.1.0) local-pkg: 0.4.3 magic-string: 0.30.21 pathe: 1.1.2 @@ -26559,7 +26559,7 @@ snapshots: vue-eslint-parser@7.11.0(eslint@6.8.0): dependencies: - debug: 4.3.4(supports-color@9.4.0) + debug: 4.3.4(supports-color@6.1.0) eslint: 6.8.0 eslint-scope: 5.1.1 eslint-visitor-keys: 1.3.0 diff --git a/docs/package.json b/docs/package.json index 84fa6776c4..198055b2a9 100644 --- a/docs/package.json +++ b/docs/package.json @@ -18,7 +18,7 @@ "@visactor/vchart-extension": "workspace:2.0.19", "@visactor/vchart-theme": "~1.6.6", "@visactor/vmind": "1.2.4-alpha.5", - "@visactor/vutils": "~1.0.22", + "@visactor/vutils": "~1.0.23", "@visactor/vrender": "~1.0.41", "@visactor/vrender-kits": "~1.0.41", "@visactor/vtable": "1.19.0-alpha.0", diff --git a/packages/openinula-vchart/package.json b/packages/openinula-vchart/package.json index f8e6c442b3..1486242162 100644 --- a/packages/openinula-vchart/package.json +++ b/packages/openinula-vchart/package.json @@ -29,7 +29,7 @@ }, "dependencies": { "@visactor/vchart": "workspace:2.0.19", - "@visactor/vutils": "~1.0.22", + "@visactor/vutils": "~1.0.23", "@visactor/vrender-core": "~1.0.41", "@visactor/vrender-kits": "~1.0.41", "react-is": "^18.2.0" diff --git a/packages/react-vchart/package.json b/packages/react-vchart/package.json index 2bcfae6ae2..96dc373865 100644 --- a/packages/react-vchart/package.json +++ b/packages/react-vchart/package.json @@ -30,7 +30,7 @@ "dependencies": { "@visactor/vchart": "workspace:2.0.19", "@visactor/vchart-extension": "workspace:2.0.19", - "@visactor/vutils": "~1.0.22", + "@visactor/vutils": "~1.0.23", "@visactor/vrender-core": "~1.0.41", "@visactor/vrender-kits": "~1.0.41", "react-is": "^18.2.0" diff --git a/packages/vchart-extension/package.json b/packages/vchart-extension/package.json index 188f12e420..34d8e8307c 100644 --- a/packages/vchart-extension/package.json +++ b/packages/vchart-extension/package.json @@ -26,9 +26,9 @@ "@visactor/vrender-components": "~1.0.41", "@visactor/vrender-animate": "~1.0.41", "@visactor/vchart": "workspace:2.0.19", - "@visactor/vutils": "~1.0.22", - "@visactor/vdataset": "~1.0.22", - "@visactor/vlayouts": "~1.0.22" + "@visactor/vutils": "~1.0.23", + "@visactor/vdataset": "~1.0.23", + "@visactor/vlayouts": "~1.0.23" }, "devDependencies": { "@internal/bundler": "workspace:*", diff --git a/packages/vchart/package.json b/packages/vchart/package.json index fb00ba9e55..51bae70906 100644 --- a/packages/vchart/package.json +++ b/packages/vchart/package.json @@ -118,10 +118,10 @@ "cross-env": "^7.0.3" }, "dependencies": { - "@visactor/vutils": "~1.0.22", - "@visactor/vdataset": "~1.0.22", - "@visactor/vscale": "~1.0.22", - "@visactor/vlayouts": "~1.0.22", + "@visactor/vutils": "~1.0.23", + "@visactor/vdataset": "~1.0.23", + "@visactor/vscale": "~1.0.23", + "@visactor/vlayouts": "~1.0.23", "@visactor/vrender-core": "~1.0.41", "@visactor/vrender-kits": "~1.0.41", "@visactor/vrender-components": "~1.0.41", diff --git a/packages/vutils-extension/package.json b/packages/vutils-extension/package.json index c8e6e5dc2c..c179b40dd2 100644 --- a/packages/vutils-extension/package.json +++ b/packages/vutils-extension/package.json @@ -25,8 +25,8 @@ "test-watch": "DEBUG_MODE=1 jest --watch" }, "dependencies": { - "@visactor/vutils": "~1.0.22", - "@visactor/vdataset": "~1.0.22" + "@visactor/vutils": "~1.0.23", + "@visactor/vdataset": "~1.0.23" }, "devDependencies": { "@internal/bundler": "workspace:*", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9899e062d1..209a043bdd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,32 +1,39 @@ -lockfileVersion: '6.0' +lockfileVersion: '9.0' settings: autoInstallPeers: true excludeLinksFromLockfile: false -dependencies: - js-yaml: - specifier: ^4.1.0 - version: 4.1.0 +importers: -devDependencies: - '@types/js-yaml': - specifier: ^4.0.9 - version: 4.0.9 + .: + dependencies: + js-yaml: + specifier: ^4.1.0 + version: 4.1.1 + devDependencies: + '@types/js-yaml': + specifier: ^4.0.9 + version: 4.0.9 packages: - /@types/js-yaml@4.0.9: + '@types/js-yaml@4.0.9': resolution: {integrity: sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==} - dev: true - /argparse@2.0.1: + argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - dev: false - /js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + js-yaml@4.1.1: + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} hasBin: true + +snapshots: + + '@types/js-yaml@4.0.9': {} + + argparse@2.0.1: {} + + js-yaml@4.1.1: dependencies: argparse: 2.0.1 - dev: false diff --git a/tools/story-player/package.json b/tools/story-player/package.json index 70b72ff595..c632f49e03 100644 --- a/tools/story-player/package.json +++ b/tools/story-player/package.json @@ -60,6 +60,6 @@ "@visactor/vrender-kits": "~1.0.41", "@visactor/vchart": "workspace:2.0.19", "@visactor/vrender": "~1.0.41", - "@visactor/vutils": "~1.0.22" + "@visactor/vutils": "~1.0.23" } } \ No newline at end of file From fe799cd78655528760a1f78210c29f8eec24f156 Mon Sep 17 00:00:00 2001 From: xile611 Date: Thu, 12 Mar 2026 18:02:21 +0800 Subject: [PATCH 10/24] chore: add change file for dependency upgrade Co-Authored-By: Claude Opus 4.6 --- .../@visactor/vchart/upgrade-deps_20260312.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 common/changes/@visactor/vchart/upgrade-deps_20260312.json diff --git a/common/changes/@visactor/vchart/upgrade-deps_20260312.json b/common/changes/@visactor/vchart/upgrade-deps_20260312.json new file mode 100644 index 0000000000..974163ff03 --- /dev/null +++ b/common/changes/@visactor/vchart/upgrade-deps_20260312.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "packageName": "@visactor/vchart", + "comment": "chore: upgrade vutils, vdataset, vscale, vlayouts to ~1.0.23", + "type": "none" + } + ], + "packageName": "@visactor/vchart", + "email": "test@example.com" +} From 25e23f2df1c9c41ef0df6249ab7aeb86ac5b77bf Mon Sep 17 00:00:00 2001 From: "lixuefei.1313" Date: Tue, 17 Mar 2026 14:14:47 +0800 Subject: [PATCH 11/24] fix(vchart): fix mark state persistence issue during updateSpec --- ...tate-when-updateSpec_2026-03-17-06-14.json | 11 ++++++++ packages/vchart/src/compile/mark/interface.ts | 1 + .../src/compile/mark/mark-state-manager.ts | 4 +++ packages/vchart/src/mark/base/base-mark.ts | 6 +++++ packages/vchart/src/mark/interface/common.ts | 2 ++ .../vchart/src/series/base/base-series.ts | 1 + .../plan.md | 25 +++++++++++++++++++ 7 files changed, 50 insertions(+) create mode 100644 common/changes/@visactor/vchart/feat-fix-issue-of-mark-state-when-updateSpec_2026-03-17-06-14.json create mode 100644 specs/009-fix-issue-of-mark-state-when-updateSpec/plan.md diff --git a/common/changes/@visactor/vchart/feat-fix-issue-of-mark-state-when-updateSpec_2026-03-17-06-14.json b/common/changes/@visactor/vchart/feat-fix-issue-of-mark-state-when-updateSpec_2026-03-17-06-14.json new file mode 100644 index 0000000000..fb73222957 --- /dev/null +++ b/common/changes/@visactor/vchart/feat-fix-issue-of-mark-state-when-updateSpec_2026-03-17-06-14.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "update changes for 009-fix-issue-of-mark-state-when-updateSpec: Fix an issue where mark states were not properly cleared when updateSpec was called, causing incorrect state persistence.", + "type": "none", + "packageName": "@visactor/vchart" + } + ], + "packageName": "@visactor/vchart", + "email": "lixuef1313@163.com" +} \ No newline at end of file diff --git a/packages/vchart/src/compile/mark/interface.ts b/packages/vchart/src/compile/mark/interface.ts index 01c0568fca..b1c26c9435 100644 --- a/packages/vchart/src/compile/mark/interface.ts +++ b/packages/vchart/src/compile/mark/interface.ts @@ -64,6 +64,7 @@ export interface IMarkStateManager { addStateInfo: (stateInfo: IStateInfo) => void; changeStateInfo: (stateInfo: Partial) => void; clearStateInfo: (stateValues: StateValue[]) => void; + clearAllStateInfo: () => void; checkOneState: (renderNode: IMarkGraphic, datum: Datum[], state: IStateInfo) => 'in' | 'out' | 'skip'; checkState: (renderNode: IMarkGraphic, datum: Datum[]) => StateValue[]; getStateMap: () => StateValueMap; diff --git a/packages/vchart/src/compile/mark/mark-state-manager.ts b/packages/vchart/src/compile/mark/mark-state-manager.ts index c7d1d065bf..1374d48ef2 100644 --- a/packages/vchart/src/compile/mark/mark-state-manager.ts +++ b/packages/vchart/src/compile/mark/mark-state-manager.ts @@ -123,6 +123,10 @@ export class MarkStateManager extends StateManager implements IMarkStateManager }); } + clearAllStateInfo() { + this._stateInfoList = []; + } + protected _isMultiMark() { return !this._mark || isMultiDatumMark(this._mark.type as MarkTypeEnum); } diff --git a/packages/vchart/src/mark/base/base-mark.ts b/packages/vchart/src/mark/base/base-mark.ts index 7765d236ca..379ba3bde2 100644 --- a/packages/vchart/src/mark/base/base-mark.ts +++ b/packages/vchart/src/mark/base/base-mark.ts @@ -2056,4 +2056,10 @@ export class BaseMark extends GrammarItem implements IMar runAnimation() { this._runStateAnimation(this.getGraphics()); } + + clearBeforeReInit() { + this.state.clearAllStateInfo(); + this.uncommit(); + this.stateStyle = {}; + } } diff --git a/packages/vchart/src/mark/interface/common.ts b/packages/vchart/src/mark/interface/common.ts index 9ead7699d6..56df36e444 100644 --- a/packages/vchart/src/mark/interface/common.ts +++ b/packages/vchart/src/mark/interface/common.ts @@ -246,6 +246,8 @@ export interface IMarkRaw extends ICompilableMark { disableAnimationByState: (state: string | string[]) => void; /** 启用状态动画 */ enableAnimationByState: (state: string | string[]) => void; + /** 重新加载前清除缓存 */ + clearBeforeReInit: () => void; } export type IMark = IMarkRaw; diff --git a/packages/vchart/src/series/base/base-series.ts b/packages/vchart/src/series/base/base-series.ts index 725e6bc791..5214cbbf02 100644 --- a/packages/vchart/src/series/base/base-series.ts +++ b/packages/vchart/src/series/base/base-series.ts @@ -1109,6 +1109,7 @@ export abstract class BaseSeries extends BaseModel imp const marks = this.getMarksWithoutRoot(); // FIXME: 合并 mark spec 的时机是否需要统一调整到 this.initMarkStyle() 中? marks.forEach(mark => { + mark.clearBeforeReInit(); (this._spec as any)[mark.name] && this.initMarkStyleWithSpec(mark, (this._spec as any)[mark.name]); }); this.initMarkStyle(); diff --git a/specs/009-fix-issue-of-mark-state-when-updateSpec/plan.md b/specs/009-fix-issue-of-mark-state-when-updateSpec/plan.md new file mode 100644 index 0000000000..d25d86b062 --- /dev/null +++ b/specs/009-fix-issue-of-mark-state-when-updateSpec/plan.md @@ -0,0 +1,25 @@ +# Implementation Plan: Fix mark state issue during updateSpec + +## Summary +Fix an issue where mark states were not properly cleared when `updateSpec` was called, causing incorrect state persistence. + +## Technical Context +The `updateSpec` process re-initializes marks but previous state information was lingering. +Changes include: +- Added `clearAllStateInfo` method to `IMarkStateManager` interface and implementation. +- Added `clearBeforeReInit` method to `IMarkRaw` interface and implementation. +- Invoked `clearBeforeReInit` in `BaseMark` during re-initialization. +- Updated `BaseSeries` to handle state cleanup during spec updates. + +### Source Code (repository root) +``` +packages/vchart/src/compile/mark/interface.ts +packages/vchart/src/compile/mark/mark-state-manager.ts +packages/vchart/src/mark/base/base-mark.ts +packages/vchart/src/mark/interface/common.ts +packages/vchart/src/series/base/base-series.ts +``` + +## Verification Plan +- Verify that mark states (e.g., hover, select) are reset correctly after `updateSpec`. +- Ensure no regression in normal state interactions. From 55f60538b4f9e07937891b0f0bfac62147ee857b Mon Sep 17 00:00:00 2001 From: "lixuefei.1313" Date: Tue, 17 Mar 2026 14:14:47 +0800 Subject: [PATCH 12/24] fix(vchart): fix mark state persistence issue during updateSpec --- packages/vchart/src/mark/base/base-mark.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/vchart/src/mark/base/base-mark.ts b/packages/vchart/src/mark/base/base-mark.ts index 379ba3bde2..5be19dcc09 100644 --- a/packages/vchart/src/mark/base/base-mark.ts +++ b/packages/vchart/src/mark/base/base-mark.ts @@ -1087,7 +1087,11 @@ export class BaseMark extends GrammarItem implements IMar return; } this._product = mark.getProduct(); + this._product.clearStates(); this._graphics = mark.getGraphics(); + this._graphics.forEach(g => { + g.clearStates(); + }); this._graphicMap = (mark as any)._graphicMap; this._graphicMap.forEach(g => { @@ -2061,5 +2065,8 @@ export class BaseMark extends GrammarItem implements IMar this.state.clearAllStateInfo(); this.uncommit(); this.stateStyle = {}; + this.getGraphics().forEach(g => { + g.clearStates(); + }); } } From dabd616ae9cecda7b8dc01e3077607127cadb66a Mon Sep 17 00:00:00 2001 From: xuefei1313 Date: Fri, 20 Mar 2026 06:33:02 +0000 Subject: [PATCH 13/24] feat(vchart,vchart-types): Add hideWhenEmpty axis option for cartesian axes --- .cursor/rules/specify-rules.mdc | 3 +- .../010-hide-empty-axes_2026-03-20-06-29.json | 11 ++ .../axis/cartesian/interface/spec.d.ts | 1 + .../cartesian/axis/hide-when-empty.test.ts | 122 ++++++++++++++++++ .../vchart/src/component/axis/base-axis.ts | 53 +++++++- .../src/component/axis/cartesian/axis.ts | 11 +- .../axis/cartesian/interface/spec.ts | 7 + .../component/axis/mixin/band-axis-mixin.ts | 2 + .../component/axis/mixin/linear-axis-mixin.ts | 2 + .../vchart/src/component/axis/polar/axis.ts | 2 +- .../ICartesianAxisSpec-Type-Definition.md | 17 +++ .../checklists/requirements.md | 34 +++++ .../contracts/interface.ts | 7 + specs/010-hide-empty-axes/data-model.md | 56 ++++++++ specs/010-hide-empty-axes/plan.md | 85 ++++++++++++ specs/010-hide-empty-axes/quickstart.md | 54 ++++++++ specs/010-hide-empty-axes/research.md | 40 ++++++ specs/010-hide-empty-axes/spec.md | 89 +++++++++++++ specs/010-hide-empty-axes/tasks.md | 43 ++++++ 19 files changed, 632 insertions(+), 7 deletions(-) create mode 100644 common/changes/@visactor/vchart/010-hide-empty-axes_2026-03-20-06-29.json create mode 100644 packages/vchart/__tests__/unit/component/cartesian/axis/hide-when-empty.test.ts create mode 100644 specs/010-hide-empty-axes/checklists/requirements.md create mode 100644 specs/010-hide-empty-axes/contracts/interface.ts create mode 100644 specs/010-hide-empty-axes/data-model.md create mode 100644 specs/010-hide-empty-axes/plan.md create mode 100644 specs/010-hide-empty-axes/quickstart.md create mode 100644 specs/010-hide-empty-axes/research.md create mode 100644 specs/010-hide-empty-axes/spec.md create mode 100644 specs/010-hide-empty-axes/tasks.md diff --git a/.cursor/rules/specify-rules.mdc b/.cursor/rules/specify-rules.mdc index f4448e2042..56092a6035 100644 --- a/.cursor/rules/specify-rules.mdc +++ b/.cursor/rules/specify-rules.mdc @@ -6,6 +6,7 @@ Auto-generated from all feature plans. Last updated: 2026-01-15 - TypeScript 4.x+ (Project uses TS) + `@visactor/vchart` (Core logic), `@visactor/react-vchart` (React wrapper) (007-fix-datazoom-react) - N/A (In-memory chart state) (007-fix-datazoom-react) - Markdown + JSON(文档内容与菜单配置) + `@internal/docs` 文档构建体系、`docs/assets/guide/menu.json` 导航配置、现有教程目录结构 (001-vchart-skill-tutorial) +- TypeScript 4.9.5 + `@visactor/vchart`, `@visactor/vutils`, `@visactor/vrender-components` (010-hide-empty-axes) - TypeScript/React 18 + @visactor/react-vchart, @visactor/vchar (001-react-vchart-demo) @@ -27,9 +28,9 @@ npm test && npm run lint TypeScript 4.9.5: Follow standard conventions ## Recent Changes +- 010-hide-empty-axes: Added TypeScript 4.9.5 + `@visactor/vchart`, `@visactor/vutils`, `@visactor/vrender-components` - 001-vchart-skill-tutorial: Added Markdown + JSON(文档内容与菜单配置) + `@internal/docs` 文档构建体系、`docs/assets/guide/menu.json` 导航配置、现有教程目录结构 - 007-fix-datazoom-react: Added TypeScript 4.x+ (Project uses TS) + `@visactor/vchart` (Core logic), `@visactor/react-vchart` (React wrapper) -- 007-fix-datazoom-react: Added [if applicable, e.g., PostgreSQL, CoreData, files or N/A] diff --git a/common/changes/@visactor/vchart/010-hide-empty-axes_2026-03-20-06-29.json b/common/changes/@visactor/vchart/010-hide-empty-axes_2026-03-20-06-29.json new file mode 100644 index 0000000000..f540ce9ec1 --- /dev/null +++ b/common/changes/@visactor/vchart/010-hide-empty-axes_2026-03-20-06-29.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "update changes for 010-hide-empty-axes: Add an opt-in hideWhenEmpty axis option for cartesian axes.", + "type": "none", + "packageName": "@visactor/vchart" + } + ], + "packageName": "@visactor/vchart", + "email": "lixuef1313@163.com" +} \ No newline at end of file diff --git a/packages/vchart-types/types/component/axis/cartesian/interface/spec.d.ts b/packages/vchart-types/types/component/axis/cartesian/interface/spec.d.ts index 29e8f4b791..cae05123be 100644 --- a/packages/vchart-types/types/component/axis/cartesian/interface/spec.d.ts +++ b/packages/vchart-types/types/component/axis/cartesian/interface/spec.d.ts @@ -21,6 +21,7 @@ export type ICartesianZ = { orient: 'z'; }; export type ICartesianAxisCommonSpec = ICommonAxisSpec & { + hideWhenEmpty?: boolean; grid?: IGrid; subGrid?: IGrid; domainLine?: ICartesianDomainLine; diff --git a/packages/vchart/__tests__/unit/component/cartesian/axis/hide-when-empty.test.ts b/packages/vchart/__tests__/unit/component/cartesian/axis/hide-when-empty.test.ts new file mode 100644 index 0000000000..eb2b7080f5 --- /dev/null +++ b/packages/vchart/__tests__/unit/component/cartesian/axis/hide-when-empty.test.ts @@ -0,0 +1,122 @@ +import { default as VChartConstructor } from '../../../../../src'; +import { createCanvas, removeDom } from '../../../../util/dom'; + +describe('cartesian axis hideWhenEmpty', () => { + let canvasDom: HTMLCanvasElement; + let vchart: any; + + beforeEach(() => { + canvasDom = createCanvas(); + canvasDom.style.position = 'relative'; + canvasDom.style.width = '500px'; + canvasDom.style.height = '500px'; + canvasDom.width = 500; + canvasDom.height = 500; + }); + + afterEach(() => { + removeDom(canvasDom); + vchart?.release(); + }); + + const getAxis = (orient: string) => vchart.getComponents().find(com => com.layout?.layoutOrient === orient) as any; + + test('should hide axis on initial render when bound series has no collected data', () => { + vchart = new VChartConstructor( + { + type: 'line', + width: 400, + height: 300, + data: [{ id: 'lineData', values: [] }], + axes: [ + { id: 'axis-left', orient: 'left', hideWhenEmpty: true }, + { id: 'axis-bottom', orient: 'bottom', type: 'band' } + ], + series: [{ type: 'line', dataId: 'lineData', xField: 'x', yField: 'y' }] + } as any, + { + renderCanvas: canvasDom, + animation: false + } + ); + + vchart.renderSync(); + + const leftAxis = getAxis('left'); + expect(leftAxis.getVisible()).toBe(false); + expect(leftAxis.getLayoutRect().width).toBe(0); + }); + + test('should keep default behavior when hideWhenEmpty is not enabled', () => { + vchart = new VChartConstructor( + { + type: 'line', + width: 400, + height: 300, + data: [{ id: 'lineData', values: [] }], + axes: [ + { id: 'axis-left', orient: 'left' }, + { id: 'axis-bottom', orient: 'bottom', type: 'band' } + ], + series: [{ type: 'line', dataId: 'lineData', xField: 'x', yField: 'y' }] + } as any, + { + renderCanvas: canvasDom, + animation: false + } + ); + + vchart.renderSync(); + + const leftAxis = getAxis('left'); + expect(leftAxis.getVisible()).toBe(true); + }); + + test('should only hide empty bound axes and show them again after data updates', async () => { + vchart = new VChartConstructor( + { + type: 'common', + width: 400, + height: 300, + data: [ + { id: 'emptyLine', values: [] }, + { + id: 'activeLine', + values: [ + { x: 'Mon', y: 10 }, + { x: 'Tue', y: 20 } + ] + } + ], + axes: [ + { id: 'axis-left', orient: 'left', seriesIndex: [0], hideWhenEmpty: true }, + { id: 'axis-right', orient: 'right', seriesIndex: [1], hideWhenEmpty: true }, + { id: 'axis-bottom', orient: 'bottom', type: 'band' } + ], + series: [ + { type: 'line', dataId: 'emptyLine', xField: 'x', yField: 'y' }, + { type: 'line', dataId: 'activeLine', xField: 'x', yField: 'y' } + ] + } as any, + { + renderCanvas: canvasDom, + animation: false + } + ); + + vchart.renderSync(); + + const leftAxis = getAxis('left'); + const rightAxis = getAxis('right'); + expect(leftAxis.getVisible()).toBe(false); + expect(rightAxis.getVisible()).toBe(true); + + await vchart.updateData('emptyLine', [ + { x: 'Mon', y: 5 }, + { x: 'Tue', y: 15 } + ]); + + expect(leftAxis.getVisible()).toBe(true); + expect(leftAxis.getLayoutRect().width).toBeGreaterThan(0); + }); +}); diff --git a/packages/vchart/src/component/axis/base-axis.ts b/packages/vchart/src/component/axis/base-axis.ts index bf7e7fad78..5afe6dd768 100644 --- a/packages/vchart/src/component/axis/base-axis.ts +++ b/packages/vchart/src/component/axis/base-axis.ts @@ -96,10 +96,16 @@ export abstract class AxisComponent { @@ -378,6 +400,31 @@ export abstract class AxisComponent 0; + } + + protected _refreshVisibilityByData() { + const nextVisible = this._specVisible && (!this._hideWhenEmpty || this._hasCollectedSeriesData()); + const changed = this._visible !== nextVisible; + this._visible = nextVisible; + + if (this._axisMark || this._gridMark) { + this._syncComponentVisibility(); + } + + if (changed) { + this._forceLayout(); + } + + return changed; + } + + protected _syncComponentVisibility() { + this._axisMark?.setSimpleStyle({ visible: this._visible }); + this._gridMark?.setSimpleStyle({ visible: this._visible && this._spec.grid?.visible !== false }); + } + protected _clearRawDomain() { // 留给各个类型的 axis 来 override } diff --git a/packages/vchart/src/component/axis/cartesian/axis.ts b/packages/vchart/src/component/axis/cartesian/axis.ts index d8976623f2..a058a91b11 100644 --- a/packages/vchart/src/component/axis/cartesian/axis.ts +++ b/packages/vchart/src/component/axis/cartesian/axis.ts @@ -302,7 +302,7 @@ export abstract class CartesianAxis getBoundsInRect: update tick attr -> forceLayout -> updateLayoutAttr: update tick attr -> chart layout -> scale update -> mark encode // 问题: chart layout之后, scale发生变化, 导致tick 和 mark position 不同步 // 解决方案: chart layout 之后重新计算tick位置 @@ -805,6 +805,11 @@ export abstract class CartesianAxis { + if (!this._visible) { + this._syncComponentVisibility(); + return; + } + const startPoint = this.getLayoutStartPoint(); const { grid: updateGridAttrs, ...updateAxisAttrs } = this._getUpdateAttribute(false); const axisAttrs = mergeSpec({ x: startPoint.x, y: startPoint.y }, this._axisStyle, updateAxisAttrs); @@ -822,6 +827,8 @@ export abstract class CartesianAxis number; _onTickDataChange: (compilableData: CompilableData) => void; registerTicksTransform: () => string; + _refreshVisibilityByData: () => boolean; } export class BandAxisMixin { @@ -199,6 +200,7 @@ export class BandAxisMixin { } } this.transformScaleDomain(); + this._refreshVisibilityByData(); this.event.emit(ChartEvent.scaleDomainUpdate, { model: this as unknown as IModel }); this.event.emit(ChartEvent.scaleUpdate, { model: this as unknown as IModel, value: 'domain' }); } diff --git a/packages/vchart/src/component/axis/mixin/linear-axis-mixin.ts b/packages/vchart/src/component/axis/mixin/linear-axis-mixin.ts index a73a417db3..29b3143cb7 100644 --- a/packages/vchart/src/component/axis/mixin/linear-axis-mixin.ts +++ b/packages/vchart/src/component/axis/mixin/linear-axis-mixin.ts @@ -52,6 +52,7 @@ export interface LinearAxisMixin { _orient: IOrientType; _option: IComponentOption; niceLabelFormatter: (value: StringOrNumber) => StringOrNumber; + _refreshVisibilityByData: () => boolean; } export class LinearAxisMixin { @@ -403,6 +404,7 @@ export class LinearAxisMixin { this._updateNiceLabelFormatter(domain); this._domainAfterSpec = this._scale.domain(); + this._refreshVisibilityByData(); this.event.emit(ChartEvent.scaleDomainUpdate, { model: this as any }); this.event.emit(ChartEvent.scaleUpdate, { model: this as any, value: 'domain' }); } diff --git a/packages/vchart/src/component/axis/polar/axis.ts b/packages/vchart/src/component/axis/polar/axis.ts index 9bb5755bf1..6eee0e97ab 100644 --- a/packages/vchart/src/component/axis/polar/axis.ts +++ b/packages/vchart/src/component/axis/polar/axis.ts @@ -201,7 +201,7 @@ export abstract class PolarAxis