!!!###!!!title=Custom Animation——VisActor/VChart tutorial documents!!!###!!!!!!###!!!description=Previously, we introduced how to configure basic animations and animation arrangements in VChart. In addition, if you have more specific needs or better animation ideas, you can achieve them through the ability to customize animations. Custom animation methods can be used not only in VChart, but also in the entire VisActor series of visualization solutions.This chapter will introduce how to customize animations in VChart, including custom animation attribute interpolation functions and custom animation classes. Before you begin, please make sure you are familiar with and can use VChart's basic chart animation capabilities. In the last section ([Complex Animation Configuration and Choreography](../Animation/Configuration_and_Choreography_of_Complex_Animations)), we introduced the concept of TimeSlice, each TimeSlice can define multiple animation effects (`effect`), and we will focus on `effect.custom` to introduce custom animation methods.!!!###!!!

Custom Animation

Previously, we introduced how to configure basic animations and animation arrangements in VChart. In addition, if you have more specific needs or better animation ideas, you can achieve them through the ability to customize animations. Custom animation methods can be used not only in VChart, but also in the entire VisActor series of visualization solutions.

This chapter will introduce how to customize animations in VChart, including custom animation attribute interpolation functions and custom animation classes. Before you begin, please make sure you are familiar with and can use VChart's basic chart animation capabilities. In the last section (Complex Animation Configuration and Choreography), we introduced the concept of TimeSlice, each TimeSlice can define multiple animation effects (effect), and we will focus on effect.custom to introduce custom animation methods.

Custom Animation Attribute Interpolation Function

Custom animation attribute interpolation functions are mainly used to provide visual channels before and after the animation is executed to achieve some animation effects. effect.custom can be configured as a custom interpolation function:

export type IAnimationChannelInterpolator = (
  ratio: number,
  from: any,
  to: any,
  nextAttributes: any,
  datum: any,
  element: IElement,
  parameters: IAnimationParameters
) => boolean | void;

You need to create an animation function that implements the IAnimationChannelInterpolator type, with the following function parameters:

  • ratio: The progress ratio of the animation, a decimal value between 0 and 1.
  • from: The visual channel attribute of the graphic element at the start of the animation.
  • to: The visual channel attribute of the graphic element at the start of the animation.
  • nextAttributes: The attribute values for the next frame, which can be calculated and modified in the function.
  • datum: The original data associated with the current graphic element.
  • element: The current graphic element.
  • parameters: Custom animation parameters that can be passed when creating the animation.

Here is an example of a custom animation:

Custom Animation Class

In VChart, custom animations are accomplished by implementing the ICustomAnimate interface. The following is the definition of the ICustomAnimate interface:

export interface ICustomAnimate {
  duration: number;
  easing EasingType;
  step?: IStep;
  mode?: AnimateMode;

  bind: (target IAnimateTarget, subAni: ISubAnimate => void;
  onBind: () => void;
  onRun: () => void;
  onStart: () => void;
  onEnd: () => void;
  onUpdate: (end: boolean, ratio: number, out: Record<string, any>) => void;
  update (end: boolean, ratio: number, out: Record<string, any>) => void;
  getEndProps: () => Record<string, any> | void;
  getFromProps: () => Record<string, any> | void;
  MergedEndProps: () => Record<string, any> | void;
}

The interface defines some basic animation properties and lifecycle functions that can be used to create, update, and destroy custom animations. Detailed documentation can be found in VRender Custom Animation.

The following example uses the built-in StreamLight custom animation class from VRender to implement the bar chart streamer effect:

Writing Your Own Custom Animation Class

In VChart, you can inherit the ACustomAnimate class to write your own custom animation class. For example, the following code writes an animation that translates a column from a certain point.

import { ACustomAnimate, EasingType } from '@visactor/vrender-core';
export class BarFromPoint extends ACustomAnimate<{ y?: number; y1?: number; x?: number; x1?: number }> {
  constructor(
    from: { y?: number; y1?: number; x?: number; x1?: number },
    to: { y?: number; y1?: number; x?: number; x1?: number },
    duration: number,
    easing: EasingType,
    params: any
  ) {
    const f = {
      y: from.y1,
      y1: from.y1,
      x: from.x1,
      x1: from.x1
    };
    super(f, { y: from.y, y1: from.y1, x: from.x, x1: from.x1 }, duration, easing, params);
  }

  getEndProps(): Record<string, any> {
    return this.to;
  }

  getFromProps(): void | Record<string, any> {
    return this.from;
  }

  onBind(): void {
    this.target && this.target.setAttributes(this.from);
  }

  onUpdate(end: boolean, ratio: number, out: Record<string, any>): void {
    const { x: fromX, y: fromY } = this.params.from;
    const { x: toX, y: toY, y1: toY1 } = this.to;
    const height = toY1! - toY!;
    out.x = fromX + (toX! - fromX) * ratio;
    out.y = fromY + (toY! - fromY) * ratio;
    out.y1 = out.y + height;
  }
}

Then pass this class to the custom field of the custom function in the spec

{
  type: 'bar',
  data: [
    {
      id: 'barData',
      values: [
        { month: 'Monday', sales: 22 },
        { month: 'Tuesday', sales: 13 },
        { month: 'Wednesday', sales: 25 },
        { month: 'Thursday', sales: 29 },
        { month: 'Friday', sales: 38 }
      ]
    }
  ],
  animationAppear: {
    bar: {
      channel: ['x', 'y', 'x1', 'y1', 'width', 'height', 'cornerRadius'],
      custom: BarFromPoint,
      duration: 1000,
      easing: 'linear',
      customParameters: {
        from: {x: 0, y: 0},
      }
    },
  },
  xField: 'month',
  yField: 'sales'
}