The GIF module adds animated GIF support to PixiJS. It handles decoding, frame management, and playback control. GIF support is not included in the base pixi.js import; you must import from pixi.js/gif.
Assets.load() returns a GifSource, which holds all decoded frames. Pass it to GifSprite to display and animate it.
import 'pixi.js/gif'; // Must be imported before loading GIFs
import { Application, Assets, GifSprite } from 'pixi.js';
const app = new Application();
await app.init({ width: 800, height: 600 });
const source = await Assets.load('explosion.gif');
const gif = new GifSprite(source);
app.stage.addChild(gif);
GIFs are convenient but decode every frame into a separate texture. For performance-critical animations with many frames, consider using a spritesheet with AnimatedSprite instead; it uses a single atlas texture and is more GPU-friendly.
You can also pass an options object with the source and any SpriteOptions:
const gif = new GifSprite({
source,
x: 100,
y: 200,
anchor: 0.5,
});
The asset loader accepts configuration through the data property. These options are forwarded to GifSource.from and extend CanvasSourceOptions.
import { Assets } from 'pixi.js';
import 'pixi.js/gif';
// Load with custom frame rate and scale mode
const source = await Assets.load({
src: 'pixel-art.gif',
data: {
fps: 12,
scaleMode: 'nearest',
resolution: 2,
},
});
// Load from a base64 data URI
const source2 = await Assets.load('data:image/gif;base64,...');
The fps option (default: 30) sets the fallback frame delay for GIF frames that don't specify their own delay.
gif.play();
gif.stop();
// Jump to a specific frame
gif.currentFrame = 5;
gif.play();
// Read-only state
console.log(gif.totalFrames); // number of frames
console.log(gif.playing); // true if animating
console.log(gif.progress); // 0-1 playback progress
console.log(gif.duration); // total duration in ms
// Speed and looping
gif.animationSpeed = 0.5; // half speed
gif.loop = false; // stop at the last frame
All properties of GifSpriteOptions:
const gif = new GifSprite({
source,
autoPlay: true, // start playing on creation (default: true)
loop: true, // loop the animation (default: true)
animationSpeed: 1, // playback speed multiplier (default: 1)
autoUpdate: true, // auto-update via Ticker.shared (default: true)
fps: 30, // fallback frame rate (default: 30)
// Callbacks
onComplete: () => {
console.log('animation finished');
},
onLoop: () => {
console.log('animation looped');
},
onFrameChange: (frame) => {
console.log(`frame: ${frame}`);
},
});
Set autoUpdate to false to drive playback yourself by calling gif.update(ticker) each frame.
clone() creates a new GifSprite sharing the same GifSource. The clone copies playback settings but gets its own playback state.
const clone = gif.clone();
// Destroy the sprite; the GifSource stays alive for other sprites
gif.destroy();
// Destroy the sprite AND its GifSource (destroys all frame textures).
// WARNING: this also breaks any other GifSprite using the same source.
gif.destroy(true);
// Or unload through the Assets system
await Assets.unload('explosion.gif');
GifSource.from()GifSource.from() and the asset loader's data field