---
title: "Animation"
enterprise: true
framework: react
version: "14.1.0"
---

# Animation

## Initial Load

Switch between the different series types below to see their initial load animations. Toggling items in the legend will also animate the series in and out.

#### Initial Load

```tsx
import React, { useState, Fragment } from "react";
import { createRoot } from "react-dom/client";
import { AgCharts } from "ag-charts-react";
import {
  AgCartesianChartOptions,
  AgCartesianSeriesTooltipRendererParams,
  AgChartOptions,
  AgPolarChartOptions,
  AgTooltipRendererResult,
  AnimationModule,
  AreaSeriesModule,
  BarSeriesModule,
  CategoryAxisModule,
  ContextMenuModule,
  CrosshairModule,
  DonutSeriesModule,
  LegendModule,
  LineSeriesModule,
  ModuleRegistry,
  NumberAxisModule,
  PieSeriesModule,
} from "ag-charts-enterprise";
import { DataType, getData } from "./data";
import clone from "clone";

const numFormatter = new Intl.NumberFormat("en-US");
const tooltip = {
  renderer: ({
    datum,
    yKey,
    yName,
  }: AgCartesianSeriesTooltipRendererParams<DataType>): AgTooltipRendererResult => {
    return {
      data: [
        { label: yName!, value: numFormatter.format(Number(datum[yKey])) },
      ],
    };
  },
};
const barOptions: AgCartesianChartOptions<DataType> = {
  series: [
    {
      type: "bar",
      xKey: "station",
      yKey: "early",
      stacked: true,
      yName: "Early",
      tooltip,
    },
    {
      type: "bar",
      xKey: "station",
      yKey: "morningPeak",
      yName: "Morning peak",
      stacked: true,
      tooltip,
    },
    {
      type: "bar",
      xKey: "station",
      yKey: "interPeak",
      yName: "Between peak",
      stacked: true,
      tooltip,
    },
    {
      type: "bar",
      xKey: "station",
      yKey: "afternoonPeak",
      yName: "Afternoon peak",
      stacked: true,
      tooltip,
    },
    {
      type: "bar",
      xKey: "station",
      yKey: "evening",
      yName: "Evening",
      stacked: true,
      tooltip,
    },
  ],
  axes: {
    x: {
      type: "category",
      label: {
        wrapping: "on-space",
        autoRotate: false,
      },
    },
    y: {
      type: "number",
      label: {
        formatter: (params) => {
          return params.value / 1000 + "k";
        },
      },
    },
  },
};
const lineOptions: AgCartesianChartOptions<DataType> = {
  series: [
    {
      type: "line",
      xKey: "station",
      yKey: "early",
      yName: "Early",
      tooltip,
    },
    {
      type: "line",
      xKey: "station",
      yKey: "morningPeak",
      yName: "Morning peak",
      tooltip,
    },
    {
      type: "line",
      xKey: "station",
      yKey: "interPeak",
      yName: "Between peak",
      tooltip,
    },
    {
      type: "line",
      xKey: "station",
      yKey: "afternoonPeak",
      yName: "Afternoon peak",
      tooltip,
    },
    {
      type: "line",
      xKey: "station",
      yKey: "evening",
      yName: "Evening",
      tooltip,
    },
  ],
  axes: {
    x: {
      type: "category",
      label: {
        wrapping: "on-space",
        autoRotate: false,
      },
    },
    y: {
      type: "number",
      label: {
        formatter: (params) => {
          return params.value / 1000 + "k";
        },
      },
    },
  },
};
const areaOptions: AgCartesianChartOptions<DataType> = {
  series: [
    {
      type: "area",
      xKey: "station",
      yKey: "early",
      stacked: true,
      yName: "Early",
      tooltip,
    },
    {
      type: "area",
      xKey: "station",
      yKey: "morningPeak",
      yName: "Morning peak",
      stacked: true,
      tooltip,
    },
    {
      type: "area",
      xKey: "station",
      yKey: "interPeak",
      yName: "Between peak",
      stacked: true,
      tooltip,
    },
    {
      type: "area",
      xKey: "station",
      yKey: "afternoonPeak",
      yName: "Afternoon peak",
      stacked: true,
      tooltip,
    },
    {
      type: "area",
      xKey: "station",
      yKey: "evening",
      yName: "Evening",
      stacked: true,
      tooltip,
    },
  ],
  axes: {
    x: {
      type: "category",
      label: {
        wrapping: "on-space",
        autoRotate: false,
      },
    },
    y: {
      type: "number",
      label: {
        formatter: (params) => {
          return params.value / 1000 + "k";
        },
      },
    },
  },
};
const donutOptions: AgPolarChartOptions<DataType> = {
  series: [
    {
      type: "pie",
      title: {
        text: "Morning Peak",
      },
      calloutLabelKey: "station",
      legendItemKey: "station",
      angleKey: "morningPeak",
      outerRadiusRatio: 0.6,
    },
    {
      type: "donut",
      title: {
        text: "Afternoon Peak",
      },
      calloutLabelKey: "station",
      legendItemKey: "station",
      angleKey: "afternoonPeak",
      showInLegend: false,
    },
  ],
};
ModuleRegistry.registerModules([
  AnimationModule,
  AreaSeriesModule,
  BarSeriesModule,
  CategoryAxisModule,
  CrosshairModule,
  DonutSeriesModule,
  LegendModule,
  LineSeriesModule,
  NumberAxisModule,
  PieSeriesModule,
  ContextMenuModule,
]);

const ChartExample = () => {
  const [options, setOptions] = useState<
    AgCartesianChartOptions<DataType> | AgPolarChartOptions<DataType>
  >({
    data: getData(),
    animation: {
      enabled: true,
    },
    ...barOptions,
  });

  const changeSeriesBar = () => {
    const nextOptions = clone(options);

    nextOptions.series = barOptions.series;
    nextOptions.axes = barOptions.axes;

    setOptions(nextOptions);
  };

  const changeSeriesLine = () => {
    const nextOptions = clone(options);

    nextOptions.series = lineOptions.series;
    nextOptions.axes = lineOptions.axes;

    setOptions(nextOptions);
  };

  const changeSeriesArea = () => {
    const nextOptions = clone(options);

    nextOptions.series = areaOptions.series;
    nextOptions.axes = areaOptions.axes;

    setOptions(nextOptions);
  };

  const changeSeriesDonut = () => {
    const nextOptions = clone(options);

    nextOptions.series = donutOptions.series;
    nextOptions.axes = donutOptions.axes;

    setOptions(nextOptions);
  };

  return (
    <Fragment>
      <div className="example-controls">
        <div className="controls-row">
          <button onClick={changeSeriesBar}>Bar</button>
          <button onClick={changeSeriesLine}>Line</button>
          <button onClick={changeSeriesArea}>Area</button>
          <button onClick={changeSeriesDonut}>Pie &amp; Donut</button>
        </div>
      </div>
      <AgCharts options={options} />
    </Fragment>
  );
};

const root = createRoot(document.getElementById("root")!);
root.render(<ChartExample />);
```

[Live example: Initial Load](https://www.ag-grid.com/charts/reactFunctionalTs/animation/examples/initial-load)

## Data Updates

A data update animation is split into three sequential phases — remove, update then add, which can be observed for different series types in this example:

#### Line Series Data Updates

```tsx
import React, { useState, Fragment } from "react";
import { createRoot } from "react-dom/client";
import { AgCharts } from "ag-charts-react";
import {
  AgCartesianChartOptions,
  AgChartOptions,
  AgPolarChartOptions,
  AnimationModule,
  AreaSeriesModule,
  BarSeriesModule,
  CategoryAxisModule,
  ContextMenuModule,
  CrosshairModule,
  DonutSeriesModule,
  LegendModule,
  LineSeriesModule,
  ModuleRegistry,
  NumberAxisModule,
  PieSeriesModule,
} from "ag-charts-enterprise";
import { getData, random } from "./data";
import clone from "clone";

let start = [120, 150, 130, 140, 80];
let variance = 20;
let offset = 0;
let length = 8;
let seed = 1234;
const barOptions: AgCartesianChartOptions = {
  series: [
    {
      type: "bar",
      xKey: "year",
      yKey: "one",
      yName: "One",
      stacked: true,
    },
    {
      type: "bar",
      xKey: "year",
      yKey: "two",
      yName: "Two",
      stacked: true,
    },
    {
      type: "bar",
      xKey: "year",
      yKey: "three",
      yName: "Three",
      stacked: true,
    },
    {
      type: "bar",
      xKey: "year",
      yKey: "four",
      yName: "Four",
      stacked: true,
    },
    {
      type: "bar",
      xKey: "year",
      yKey: "five",
      yName: "Five",
      stacked: true,
    },
  ],
  axes: {
    x: {
      type: "category",
      label: {
        autoRotate: false,
      },
    },
  },
};
const lineOptions: AgCartesianChartOptions = {
  series: [
    {
      type: "line",
      xKey: "year",
      yKey: "one",
      yName: "One",
    },
    {
      type: "line",
      xKey: "year",
      yKey: "two",
      yName: "Two",
    },
    {
      type: "line",
      xKey: "year",
      yKey: "three",
      yName: "Three",
    },
    {
      type: "line",
      xKey: "year",
      yKey: "four",
      yName: "Four",
    },
    {
      type: "line",
      xKey: "year",
      yKey: "five",
      yName: "Five",
    },
  ],
  axes: {
    x: {
      type: "number",
      nice: false,
      label: {
        autoRotate: false,
      },
    },
  },
};
const areaOptions: AgCartesianChartOptions = {
  series: [
    {
      type: "area",
      xKey: "year",
      yKey: "one",
      yName: "One",
      stacked: true,
    },
    {
      type: "area",
      xKey: "year",
      yKey: "two",
      yName: "Two",
      stacked: true,
    },
    {
      type: "area",
      xKey: "year",
      yKey: "three",
      yName: "Three",
      stacked: true,
    },
    {
      type: "area",
      xKey: "year",
      yKey: "four",
      yName: "Four",
      stacked: true,
    },
    {
      type: "area",
      xKey: "year",
      yKey: "five",
      yName: "Five",
      stacked: true,
    },
  ],
  axes: {
    x: {
      type: "number",
      nice: false,
      label: {
        autoRotate: false,
      },
    },
  },
};
const donutOptions: AgPolarChartOptions = {
  series: [
    {
      type: "pie",
      title: {
        text: "One",
      },
      calloutLabelKey: "year",
      legendItemKey: "year",
      angleKey: "one",
      outerRadiusRatio: 0.6,
    },
    {
      type: "donut",
      title: {
        text: "Two",
      },
      calloutLabelKey: "year",
      legendItemKey: "year",
      angleKey: "two",
      showInLegend: false,
    },
  ],
};
function getGeneratedData() {
  return getData(start, variance, offset, length, seed);
}
ModuleRegistry.registerModules([
  AnimationModule,
  AreaSeriesModule,
  BarSeriesModule,
  CategoryAxisModule,
  CrosshairModule,
  DonutSeriesModule,
  LegendModule,
  LineSeriesModule,
  NumberAxisModule,
  PieSeriesModule,
  ContextMenuModule,
]);

const ChartExample = () => {
  const [options, setOptions] = useState<
    AgCartesianChartOptions | AgPolarChartOptions
  >({
    animation: {
      enabled: true,
    },
    data: getGeneratedData(),
    ...barOptions,
  });

  const changeSeriesBar = () => {
    const nextOptions = clone(options);

    variance = 20;
    offset = 0;
    length = 8;
    seed = 1234;
    nextOptions.series = barOptions.series;
    nextOptions.axes = barOptions.axes;
    nextOptions.data = getGeneratedData();

    setOptions(nextOptions);
  };

  const changeSeriesLine = () => {
    const nextOptions = clone(options);

    variance = 4;
    offset = 0;
    length = 30;
    seed = 1234;
    nextOptions.series = lineOptions.series;
    nextOptions.axes = lineOptions.axes;
    nextOptions.data = getGeneratedData();

    setOptions(nextOptions);
  };

  const changeSeriesArea = () => {
    const nextOptions = clone(options);

    variance = 20;
    offset = 0;
    length = 30;
    seed = 1234;
    nextOptions.series = areaOptions.series;
    nextOptions.axes = areaOptions.axes;
    nextOptions.data = getGeneratedData();

    setOptions(nextOptions);
  };

  const changeSeriesDonut = () => {
    const nextOptions = clone(options);

    variance = 30;
    offset = 0;
    length = 6;
    seed = 1234;
    nextOptions.series = donutOptions.series;
    nextOptions.axes = donutOptions.axes;
    nextOptions.data = getGeneratedData();

    setOptions(nextOptions);
  };

  const add = () => {
    const nextOptions = clone(options);

    offset++;
    length++;
    nextOptions.data = getGeneratedData();

    setOptions(nextOptions);
  };

  const remove = () => {
    const nextOptions = clone(options);

    if (nextOptions.series?.[0].type === "pie") offset--;
    length = Math.max(0, length - 1);
    nextOptions.data = getGeneratedData();

    setOptions(nextOptions);
  };

  const update = () => {
    const nextOptions = clone(options);

    seed = Math.floor(random() * 1000);
    nextOptions.data = getGeneratedData();

    setOptions(nextOptions);
  };

  const addRemoveUpdate = () => {
    const nextOptions = clone(options);

    if (nextOptions.series?.[0].type === "pie") offset--;
    if (nextOptions.series?.[0].type !== "pie") offset++;
    seed = Math.floor(random() * 1000);
    nextOptions.data = getGeneratedData();

    setOptions(nextOptions);
  };

  return (
    <Fragment>
      <div className="example-controls">
        <div className="controls-row">
          <button onClick={changeSeriesBar}>Bar</button>
          <button onClick={changeSeriesLine}>Line</button>
          <button onClick={changeSeriesArea}>Area</button>
          <button className="gap-right" onClick={changeSeriesDonut}>
            Pie &amp; Donut
          </button>
          <button className="animation-data-updates__action" onClick={add}>
            Add
          </button>
          <button className="animation-data-updates__action" onClick={remove}>
            Remove
          </button>
          <button
            className="animation-data-updates__action gap-right"
            onClick={update}
          >
            Update
          </button>
          <button
            className="animation-data-updates__action"
            onClick={addRemoveUpdate}
          >
            Add &amp; Remove &amp; Update
          </button>
        </div>
      </div>
      <AgCharts options={options} />
    </Fragment>
  );
};

const root = createRoot(document.getElementById("root")!);
root.render(<ChartExample />);
```

[Live example: Line Series Data Updates](https://www.ag-grid.com/charts/reactFunctionalTs/animation/examples/data-updates)

## Duration

You can use the `duration` option to specify the length of all animations in milliseconds.

For an initial load, this is simply the duration of the whole animation.

For a data update, the duration is the total time of all three animation phases together — remove, update then add.

```js
{
    animation: {
        duration: 500,
    },
}
```

In this example, click a duration then change the series type to see the initial load animation.

#### Duration

```tsx
import React, { useState, Fragment } from "react";
import { createRoot } from "react-dom/client";
import { AgCharts } from "ag-charts-react";
import {
  AgCartesianChartOptions,
  AgCartesianSeriesTooltipRendererParams,
  AgChartOptions,
  AgPolarChartOptions,
  AgTooltipRendererResult,
  AnimationModule,
  AreaSeriesModule,
  BarSeriesModule,
  CategoryAxisModule,
  ContextMenuModule,
  CrosshairModule,
  DonutSeriesModule,
  LegendModule,
  LineSeriesModule,
  ModuleRegistry,
  NumberAxisModule,
  PieSeriesModule,
} from "ag-charts-enterprise";
import { DataType, getData } from "./data";
import clone from "clone";

const numFormatter = new Intl.NumberFormat("en-US");
const tooltip = {
  renderer: ({
    datum,
    yKey,
    yName,
  }: AgCartesianSeriesTooltipRendererParams<DataType>): AgTooltipRendererResult => {
    return {
      data: [
        { label: yName!, value: numFormatter.format(Number(datum[yKey])) },
      ],
    };
  },
};
const barOptions: AgCartesianChartOptions<DataType> = {
  series: [
    {
      type: "bar",
      xKey: "station",
      yKey: "early",
      stacked: true,
      yName: "Early",
      tooltip,
    },
    {
      type: "bar",
      xKey: "station",
      yKey: "morningPeak",
      yName: "Morning peak",
      stacked: true,
      tooltip,
    },
    {
      type: "bar",
      xKey: "station",
      yKey: "interPeak",
      yName: "Between peak",
      stacked: true,
      tooltip,
    },
    {
      type: "bar",
      xKey: "station",
      yKey: "afternoonPeak",
      yName: "Afternoon peak",
      stacked: true,
      tooltip,
    },
    {
      type: "bar",
      xKey: "station",
      yKey: "evening",
      yName: "Evening",
      stacked: true,
      tooltip,
    },
  ],
  axes: {
    y: {
      type: "number",
      label: {
        formatter: (params) => {
          return params.value / 1000 + "k";
        },
      },
    },
  },
};
const lineOptions: AgCartesianChartOptions<DataType> = {
  series: [
    {
      type: "line",
      xKey: "station",
      yKey: "early",
      yName: "Early",
      tooltip,
    },
    {
      type: "line",
      xKey: "station",
      yKey: "morningPeak",
      yName: "Morning peak",
      tooltip,
    },
    {
      type: "line",
      xKey: "station",
      yKey: "interPeak",
      yName: "Between peak",
      tooltip,
    },
    {
      type: "line",
      xKey: "station",
      yKey: "afternoonPeak",
      yName: "Afternoon peak",
      tooltip,
    },
    {
      type: "line",
      xKey: "station",
      yKey: "evening",
      yName: "Evening",
      tooltip,
    },
  ],
  axes: {
    y: {
      type: "number",
      label: {
        formatter: (params) => {
          return params.value / 1000 + "k";
        },
      },
    },
  },
};
const areaOptions: AgCartesianChartOptions<DataType> = {
  series: [
    {
      type: "area",
      xKey: "station",
      yKey: "early",
      stacked: true,
      yName: "Early",
      tooltip,
    },
    {
      type: "area",
      xKey: "station",
      yKey: "morningPeak",
      yName: "Morning peak",
      stacked: true,
      tooltip,
    },
    {
      type: "area",
      xKey: "station",
      yKey: "interPeak",
      yName: "Between peak",
      stacked: true,
      tooltip,
    },
    {
      type: "area",
      xKey: "station",
      yKey: "afternoonPeak",
      yName: "Afternoon peak",
      stacked: true,
      tooltip,
    },
    {
      type: "area",
      xKey: "station",
      yKey: "evening",
      yName: "Evening",
      stacked: true,
      tooltip,
    },
  ],
  axes: {
    y: {
      type: "number",
      label: {
        formatter: (params) => {
          return params.value / 1000 + "k";
        },
      },
    },
  },
};
const donutOptions: AgPolarChartOptions<DataType> = {
  series: [
    {
      type: "pie",
      title: {
        text: "Morning Peak",
      },
      calloutLabelKey: "station",
      legendItemKey: "station",
      angleKey: "morningPeak",
      outerRadiusRatio: 0.6,
    },
    {
      type: "donut",
      title: {
        text: "Afternoon Peak",
      },
      calloutLabelKey: "station",
      legendItemKey: "station",
      angleKey: "afternoonPeak",
      showInLegend: false,
    },
  ],
};
ModuleRegistry.registerModules([
  AnimationModule,
  AreaSeriesModule,
  BarSeriesModule,
  CategoryAxisModule,
  CrosshairModule,
  DonutSeriesModule,
  LegendModule,
  LineSeriesModule,
  NumberAxisModule,
  PieSeriesModule,
  ContextMenuModule,
]);

const ChartExample = () => {
  const [options, setOptions] = useState<
    AgCartesianChartOptions<DataType> | AgPolarChartOptions<DataType>
  >({
    data: getData(),
    animation: {
      enabled: true,
    },
    ...barOptions,
  });

  const changeSeriesBar = () => {
    const nextOptions = clone(options);

    nextOptions.series = barOptions.series;
    nextOptions.axes = barOptions.axes;

    setOptions(nextOptions);
  };

  const changeSeriesLine = () => {
    const nextOptions = clone(options);

    nextOptions.series = lineOptions.series;
    nextOptions.axes = lineOptions.axes;

    setOptions(nextOptions);
  };

  const changeSeriesArea = () => {
    const nextOptions = clone(options);

    nextOptions.series = areaOptions.series;
    nextOptions.axes = areaOptions.axes;

    setOptions(nextOptions);
  };

  const changeSeriesDonut = () => {
    const nextOptions = clone(options);

    nextOptions.series = donutOptions.series;
    nextOptions.axes = donutOptions.axes;

    setOptions(nextOptions);
  };

  const changeDuration = (duration: number) => {
    const nextOptions = clone(options);

    nextOptions.animation = { duration };

    setOptions(nextOptions);
  };

  return (
    <Fragment>
      <div className="example-controls">
        <div className="controls-row">
          <button onClick={changeSeriesBar}>Bar</button>
          <button onClick={changeSeriesLine}>Line</button>
          <button onClick={changeSeriesArea}>Area</button>
          <button className="gap-right" onClick={changeSeriesDonut}>
            Pie &amp; Donut
          </button>
          <button onClick={() => changeDuration(500)}>Duration: 500ms</button>
          <button onClick={() => changeDuration(2000)}>Duration: 2000ms</button>
        </div>
      </div>
      <AgCharts options={options} />
    </Fragment>
  );
};

const root = createRoot(document.getElementById("root")!);
root.render(<ChartExample />);
```

[Live example: Duration](https://www.ag-grid.com/charts/reactFunctionalTs/animation/examples/duration)

To highlight data changes with a flash effect, see [Flash On Update](https://www.ag-grid.com/charts/react/flash-on-update/).

## API Reference

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| enabled | boolean |  | Set to `true` to enable the animation module. Defaults to `false` when `flashOnUpdate.enabled` is `true`. |
| duration | DurationMs |  | The total duration of the animation on initial load and updates. |
