Skip to main content
skill CX Codex

pixijs-scene-gif — Claude Code skill: what it does, how to install

Teaches coding assistants how to load and play animated GIFs in PixiJS v8 with GifSprite. Useful when embedding GIF assets directly into scene trees.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add pixijs/pixijs-skills --skill pixijs-scene-gif -a claude-code
Open on GitHub

What pixijs-scene-gif does

The skill provides patterns for PixiJS v8 GIF playback. It ensures the assistant includes the import 'pixi.js/gif' side-effect import so Assets.load recognizes .gif files and returns a GifSource instead of a plain Texture.

GifSprite extends Sprite as a leaf display object, which means you cannot nest child elements inside it. To group multiple GIF instances, place them in a Container. The constructor configures options like autoPlay, loop, animationSpeed, and event callbacks such as onComplete or onFrameChange.

GIFs decode every frame into an individual canvas texture, so high-frame animations are a good reason to audit GPU memory and switch to AnimatedSprite with a spritesheet atlas.

What it helps with

  • load animated GIF files into PixiJS v8 scenes using Assets.load
  • control frame playback, loop behavior, and speed on GifSprite
  • handle playback events with onComplete, onLoop, and onFrameChange callbacks
  • configure fallback FPS and canvas texture resolution for GIF assets

Example prompts for the agent

  • Load animation.gif using PixiJS v8 and display it centered with GifSprite
  • Set up a non-looping GifSprite with an onComplete callback and custom animationSpeed

How to install pixijs-scene-gif

1Skills CLI (Vercel)

npx skills add pixijs/pixijs-skills --skill pixijs-scene-gif -a claude-code

2Manually: put the files in place

~/.claude/skills/pixijs-scene-gif/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/pixijs-scene-gif/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about pixijs-scene-gif

How to install pixijs-scene-gif in Claude Code?

Run npx skills add pixijs/pixijs-skills --skill pixijs-scene-gif -a claude-code in your terminal.

What does pixijs-scene-gif do?

It guides coding agents on using the pixi.js/gif package in PixiJS v8. It covers GifSource asset loading, GifSprite configuration, and playback control methods.

Why does the skill suggest AnimatedSprite for complex animations?

Each GIF frame decodes into an individual canvas texture. An AnimatedSprite uses a single spritesheet atlas instead, which batches much better on the GPU.

Source text

SKILL.md · MIT
---
name: pixijs-scene-gif
description: "Use this skill when displaying animated GIFs in PixiJS v8. Covers the pixi.js/gif side-effect import, Assets.load returning a GifSource, GifSprite playback (play/stop/currentFrame/animationSpeed), autoPlay/loop options, onComplete/onLoop/onFrameChange callbacks, GifSource sharing, clone, destroy. Triggers on: GifSprite, GifSource, pixi.js/gif, animationSpeed, currentFrame, autoPlay, onComplete, onFrameChange, constructor options, GifSpriteOptions."
license: MIT
---

`GifSprite` plays an animated GIF as a display object. `Assets.load('animation.gif')` returns a `GifSource` (not a `Texture`), and you wrap that in a `GifSprite`. Requires a side-effect `import 'pixi.js/gif'` to register the loader extension.

Assumes familiarity with `pixijs-scene-core-concepts`. `GifSprite` extends `Sprite`, so it is a leaf: do not nest children inside it. Wrap multiple `GifSprite` instances in a `Container` to group them.

## Quick Start

```ts
import "pixi.js/gif";
import { GifSprite } from "pixi.js/gif";

const source = await Assets.load("animation.gif");

const gif = new GifSprite({
  source,
  autoPlay: true,
  loop: true,
  animationSpeed: 1,
});

gif.anchor.set(0.5);
gif.x = app.screen.width / 2;
gif.y = app.screen.height / 2;

app.stage.addChild(gif);
```

> [!NOTE]
> GIFs decode every frame into a separate canvas texture. For performance-critical animations with many frames, prefer a spritesheet with `AnimatedSprite` — it uses a single atlas texture and batches better on the GPU.

**Related skills:** `pixijs-scene-core-concepts` (scene graph basics), `pixijs-scene-sprite` (`AnimatedSprite` for spritesheet-based animation), `pixijs-assets` (`Assets.load`, caching, unloading), `pixijs-ticker` (frame timing), `pixijs-performance` (texture memory).

## Constructor options

`GifSpriteOptions` extends `Omit<SpriteOptions, 'texture'>`; `texture` is managed internally (set from `source.textures[0]` and swapped per frame). All other `Sprite` options (`anchor`, `scale`, `tint`, `roundPixels`, etc.) are valid, and all `Container` options (`position`, `scale`, `tint`, `label`, `filters`, `zIndex`, etc.) are also valid here — see `skills/pixijs-scene-core-concepts/references/constructor-options.md`.

Leaf-specific options added by `GifSpriteOptions`:

| Option           | Type                              | Default    | Description                                                                                                                |
| ---------------- | --------------------------------- | ---------- | -------------------------------------------------------------------------------------------------------------------------- |
| `source`         | `GifSource`                       | —          | Required. The parsed GIF data returned by `Assets.load('file.gif')`. Can be shared across multiple `GifSprite` instances.  |
| `autoPlay`       | `boolean`                         | `true`     | Start playback immediately on construction. If `false`, you must call `gif.play()` to begin.                               |
| `loop`           | `boolean`                         | `true`     | Repeat the animation on reaching the last frame. When `false`, the sprite stops at the final frame and fires `onComplete`. |
| `animationSpeed` | `number`                          | `1`        | Multiplier on the GIF's native frame timing. `2` runs at double speed; `0.5` runs at half.                                 |
| `autoUpdate`     | `boolean`                         | `true`     | Connect playback to `Ticker.shared`. Set to `false` to drive updates yourself via `gif.update(ticker)`.                    |
| `fps`            | `number`                          | `30`       | Fallback frame rate for GIFs that do not specify per-frame delays.                                                         |
| `onComplete`     | `() => void \| null`              | `null`     | Called when a non-looping animation reaches the last frame.                                                                |
| `onLoop`         | `() => void \| null`              | `null`     | Called each time a looping animation wraps around.                                                                         |
| `onFrameChange`  | `(frame: number) => void \| null` | `null`     | Called every time the displayed frame index changes.                                                                       |
| `scaleMode`      | `SCALE_MODE`                      | `'linear'` | Deprecated since 8.13.0 — pass `scaleMode` via `Assets.load(..., { data: { scaleMode } })` instead.                        |

The constructor also accepts a bare `GifSource` as its sole argument (`new GifSprite(source)`), which is shorthand for `new GifSprite({ source })` using the defaults above.

## Core Patterns

### Setup and the side-effect import

```ts
import "pixi.js/gif";
import { Assets } from "pixi.js";
import { GifSprite } from "pixi.js/gif";

const source = await Assets.load("animation.gif");
const gif = new GifSprite({ source });
```

`pixi.js/gif` calls `extensions.add(GifAsset)`, registering `.gif` with the asset loader. Without it, `Assets.load` does not recognize GIF files. `GifSprite` and `GifSource` are exported from `pixi.js/gif`, not `pixi.js`.

Importing a named export from `pixi.js/gif` also triggers the side effect, so a bare `import 'pixi.js/gif'` is only needed when you don't import anything from that path.

### Playback control

```ts
const gif = new GifSprite({ source });

gif.play();
gif.stop();

gif.currentFrame = 5;
gif.animationSpeed = 2;
gif.animationSpeed = 0.5;

gif.playing; // read-only
gif.progress; // 0-1 playback position
gif.totalFrames; // number of frames
gif.duration; // total duration in ms
```

`autoPlay: true` (default) starts playback immediately; `loop: true` (default) repeats. `animationSpeed` is a multiplier on the GIF's native frame timing. `currentFrame` is zero-based.

### Loading options

```ts
const source = await Assets.load({
  src: "animation.gif",
  data: {
    fps: 12,
    scaleMode: "nearest",
    resolution: 2,
  },
});

const fromDataUri = await Assets.load("data:image/gif;base64,R0lGODlh...");
```

Options in `data` are passed to `GifSource.from`. `fps` sets the fallback frame delay for GIFs that don't specify timing. `scaleMode` and `resolution` control the canvas textures created for each frame. The loader matches both `.gif` file extensions and `data:image/gif` URIs.

### Callbacks

```ts
const gif = new GifSprite({
  source,
  loop: false,
  onComplete: () => console.log("animation finished"),
  onLoop: () => console.log("loop completed"),
  onFrameChange: (frame) => console.log("now on frame", frame),
});
```

- `onComplete` fires when a non-looping animation reaches the last frame.
- `onLoop` fires each time a looping animation wraps around.
- `onFrameChange` fires every time the displayed frame changes.

### Manual update mode

```ts
const gif = new GifSprite({ source, autoUpdate: false });

app.ticker.add((ticker) => {
  gif.update(ticker);
});
```

`autoUpdate: false` disconnects from `Ticker.shared`. You call `gif.update(ticker)` yourself, passing any `Ticker` instance. Useful when animation should be driven by a private ticker (e.g., a pause-aware game ticker).

### Sharing source data and cloning

```ts
const source = await Assets.load("animation.gif");

const gif1 = new GifSprite({ source, autoPlay: true });
const gif2 = new GifSprite({ source, autoPlay: false });

const gif3 = gif1.clone();
gif3.animationSpeed = 0.5;
```

`GifSource` can be shared across multiple `GifSprite` instances; each sprite has independent playback state. `clone()` copies all playback settings but creates an independent instance.

## Common Mistakes

### [HIGH] Not importing pixi.js/gif

Wrong:

```ts
import { Assets } from "pixi.js";
const gif = await Assets.load("animation.gif");
```

Correct:

```ts
import "pixi.js/gif";
import { Assets } from "pixi.js";
const source = await Assets.load("animation.gif");
```

The GIF loader extension must be registered before loading. Without the side-effect import, the loader does not recognize `.gif` files and the load either fails or returns raw data.


### [MEDIUM] Expecting Assets.load to return a Texture

Wrong:

```ts
const texture = await Assets.load("animation.gif");
const sprite = new Sprite(texture);
```

Correct:

```ts
const source = await Assets.load("animation.gif");
const gif = new GifSprite({ source });
```

`Assets.load` on a GIF returns a `GifSource` containing frame textures and timing data. Pass the source to `GifSprite`; for a single still frame, read `source.textures[0]`.


### [MEDIUM] GIF memory not released on destroy

Wrong:

```ts
gif.destroy();
// GifSource and frame textures remain in memory
```

Correct:

```ts
gif.destroy(true);
// or
await Assets.unload("animation.gif");
```

GIF frames hold decoded pixel data as individual canvas textures. `gif.destroy()` (or `destroy(false)`) destroys the sprite but keeps the `GifSource` intact. Pass `true` to also destroy the source. For shared sources, only destroy when the last consumer is done, or call `Assets.unload` to let the asset cache handle it.


### [LOW] Do not nest children inside a GifSprite

`GifSprite` extends `Sprite`, which sets `allowChildren = false`. It is a leaf. To group a GIF with other display objects, wrap them all in a plain `Container`:

```ts
const group = new Container();
group.addChild(gif, label);
```


## API Reference

- [GifSprite](https://pixijs.download/release/docs/gif.GifSprite.html.md)
- [GifSpriteOptions](https://pixijs.download/release/docs/gif.GifSpriteOptions.html.md)
- [GifSource](https://pixijs.download/release/docs/gif.GifSource.html.md)
- [GifAsset](https://pixijs.download/release/docs/gif.GifAsset.html.md)
- [GifBufferOptions](https://pixijs.download/release/docs/gif.GifBufferOptions.html.md)
- [GifFrame](https://pixijs.download/release/docs/gif.GifFrame.html.md)

© pixijs · MIT · pixijs/pixijs-skills

Similar skills

Everything for Frontend and UI →

From the same set25

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor