The animation arrangement in VChart's source code mainly revolves around generating and configuring animations to achieve animation effects in different states. Below, we interpret its implementation from several key functions and type definitions:
Type Definitions and Constants
utils.ts
Apply
// Import various types and constants
import type { IAnimationConfig } from '@visactor/vgrammar-core';
// ... other imports ...
/**
Define an array of animation states, including all keys in the default animation configuration and 'normal'
*/
export const AnimationStates = [...Object.keys(DEFAULT_ANIMATION_CONFIG), 'normal'];
Type Imports: Various types are imported from different modules, such as IAnimationConfig, IElement, etc., which are used to define animation configurations, elements, etc., ensuring type safety in the code.
AnimationStates Constant: Contains all possible animation states, including states in the default animation configuration and the 'normal' state, used for subsequent traversal and processing of animation configurations in different states.
Create an empty object userConfig to store user animation configurations.
Assign the corresponding configuration to userConfig based on different animation configurations in spec (such as animationAppear, animationDisappear, etc.).
Call the uniformAnimationConfig function to unify animation configurations.
Return the generated user animation configuration.
stateConfig: Configuration object for the animation type.
dataIndex: Function that returns the index of the data item in the animation sequence.
dataCount: Optional function that returns the total number of data items.
Implementation logic:
Destructure oneByOne, duration, delay, and delayAfter configurations from stateConfig.
Configure the delay time delay before the element appears, calculate the delay time based on the data item index and animation parameters.
Configure the delay time delayAfter after the element appears, also calculate the delay time based on the data item index and animation parameters.
Remove the no longer needed oneByOne parameter.
Return the updated animation configuration object.
Other auxiliary functions
defaultDataIndex: Get the default data index based on the data item or animation parameters.
shouldMarkDoMorph: Determine whether the specified mark should perform morphing animation.
isTimeLineAnimation and isChannelAnimation: Determine whether the animation configuration is a timeline animation or a channel animation.
uniformAnimationConfig: Unify the animation configuration, process and convert functions in the configuration.
traverseSpec: Traverse and transform the given object or array, applying the provided transformation function.
isAnimationEnabledForSeries: Determine whether the series has animation enabled, check based on series specifications, area animation properties, and data volume.
Summary
The animation orchestration implementation of VChart mainly merges and processes default configurations and user configurations through a series of functions and type definitions to generate the final animation configuration. At the same time, it provides functions such as executing animations one by one, morphing animations, and logic to determine whether animations are enabled, ensuring flexibility and configurability of animations in different scenarios.
Interpretation of Animation Orchestration Implementation
Animation orchestration refers to combining multiple animation tasks in a certain order or condition to form a coherent and complex animation sequence. In VChart, the design of animation orchestration allows developers to create multi-stage, multi-element collaborative animation effects, thereby enhancing the visual expressiveness and user experience of the chart. The following is a detailed interpretation of the implementation.
1. Concept of Animation Orchestration
Animation Orchestration is to enhance the effect of data visualization through carefully designed animation sequences. It is not just simple animation stacking, but also considers the coordination between animations, timeline management, and state transitions. VChart provides flexible tools to achieve animation orchestration, including but not limited to:
Chained Animation: Multiple animations are executed sequentially.
Parallel Animation: Multiple animations are executed simultaneously.
Conditional Trigger: Certain animations are triggered based on specific conditions.
Event Driven: Animations are triggered based on user interactions or other events.
2. Animation Configuration Structure
IAnimationSpec Interface
The IAnimationSpec interface defines the basic structure of animation configuration, which includes animation settings for different states. For animation orchestration, it mainly involves the following properties:
animationState: Used to describe state transition animations, can be used to build complex animation sequences.
animationNormal: Used to describe persistent loop animations, can be used as background animations in animation orchestration.
Each attribute can accept a boolean value (enable/disable), a preset configuration object, or a custom configuration object as a parameter, providing developers with a high degree of customization possibilities.
3. Animation Task Interface
IAnimationTask Interface
To support complex animation orchestration, VChart introduces the IAnimationTask interface to describe the data structure of animation tasks. Each task includes a time offset, an action queue, and a list of successor tasks, forming a chain-like animation execution mechanism.
This design allows multiple animation tasks to be executed sequentially or concurrently, achieving more complex and delicate animation effects.
4. Specific Implementation of Animation Orchestration
Taking the creation of a bar chart with animation orchestration as an example, suppose we want to achieve the following effects:
When the page loads, all bars grow from the bottom up;
After the bars finish growing, a pulse effect is added to the top to attract the user's attention;
If new data is added, new bars fade in, and existing bars slightly scale to indicate changes.
Step 1: Define Animation Configuration
First, specify animationAppear, animationEnter, animationUpdate, etc., in the chart configuration for the bar chart series. Here we can choose built-in animation types and adjust their duration and easing functions.
Ensure that the required animations have been correctly registered in the system. This step is usually completed at project startup or explicitly called where needed.
With the above configuration, we can initialize a VChart instance and pass the configuration to it. This will trigger the chart rendering process and apply the corresponding animation effects.
To achieve animation choreography, we need to construct a task chain that includes multiple animation tasks. Each task can be a single animation or a composite animation (i.e., containing multiple subtasks). Here are the specific implementation steps:
Define Animation Tasks: First, define each individual animation task, including their time offsets, action queues, and successor task lists.
Composite Animation Tasks: Next, combine these tasks into a complete animation choreography. For example, we can create a task chain that includes entrance animations and animations in the normal state.
Once the chart is rendered, any changes in the data will automatically trigger animations. For example, when new data is added, the enter task will be triggered; when data is updated, the update task takes effect; and when data is removed, the exit task comes into play.
In this example, the updateSeriesData method triggers a series of animations:
For newly added data points (the fourth data point), the enter task will make it gradually appear with a fade-in effect.
For existing data points (the first three data points), the update task will adjust their size based on the new data values and transition with a scaling effect.
Step 6: Dynamically Control Animation Orchestration
In some cases, you may want to dynamically control the behavior of animation orchestration, such as changing the speed or style of the animation. VChart provides flexible methods to achieve this.
5. Internal Implementation of Animation Orchestration
AnimateManager Class
The AnimateManager class is responsible for managing and coordinating the state of all animations. It implements the IAnimate interface and provides methods to update and retrieve animation states. For animation orchestration, AnimateManager ensures that these animation tasks are executed in a predetermined order or condition.
This code demonstrates how to execute a set of animation tasks using the arrangeAnimations method. The action queue in each task will be executed one by one, and then subsequent tasks will be recursively processed according to the timeOffset attribute. This allows for the construction of an ordered animation sequence, achieving complex animation orchestration effects.
6. Advanced Features of Animation Orchestration
Conditional Triggering and Event Listening
To increase the flexibility of animation orchestration, VChart also provides conditional triggering and event listening features. For example, animations can be triggered by listening to user interaction events (such as clicks, hovers), or dynamically adjust animation behavior based on specific conditions (such as data thresholds).
// 监听用户交互事件
chart.on('element:click', (event) => {
const element = event.detail.element;
if (element) {
// 根据点击事件触发动画
this.triggerCustomAnimation(element);
}
});
// 条件触发动画
if (someCondition) {
// 触发特定条件下的动画
this.triggerConditionalAnimation();
}
Parallel Animation
Sometimes, we want multiple animations to occur simultaneously rather than waiting for each to finish in sequence. VChart supports parallel animations, allowing developers to define multiple animation tasks to start executing at the same time.
By setting the timeOffset property, you can control the delay time between animation tasks. Additionally, you can use setInterval or setTimeout to achieve more complex timing logic.
7. Example: Creating a Bar Chart with Animation Orchestration
Below is an example of creating a bar chart with animation orchestration, illustrating how to use VChart's animation orchestration system to achieve the basic process.
Example: Creating a Bar Chart with Animation Orchestration
In VChart, animation orchestration refers to the combination and sequencing of multiple animation effects to achieve complex and coordinated visual effects. Through proper animation orchestration, the interactivity and user experience of the chart can be significantly enhanced. Below we will demonstrate in detail how to create a bar chart with animation orchestration, including the entrance animation for new data points, the update animation for existing data points, and the exit animation for old data points.
1. Define Animation Configuration
First, we need to define the basic configuration of the bar chart and specify specific animation effects for each animation state (enter, update, exit). To achieve complex animation orchestration, we can use chained animation tasks to define the specific animation sequence for each state.
**animationEnter**: New data points first fade in (fadeIn), then grow outward from the center (growCenterIn), and finally pulse slightly (pulse).
**animationUpdate**: Existing data points transition with scaling when updated.
**animationExit**: Old data points disappear by fading out.
2. Register Animation
Next, we need to ensure that the required animations have been correctly registered in the system. This step is usually completed at project startup or explicitly called where needed.
These animation functions define the specific logic for fade-in, zoom, fade-out, center growth, and pulse animations respectively. For example, the Appear_FadeIn function might look like this:
With the above configuration, we can initialize a VChart instance and pass the configuration to it. This will trigger the chart rendering process and apply the corresponding animation effects.
Once the chart is rendered, any changes in the data will automatically trigger animations. For example, when new data is added, the animationEnter configuration will take effect; when data is updated, the animationUpdate configuration is effective; and when data is removed, the animationExit configuration comes into play.
In this example, the updateSeriesData method will trigger a series of animations:
New Data Points (D):
Fade In (fadeIn): Gradually change from opacity 0 to 1.
Grow Center In (growCenterIn): Grow outward from the center, with width and height changing from 0 to the final value.
Pulse (pulse): Slightly enlarge and then return to the original state to attract the user's attention.
Existing Data Points (A, B, C):
Scale In (scaleIn): Adjust the height of the columns according to the new data values for a smooth transition.
5. Detailed Implementation of Animation Orchestration
Chained Animation Tasks
To achieve complex animation orchestration, we can use the IAnimationTask interface to define a sequence of animation tasks for each state. Each task includes time offset, action queue, and a list of successor tasks, forming a chained animation execution mechanism.
Suppose we want to define a complex chained animation task for new data points in a bar chart, starting with a fade-in, followed by a center growth, and finally a slight pulse effect.
Using Chained Animation Tasks in Chart Configuration
Integrate the defined chained animation tasks into the chart configuration to ensure that new data points execute animations in the expected order and effect.
VChart internally parses the animation tasks in animationEnter, animationUpdate, and animationExit, and executes the corresponding animations according to the defined order and time offset. Below is a simplified example showing how to parse and execute chained animation tasks.
In this example, the handleAnimationTasks method recursively parses and executes each animation task, ensuring that the corresponding animations are triggered in the defined order and time offset.
7. Specific Implementation of Animations
Definition of Animation Functions
Each specific animation function (such as Appear_FadeIn, ScaleInOutAnimation, Appear_FadeOut, growCenterIn, and pulseAnimation) defines the specific behavior of the animation. Here are some examples of specific animation functions:
Conditional Animation Configuration allows dynamically selecting different animation effects based on specific attributes of data points. For example, when a data value exceeds a certain threshold, a special animation is used; otherwise, the default animation is used. VChart allows you to embed logical judgments in the configuration to achieve such requirements.
In this example, the animationEnter configuration accepts a function as a parameter, which can return different animation configuration objects based on the specific attributes of the data points. Specifically:
Data point B has a value of 60, which is greater than the threshold of 50, so the specialGrowth animation is used.
Data points A and C have values of 10 and 30 respectively, which are less than the threshold of 50, so the fadeIn animation is used.
Custom Animation Types
In addition to using built-in animation types, VChart also supports developers in customizing animation logic. You can create new animation effects by inheriting or extending existing animation classes and register them into the system.
In this example, we define a custom animation named specialGrowth and register it into the system. Then, in the animationEnter configuration, we dynamically choose to use either the specialGrowth or fadeIn animation based on the value of the data point.
10. Advanced Usage of Animation Tasks
Nested Animation Tasks
In addition to simple chained animation tasks, VChart also supports nested animation tasks, making animation orchestration more flexible and complex. Through nested tasks, more precise animation control can be achieved.
Example: Nested Animation Tasks
Suppose we want to create a more complex animation sequence for newly added data points, starting with a fade-in, followed by a center growth, then a slight pulse effect, and finally a highlight.
VChart internally parses the animation tasks in animationEnter, animationUpdate, and animationExit, and executes the corresponding animations according to the defined order and time offset. Below is a simplified example showing how to parse and execute chained animation tasks.
In this example, the handleAnimationTasks method recursively parses and executes each animation task, ensuring that the corresponding animations are triggered in the defined order and time offset.
Timing of Animation Task Triggering
To ensure animations are triggered at the appropriate time, VChart provides a series of hook functions, such as VGRAMMAR_HOOK_EVENT.AFTER_DO_RENDER and VGRAMMAR_HOOK_EVENT.ANIMATION_END. These hooks can help us execute specific logic when the chart is first rendered or when the animation ends.
To improve performance, it is recommended to minimize frequent data update operations. If you need to update a large amount of data, consider merging these updates into a single batch operation to reduce unnecessary rendering times.
For scenarios with large charts or a large number of data points, lazy loading can be used to delay loading animations until user interaction or specific conditions are met. This helps improve initial loading speed and overall performance.
For those animation effects with high computational cost, consider caching their results to avoid repeated calculations. For example, for complex path animations, you can pre-calculate the keyframes of the path and reuse these keyframes in subsequent rendering.
To avoid performance issues caused by frequent event triggering, you can apply throttling or debouncing techniques to event listeners. For example, when handling mouse hover events, you can limit the frequency of animation triggers.
In some cases, you may want to dynamically control the behavior of animations, such as changing the speed or style of the animation. VChart provides flexible methods to achieve this.
Below is a complete example code demonstrating how to create a bar chart with complex animation choreography, implementing conditional animation configuration and custom animation types.
In this example, the animationEnter configuration accepts a function as a parameter, which can return different values based on the specific attributes of the data points.
Continuing to Interpret the Implementation of Data Update Animation
In the previous section, we have detailed the basic concepts and implementation methods of data update animation in VChart. Next, we will delve into some more specific details, including how to handle complex animation sequences, advanced usage of animation configuration, and best practices for optimizing performance.
1. Handling Complex Animation Sequences
Chained Animation Tasks
For complex animation sequences, VChart introduces the IAnimationTask interface to describe the data structure of animation tasks. Each task includes a time offset, an action queue, and a list of successor tasks, forming a chained animation execution mechanism.
This design allows multiple animation tasks to be executed sequentially or concurrently, achieving more complex and subtle animation effects. For example, in a bar chart, we can define a series of consecutive animation tasks, first letting the newly added data points fade in, then gradually grow to the final height, and finally add some decorative animations (such as highlighting).
Example: Creating Chained Animations
Suppose we want to create a chained entry animation for new data points in a bar chart, starting with a fade-in, followed by growth, and finally a slight pulse effect to attract the user's attention.
In this example, we use the enterAnimationTasks array to define a series of animation tasks, each with its own time offset, action queue, and list of successor tasks. In this way, very rich visual effects can be achieved.
2. Advanced Usage of Animation Configuration
Conditional Animation Configuration
Sometimes, you may want to dynamically choose different animation effects based on certain conditions. For example, when a data value exceeds a certain threshold, use a special animation; otherwise, use the default animation. VChart allows you to embed logical judgments in the configuration to achieve such requirements.
In this example, the animationEnter configuration accepts a function as a parameter, which can return different animation configuration objects based on the specific attributes of the data points. This allows the animation behavior to be dynamically adjusted according to the actual data, enhancing the expressiveness of the chart.
Custom Animation Types
In addition to using built-in animation types, VChart also supports developers in customizing animation logic. You can create new animation effects by inheriting or extending existing animation classes and registering them into the system.
This code demonstrates how to define and register a custom animation named customGrow, which adjusts the width and height of graphic elements based on the parameters passed. Then, this custom animation can be directly used in the chart configuration.
3. Performance Optimization and Best Practices
Batch Update Data
To improve performance, it is recommended to minimize frequent data update operations. If you need to update a large amount of data, consider merging these updates into a single batch operation to reduce unnecessary rendering times.
For scenarios with large charts or a large number of data points, lazy loading can be used to delay the animation until user interaction or specific conditions are met. This helps improve initial loading speed and overall performance.
For those animation effects with high computational cost, consider caching their results to avoid repeated calculations. For example, for complex path animations, you can pre-calculate the keyframes of the path and reuse these keyframes in subsequent renderings.
To avoid performance issues caused by frequent event triggering, you can apply throttling or debouncing techniques to event listeners. For example, when handling mouse hover events, you can limit the frequency of animation triggers.
Suppose we are developing a dynamic bar chart that updates in real-time, with a new batch of data added to the chart every second. We need to ensure that each time the data is updated, the newly added data points are presented to the user in a smooth and engaging manner, while the existing data points remain stable.
Step 1: Define Basic Configuration
First, define the basic configuration of the bar chart, including initial data and other visual attributes. At the same time, specify animationEnter, animationUpdate, and animationExit configurations to ensure animations are triggered when data changes.
Considering that a new batch of data is added every second, it may impact performance. Therefore, we can take the following optimization measures:
Batch update data: Update all new data to the chart at once, instead of adding them one by one.
Lazy load animations: Enable lazy load animations for newly added data points, so that animations only start playing when they enter the viewport.
Event throttling: Apply throttling techniques to interaction events such as mouse hover to prevent unnecessary animations from being triggered frequently.
To make the charts more vivid and interesting, you can add additional decorative animations to the newly added data points, such as highlighting or tooltip labels. This not only enhances visual appeal but also helps users better understand the changes in the data.
In some cases, you may want to dynamically adjust animation parameters such as duration, easing functions, etc., based on user input or other external factors. VChart provides flexible methods to achieve this.