# Animate (motion) (/start/canvas-motion)



Pixi’VN allows developers to animate canvas components using a function called [`canvas.animate`](/jsdoc/pixi-vn/index/interfaces/CanvasManagerInterface#animate). This function is a re-implementation of the [`animate` function from the `motion` library](https://motion.dev/docs/animate), adapted to use PixiJS tickers for triggering animation events.

<Accordions>
  <Accordion title="What is motion?" id="what-is-motion">
    `motion` is a popular JavaScript library that provides a simple and powerful way to create animations. You can read more about it [here](https://motion.dev/).
  </Accordion>
</Accordions>

## Use [#use]

[`canvas.animate`](/jsdoc/pixi-vn/index/interfaces/CanvasManagerInterface#animate) is one of the most commonly used functions in Pixi’VN and is designed to be straightforward — though the underlying concept may not be immediately obvious at first. The idea is simple: you define a **target state** for a canvas component (e.g. a position, scale, or opacity) and a **duration**, and Pixi’VN will smoothly transition the component to that state frame by frame. Once the target is reached, the animation ends automatically.

For example, to move a component to position `{ x: 100, y: 50 }` over one second, you pass `{ x: 100, y: 50 }` as the [`keyframes`](/jsdoc/pixi-vn/index/interfaces/CanvasManagerInterface#keyframes) and `{ duration: 1 }` as the [`options`](/jsdoc/pixi-vn/index/interfaces/CanvasManagerInterface#options). The [`keyframes`](/jsdoc/pixi-vn/index/interfaces/CanvasManagerInterface#keyframes) parameter defines *what* to reach; [`options`](/jsdoc/pixi-vn/index/interfaces/CanvasManagerInterface#options) defines *how* to get there.

<CalloutContainer type="warning">
  <CalloutDescription>
    [`canvas.animate`](/jsdoc/pixi-vn/index/interfaces/CanvasManagerInterface#animate) internally creates a Ticker. For advanced use cases — such as pausing, resuming, or stopping an animation — you can use the <DynamicLink href="/start/canvas-tickers#functions">functions available to control Pixi’VN Tickers</DynamicLink>.
  </CalloutDescription>
</CalloutContainer>

## Examples [#examples]

<Accordions>
  <Accordion title="Move" id="move">
    <CodeBlockTabs defaultValue="content/labels/start.label.ts">
      <CodeBlockTabsList>
        <CodeBlockTabsTrigger value="content/labels/start.label.ts">
          content/labels/start.label.ts
        </CodeBlockTabsTrigger>

        <CodeBlockTabsTrigger value="assets/index.ts">
          assets/index.ts
        </CodeBlockTabsTrigger>
      </CodeBlockTabsList>

      <CodeBlockTab value="content/labels/start.label.ts">
        ```ts
        import { canvas, ImageSprite, newLabel, showImage } from "@drincs/pixi-vn";

        export const startLabel = newLabel("start", [
            async () => {
                const alien = await showImage("alien");
                canvas.animate(alien, { xAlign: 1, yAlign: 0 }, { ease: "easeOut" });
            },
            () =>
                canvas.animate<ImageSprite>(
                    "alien",
                    { xAlign: 1, yAlign: 1 },
                    { ease: "backOut" },
                ),
            () =>
                canvas.animate<ImageSprite>(
                    "alien",
                    { xAlign: 0, yAlign: 1 },
                    { ease: "circIn" },
                ),
            () =>
                canvas.animate<ImageSprite>(
                    "alien",
                    { xAlign: 0, yAlign: 0 },
                    { ease: "linear" },
                ),
        ]);
        ```
      </CodeBlockTab>

      <CodeBlockTab value="assets/index.ts">
        ```ts
        import { AssetsManifest } from "@drincs/pixi-vn";

        /**
         * Manifest for the assets used in the game.
         * You can read more about the manifest here: https://pixijs.com/8.x/guides/components/assets#loading-multiple-assets
         */
        export const manifest: AssetsManifest = {
            bundles: [
                {
                    name: "start",
                    assets: [
                        {
                            alias: "alien",
                            src: "https://pixijs.com/assets/eggHead.png",
                        },
                    ],
                },
            ],
        };
        ```
      </CodeBlockTab>
    </CodeBlockTabs>

    <PixiVnExample path="canvas/move" />
  </Accordion>

  <Accordion title="Rotate" id="rotate">
    <CodeBlockTabs defaultValue="content/labels/start.label.ts">
      <CodeBlockTabsList>
        <CodeBlockTabsTrigger value="content/labels/start.label.ts">
          content/labels/start.label.ts
        </CodeBlockTabsTrigger>

        <CodeBlockTabsTrigger value="assets/index.ts">
          assets/index.ts
        </CodeBlockTabsTrigger>
      </CodeBlockTabsList>

      <CodeBlockTab value="content/labels/start.label.ts">
        ```ts
        import { canvas, newLabel, showImage } from "@drincs/pixi-vn";

        export const startLabel = newLabel("start", [
            async () => {
                const alien = await showImage("alien", "alien", {
                    align: 0.5,
                    anchor: 0.5,
                });
                canvas.animate(
                    alien,
                    { angle: 360 },
                    { duration: 1, type: "spring", repeat: Infinity, repeatDelay: 0.2 },
                );
            },
        ]);
        ```
      </CodeBlockTab>

      <CodeBlockTab value="assets/index.ts">
        ```ts
        import { AssetsManifest } from "@drincs/pixi-vn";

        /**
         * Manifest for the assets used in the game.
         * You can read more about the manifest here: https://pixijs.com/8.x/guides/components/assets#loading-multiple-assets
         */
        export const manifest: AssetsManifest = {
            bundles: [
                {
                    name: "start",
                    assets: [
                        {
                            alias: "alien",
                            src: "https://pixijs.com/assets/eggHead.png",
                        },
                    ],
                },
            ],
        };
        ```
      </CodeBlockTab>
    </CodeBlockTabs>

    <PixiVnExample path="canvas/rotate" />
  </Accordion>

  <Accordion title="Fade" id="fade">
    <CodeBlockTabs defaultValue="content/labels/start.label.ts">
      <CodeBlockTabsList>
        <CodeBlockTabsTrigger value="content/labels/start.label.ts">
          content/labels/start.label.ts
        </CodeBlockTabsTrigger>

        <CodeBlockTabsTrigger value="assets/index.ts">
          assets/index.ts
        </CodeBlockTabsTrigger>
      </CodeBlockTabsList>

      <CodeBlockTab value="content/labels/start.label.ts">
        ```ts
        import { canvas, newLabel, showImage } from "@drincs/pixi-vn";

        export const startLabel = newLabel("start", [
            async () => {
                const alien = await showImage("alien", "alien", {
                    align: 0.5,
                    anchor: 0.5,
                    alpha: 0,
                });
                canvas.animate(alien, { alpha: 1 }, { ease: "linear", duration: 1 });
            },
        ]);
        ```
      </CodeBlockTab>

      <CodeBlockTab value="assets/index.ts">
        ```ts
        import { AssetsManifest } from "@drincs/pixi-vn";

        /**
         * Manifest for the assets used in the game.
         * You can read more about the manifest here: https://pixijs.com/8.x/guides/components/assets#loading-multiple-assets
         */
        export const manifest: AssetsManifest = {
            bundles: [
                {
                    name: "start",
                    assets: [
                        {
                            alias: "alien",
                            src: "https://pixijs.com/assets/eggHead.png",
                        },
                    ],
                },
            ],
        };
        ```
      </CodeBlockTab>
    </CodeBlockTabs>

    <PixiVnExample path="canvas/fade" />
  </Accordion>

  <Accordion title="Zoom" id="zoom">
    <CodeBlockTabs defaultValue="content/labels/start.label.ts">
      <CodeBlockTabsList>
        <CodeBlockTabsTrigger value="content/labels/start.label.ts">
          content/labels/start.label.ts
        </CodeBlockTabsTrigger>

        <CodeBlockTabsTrigger value="assets/index.ts">
          assets/index.ts
        </CodeBlockTabsTrigger>
      </CodeBlockTabsList>

      <CodeBlockTab value="content/labels/start.label.ts">
        ```ts
        import { canvas, newLabel, showImage } from "@drincs/pixi-vn";

        export const startLabel = newLabel("start", [
            async () => {
                const alien = await showImage("alien", "alien", {
                    align: 0.5,
                    anchor: 0.5,
                    scale: 0,
                });
                canvas.animate(
                    alien,
                    { scaleX: 1, scaleY: 1 },
                    { ease: "circInOut", duration: 1 },
                );
            },
        ]);
        ```
      </CodeBlockTab>

      <CodeBlockTab value="assets/index.ts">
        ```ts
        import { AssetsManifest } from "@drincs/pixi-vn";

        /**
         * Manifest for the assets used in the game.
         * You can read more about the manifest here: https://pixijs.com/8.x/guides/components/assets#loading-multiple-assets
         */
        export const manifest: AssetsManifest = {
            bundles: [
                {
                    name: "start",
                    assets: [
                        {
                            alias: "alien",
                            src: "https://pixijs.com/assets/eggHead.png",
                        },
                    ],
                },
            ],
        };
        ```
      </CodeBlockTab>
    </CodeBlockTabs>

    <PixiVnExample path="canvas/zoom" />
  </Accordion>

  <Accordion title="Mirror" id="mirror">
    <CodeBlockTabs defaultValue="content/labels/start.label.ts">
      <CodeBlockTabsList>
        <CodeBlockTabsTrigger value="content/labels/start.label.ts">
          content/labels/start.label.ts
        </CodeBlockTabsTrigger>

        <CodeBlockTabsTrigger value="assets/index.ts">
          assets/index.ts
        </CodeBlockTabsTrigger>
      </CodeBlockTabsList>

      <CodeBlockTab value="content/labels/start.label.ts">
        ```ts
        import { canvas, newLabel, showImage } from "@drincs/pixi-vn";

        export const startLabel = newLabel("start", [
            async () => {
                const alien = await showImage("alien", "alien", {
                    align: 0.5,
                    anchor: 0.5,
                });
                canvas.animate(alien, { scaleX: -1 });
            },
            () => canvas.animate("alien", { scaleX: 1 }),
        ]);
        ```
      </CodeBlockTab>

      <CodeBlockTab value="assets/index.ts">
        ```ts
        import { AssetsManifest } from "@drincs/pixi-vn";

        /**
         * Manifest for the assets used in the game.
         * You can read more about the manifest here: https://pixijs.com/8.x/guides/components/assets#loading-multiple-assets
         */
        export const manifest: AssetsManifest = {
            bundles: [
                {
                    name: "start",
                    assets: [
                        {
                            alias: "alien",
                            src: "https://pixijs.com/assets/eggHead.png",
                        },
                    ],
                },
            ],
        };
        ```
      </CodeBlockTab>
    </CodeBlockTabs>

    <PixiVnExample path="canvas/mirror" />
  </Accordion>
</Accordions>

## Other features [#other-features]

<Accordions>
  <Accordion title="Sequence" id="sequence">
    The [`canvas.animate`](/jsdoc/pixi-vn/index/interfaces/CanvasManagerInterface#animate) function can also be used to create sequences of animations.

    To create a sequence, you can pass arrays as properties values in the keyframes object. In this case, you can use the [`times` property](https://motion.dev/docs/animate#times) to specify the timing of each keyframe.

    For example:

    <CodeBlockTabs defaultValue="main.ts">
      <CodeBlockTabsList>
        <CodeBlockTabsTrigger value="main.ts">
          main.ts
        </CodeBlockTabsTrigger>

        <CodeBlockTabsTrigger value="assets/index.ts">
          assets/index.ts
        </CodeBlockTabsTrigger>
      </CodeBlockTabsList>

      <CodeBlockTab value="main.ts">
        ```ts
        import { canvas, showImage } from "@drincs/pixi-vn";

        const alien = await showImage("alien");
        canvas.animate(
            alien,
            {
                xAlign: [0, 1, 1, 0, 0],
                yAlign: [0, 0, 1, 1, 0],
            },
            { repeat: Infinity, duration: 10 },
        );
        ```
      </CodeBlockTab>

      <CodeBlockTab value="assets/index.ts">
        ```ts
        import { AssetsManifest } from "@drincs/pixi-vn";

        /**
         * Manifest for the assets used in the game.
         * You can read more about the manifest here: https://pixijs.com/8.x/guides/components/assets#loading-multiple-assets
         */
        export const manifest: AssetsManifest = {
            bundles: [
                {
                    name: "start",
                    assets: [
                        {
                            alias: "alien",
                            src: "https://pixijs.com/assets/eggHead.png",
                        },
                    ],
                },
            ],
        };
        ```
      </CodeBlockTab>
    </CodeBlockTabs>

    <PixiVnExample path="canvas/sequence" />
  </Accordion>

  <Accordion title="Timeline sequences" id="timeline-sequences">
    <CalloutContainer type="warning">
      <CalloutDescription>
        This method has some limitations compared to the previous one, such as restrictions on the [`repeat`](https://motion.dev/docs/animate#repeat) property due to the original `motion` library.
      </CalloutDescription>
    </CalloutContainer>

    Another way to create animation sequences with [`canvas.animate`](/jsdoc/pixi-vn/index/interfaces/CanvasManagerInterface#animate) is by using a [timeline](https://motion.dev/docs/animate#timeline-sequences). This is useful when you want to chain multiple animations that are not strictly linear. You can provide an array of keyframes, where each keyframe is an object with the properties to animate and their values, along with optional animation options.

    For example:

    <CodeBlockTabs defaultValue="main.ts">
      <CodeBlockTabsList>
        <CodeBlockTabsTrigger value="main.ts">
          main.ts
        </CodeBlockTabsTrigger>

        <CodeBlockTabsTrigger value="assets/index.ts">
          assets/index.ts
        </CodeBlockTabsTrigger>
      </CodeBlockTabsList>

      <CodeBlockTab value="main.ts">
        ```ts
        import { canvas, showImage } from "@drincs/pixi-vn";

        const alien = await showImage("alien");
        canvas.animate(
            alien,
            [
                [{ xAlign: 0, yAlign: 0 }, { ease: "circInOut" }],
                [{ xAlign: 1, yAlign: 0 }, { ease: "backInOut" }],
                [{ xAlign: 1, yAlign: 1 }, { ease: "linear" }],
                [{ xAlign: 0, yAlign: 1 }, { ease: "anticipate" }],
                [{ xAlign: 0, yAlign: 0 }, { ease: "easeOut" }],
            ],
            { repeat: 10, duration: 10 },
        );
        ```
      </CodeBlockTab>

      <CodeBlockTab value="assets/index.ts">
        ```ts
        import { AssetsManifest } from "@drincs/pixi-vn";

        /**
         * Manifest for the assets used in the game.
         * You can read more about the manifest here: https://pixijs.com/8.x/guides/components/assets#loading-multiple-assets
         */
        export const manifest: AssetsManifest = {
            bundles: [
                {
                    name: "start",
                    assets: [
                        {
                            alias: "alien",
                            src: "https://pixijs.com/assets/eggHead.png",
                        },
                    ],
                },
            ],
        };
        ```
      </CodeBlockTab>
    </CodeBlockTabs>

    <PixiVnExample path="canvas/motion-sequence" />
  </Accordion>

  <Accordion title="Animate PixiJS UI" id="animate-pixijs-ui">
    Pixi’VN also exposes the `animate` function directly from `motion`, which you can import as:

    ```ts
    import { animate } from "@drincs/pixi-vn/motion";
    ```

    Unlike `canvas.animate`, this function does **not** save the current animation state. This makes it more performant, and it is the right choice for animating <DynamicLink href="/start/interface-pixijs">PixiJS UI</DynamicLink> components — since PixiJS UI elements are not part of Pixi’VN's saved state anyway.
  </Accordion>
</Accordions>
