pixijs-v8

star 6

PixiJS v8 — fast 2D WebGL/WebGPU renderer. Use when building interactive graphics, games, or data visualizations in the browser. Covers Application setup, scene graph, sprites, graphics, text, and asset loading.

pradeepmouli By pradeepmouli schedule Updated 4/19/2026

name: pixijs-v8 description: PixiJS v8 — fast 2D WebGL/WebGPU renderer. Use when building interactive graphics, games, or data visualizations in the browser. Covers Application setup, scene graph, sprites, graphics, text, and asset loading.

PixiJS v8 Skill

When to Use

  • Building 2D games, interactive experiences, or animated UIs in the browser
  • Rendering many sprites, particles, or animated objects at high frame rates
  • Need hardware-accelerated 2D graphics with WebGL or WebGPU

Avoid When

  • Simple static UI — use CSS/HTML instead
  • Server-side rendering without a canvas environment
  • 3D scenes — use Three.js or Babylon.js instead

Critical Pitfalls (NEVER rules)

NEVER pass options to the Application constructor — always use await app.init().

// WRONG (deprecated, triggers warning in v8)
const app = new Application({ width: 800 });

// RIGHT
const app = new Application();
await app.init({ width: 800, height: 600 });

NEVER use app.view — it was renamed to app.canvas.

// WRONG
document.body.appendChild(app.view);

// RIGHT
document.body.appendChild(app.canvas);

NEVER use Texture.from(url) to load a URL that hasn't been loaded yet — load through Assets first.

// WRONG — will return empty texture if not preloaded
const tex = Texture.from('https://example.com/sprite.png');

// RIGHT
await Assets.load('https://example.com/sprite.png');
const tex = Texture.from('https://example.com/sprite.png');
// Or simply:
const tex = await Assets.load<Texture>('sprite.png');

NEVER use the v7 Graphics API (beginFill / drawRect / endFill) — v8 changed the order.

// WRONG (v7 style)
g.beginFill(0xff0000).drawRect(0, 0, 100, 100).endFill();

// RIGHT (v8 style: shape first, then fill/stroke)
g.rect(0, 0, 100, 100).fill(0xff0000);

NEVER add children to leaf nodes (Sprite, Graphics, Text) — only Container accepts children.

// WRONG
const sprite = new Sprite(texture);
sprite.addChild(otherSprite); // deprecated / will warn

// RIGHT
const container = new Container();
container.addChild(sprite);
container.addChild(otherSprite);

NEVER use DisplayObject — it was removed. Everything is a Container.

NEVER use container.name — it was renamed to container.label.

NEVER use SCALE_MODES.NEAREST enum — use the string 'nearest' instead.

NEVER use container.cacheAsBitmap = true — call container.cacheAsTexture(true) instead.

NEVER use container.getBounds() expecting a Rectangle — v8 returns a Bounds object; use .rectangle.

const rect = container.getBounds().rectangle;

NEVER use Ticker.shared.add(dt => ...) expecting delta time — the callback now receives the Ticker instance.

// WRONG
Ticker.shared.add((dt) => {
  sprite.x += dt;
});

// RIGHT
Ticker.shared.add((ticker) => {
  sprite.x += ticker.deltaTime;
});

NEVER import from sub-packages like @pixi/sprite — v8 uses a single package.

// WRONG
import { Sprite } from '@pixi/sprite';

// RIGHT
import { Sprite } from 'pixi.js';

NEVER use utils.isMobile — import directly.

// WRONG
import { utils } from 'pixi.js';
utils.isMobile.any();

// RIGHT
import { isMobile } from 'pixi.js';
isMobile.any();

NEVER use settings.RESOLUTION — configure via AbstractRenderer.defaultOptions or init options.

// WRONG
settings.RESOLUTION = 2;

// RIGHT
await app.init({ resolution: window.devicePixelRatio });

NEVER use updateTransform() for per-frame logic — use onRender instead.

// RIGHT
mySprite.onRender = () => {
  /* custom per-frame logic */
};

NEVER use ParticleContainer with Sprite children — v8 requires Particle objects.

// WRONG
container.addChild(new Sprite(texture));

// RIGHT
container.addParticle(new Particle(texture));

Key Classes — Decision Table

Goal Class to Use Notes
App scaffolding Application Manages renderer + stage + ticker
Group/layer objects Container Only class that accepts children
Display an image/texture Sprite Fastest renderable; use spritesheets
Draw shapes programmatically Graphics v8: shape→fill order; shares GraphicsContext
Canvas-rendered text Text Flexible styling; expensive if updated every frame
High-perf static/dynamic text BitmapText GPU-batched; best for score counters, labels
HTML/CSS styled text HTMLText Rich formatting; slower than canvas text
10k+ particles ParticleContainer + Particle Flat list, no children, requires boundsArea
Custom rendering batch Mesh Full shader control
9-slice UI panel NineSliceSprite Renamed from NineSlicePlane in v8
Tiling background TilingSprite Repeating texture
Load assets Assets (static) Global singleton, cached, async
GPU-optimized sub-tree Container with isRenderGroup: true Transforms applied on GPU

Quick Start

import { Application, Assets, Sprite } from 'pixi.js';

// 1. Create and initialize the app (MUST await)
const app = new Application();
await app.init({
  width: 800,
  height: 600,
  backgroundColor: 0x1099bb,
  resolution: window.devicePixelRatio,
  autoDensity: true
});

// 2. Add canvas to the DOM
document.body.appendChild(app.canvas);

// 3. Load assets via Assets (returns cached textures on repeat calls)
const texture = await Assets.load('bunny.png');

// 4. Create a sprite and add to stage
const bunny = new Sprite(texture);
bunny.anchor.set(0.5); // center anchor
bunny.position.set(app.screen.width / 2, app.screen.height / 2);
app.stage.addChild(bunny);

// 5. Animate with ticker
app.ticker.add((ticker) => {
  bunny.rotation += 0.05 * ticker.deltaTime;
});

ApplicationOptions (key fields)

Option Type Default Description
width number 800 Canvas width in pixels
height number 600 Canvas height in pixels
backgroundColor ColorSource 0x000000 Background fill color
backgroundAlpha number 1 Background alpha (0 = transparent)
antialias boolean false Enable MSAA antialiasing
resolution number 1 Device pixel ratio
autoDensity boolean false Auto-adjust CSS size to match resolution
preference 'webgl' | 'webgpu' | 'canvas' 'webgl' Renderer preference
resizeTo Window | HTMLElement Auto-resize to element
autoStart boolean true Start ticker automatically
sharedTicker boolean false Use shared global ticker
manageImports boolean true Auto-import default extensions
textureGCActive boolean true Enable texture garbage collection
textureGCMaxIdle number 3600 Frames before texture GC
roundPixels boolean false Force pixel-rounding on renderer
failIfMajorPerformanceCaveat boolean false Fail on GPU denylist

Quick Reference

Container (base class for all scene objects)

// Transform
container.x = 100; container.y = 200;
container.position.set(100, 200);
container.scale.set(2);           // uniform scale
container.rotation = Math.PI / 4; // radians
container.angle = 45;             // degrees (alias)
container.pivot.set(50, 50);      // rotation origin (local coords)
container.origin.set(50, 50);     // rotate around point without offset

// Appearance
container.alpha = 0.5;
container.visible = false;        // skips draw + transform
container.renderable = false;     // skips draw, keeps transform
container.tint = 0xff0000;        // red tint
container.blendMode = 'add';

// Children
container.addChild(child);
container.removeChild(child);
container.addChildAt(child, 0);
container.setChildIndex(child, 2);
container.sortableChildren = true;
child.zIndex = 10;

// Bounds
const bounds = container.getBounds().rectangle; // returns Bounds, use .rectangle
container.boundsArea = new Rectangle(0, 0, 400, 400); // optimization

// Culling
container.cullable = true;
container.cullArea = new Rectangle(0, 0, 400, 400);
container.cullableChildren = false;

// Events
container.on('pointerdown', (e) => { ... });
container.eventMode = 'static';  // 'none' | 'passive' | 'auto' | 'static' | 'dynamic'
container.interactiveChildren = false; // skip hit-testing children

// Utility
const globalPos = container.toGlobal(new Point(0, 0));
const localPos  = container.toLocal(new Point(100, 100));
container.label = 'myContainer';   // was .name in v7
container.onRender = () => { /* per-frame logic */ }; // replaces updateTransform

// Performance
const rg = new Container({ isRenderGroup: true }); // GPU-side transforms
container.cacheAsTexture(true); // was cacheAsBitmap in v7

Sprite

// Creation
const sprite = new Sprite(texture);
const sprite = Sprite.from('image.png'); // requires texture already loaded via Assets
const sprite = new Sprite({ texture, anchor: 0.5, roundPixels: true });

// Anchor (0=top-left, 0.5=center, 1=bottom-right)
sprite.anchor.set(0.5);
sprite.anchor.set(0.5, 0);

// Size
sprite.width = 100;
sprite.height = 200;

// Texture swap
sprite.texture = newTexture;
// After manual UV modification, force update:
sprite.onViewUpdate();

Graphics

const g = new Graphics();

// v8 pattern: build shape THEN apply fill/stroke
g.rect(x, y, w, h).fill(0xff0000);
g.rect(x, y, w, h).fill({ color: 0xff0000, alpha: 0.5 });
g.rect(x, y, w, h).fill({ texture: myTexture }).stroke({ width: 2, color: 'white' });

// Shapes
g.circle(cx, cy, radius).fill(0x00ff00);
g.ellipse(cx, cy, rx, ry).fill(color);
g.roundRect(x, y, w, h, radius).fill(color);
g.poly([x1, y1, x2, y2, x3, y3]).fill(color);
g.moveTo(x, y).lineTo(x2, y2).stroke({ width: 2, color: 0xffffff });

// Holes (cut = hollow out previous shape)
g.rect(0, 0, 100, 100).fill(0x00ff00).circle(50, 50, 20).cut();

// Shared context (draw once, render many)
const ctx = new GraphicsContext().rect(0, 0, 50, 50).fill(0xff0000);
const g1 = new Graphics(ctx);
const g2 = new Graphics(ctx); // same GPU data, different transforms

// As mask
sprite.mask = g;

Text / BitmapText / HTMLText

// Canvas text — flexible, expensive to update
const text = new Text({
  text: 'Hello!',
  style: {
    fontFamily: 'Arial',
    fontSize: 24,
    fill: 0xff1010,
    align: 'center',
    wordWrap: true,
    wordWrapWidth: 200,
    stroke: { color: '#4a1850', width: 5 },
    dropShadow: { color: '#000000', blur: 4, distance: 6, angle: Math.PI / 6 }
  },
  anchor: 0.5
});

// BitmapText — best for score counters, frequently updated labels
const bmpText = new BitmapText({ text: '0', style: { fontFamily: 'Arial', fontSize: 24 } });

// HTMLText — rich HTML markup support
const htmlText = new HTMLText({ text: '<b>Bold</b> and <i>italic</i>' });

// Constructor change from v7:
// OLD: new Text('Hello', { fontSize: 24 })
// NEW: new Text({ text: 'Hello', style: { fontSize: 24 } })

Assets

// Load single asset
const texture = await Assets.load<Texture>('sprite.png');

// Load multiple
const assets = await Assets.load(['a.png', 'b.png']);

// With alias
Assets.add({ alias: 'hero', src: 'hero.{webp,png}' });
const texture = await Assets.load('hero');

// Bundles
await Assets.init({
  manifest: {
    bundles: [{ name: 'game', assets: [{ alias: 'bg', src: 'bg.png' }] }]
  }
});
await Assets.loadBundle('game');

// Background preload
Assets.backgroundLoad(['next-level.png']);

// Unload
await Assets.unload('sprite.png');
texture.source.unload(); // manual GPU unload

Ticker

// App ticker (runs automatically)
app.ticker.add((ticker) => {
  sprite.rotation += 0.05 * ticker.deltaTime; // deltaTime = frame delta in ticks
});

// Shared global ticker
import { Ticker } from 'pixi.js';
Ticker.shared.add((ticker) => { ... });
Ticker.shared.remove(myFn);

// Manual control
app.ticker.stop();
app.ticker.start();

Destroy / Cleanup

// Sprite only (preserves texture)
sprite.destroy();

// Sprite + texture
sprite.destroy({ texture: true, textureSource: true });

// Container tree
container.destroy({ children: true });

// Full app teardown
app.destroy({ removeView: true }, { children: true, texture: true });

// Unload via Assets (removes from cache + GPU)
await Assets.unload('sprite.png');

References

Install via CLI
npx skills add https://github.com/pradeepmouli/skillit --skill pixijs-v8
Repository Details
star Stars 6
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator
pradeepmouli
pradeepmouli Explore all skills →