Skip to content
Back to skills

Pixijs

ASecurity

Renders fast 2D graphics in the browser with PixiJS 8, a WebGL and WebGPU engine for sprites, text, filters, masks and particles. Use when a user asks to build a 2D game, an interactive visualization, an animated banner, a sprite animation from a spritesheet, a particle effect, or to speed up a canvas scene with thousands of objects.

  • 142 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 6, 2026
developmenttypescriptgobashreactnodeawsgitapiperformance

Works with

  • terminal
  • cli
  • api

Security analysis

A96/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro scans all 2 files and shows the line behind each finding

Scanned October 4, 2026

npx -y skills add TerminalSkills/skills --skill pixijs --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Pixijs?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Pixijs
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/terminalskills-pixijs/badge)](https://www.skillsdirectory.com/skills/terminalskills-pixijs)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: pixijs
description: >-
  Renders fast 2D graphics in the browser with PixiJS 8, a WebGL and WebGPU engine for sprites, text, filters, masks and particles. Use when a user asks to build a 2D game, an interactive visualization, an animated banner, a sprite animation from a spritesheet, a particle effect, or to speed up a canvas scene with thousands of objects.
license: Apache-2.0
compatibility: 'PixiJS 8.x (pixi.js on npm), any modern browser with WebGL2 or WebGPU; Node.js 20+ for the build tooling.'
metadata:
  author: terminal-skills
  version: "1.1.0"
  category: development
  tags:
    - 2d-rendering
    - webgl
    - graphics
    - animation
    - game-development
  repository: https://github.com/pixijs/pixijs
---

# PixiJS — High-Performance 2D WebGL Renderer

## Overview

PixiJS is a 2D rendering library for the web. It draws a scene graph of sprites, text, vector graphics and meshes on the GPU with WebGL (default) or WebGPU, batches draw calls automatically, and adds an asset loader, a ticker, a pointer-event system and filters. It is a renderer, not a full game engine: physics, audio and game logic come from other libraries.

This skill targets PixiJS 8 (current: 8.22). The v8 API differs from v7: the application is created with `new Application()` then `await app.init(...)`, shapes use `rect().fill()`, and `ParticleContainer` holds lightweight `Particle` objects. There is no 2D-canvas fallback renderer; the `CanvasRenderer` is listed as "coming soon", so a device needs WebGL or WebGPU.

## Instructions

### Install and set up

```bash
npm create pixi.js@latest      # scaffold a project (Vite template recommended)
npm install pixi.js            # or add to an existing project
```

```typescript
// src/main.ts
import { Application, Assets, Sprite } from 'pixi.js'

(async () => {                  // wrap in a function: top-level await breaks some Vite production builds
  const app = new Application()
  await app.init({
    background: '#1a1a2e',
    resizeTo: window,
    antialias: false,                         // crisp pixel art
    resolution: window.devicePixelRatio,
    autoDensity: true,                        // keeps CSS size correct on retina screens
  })
  document.body.appendChild(app.canvas)       // v8: app.canvas, not app.view

  await Assets.load([
    { alias: 'hero', src: '/sprites/hero.png' },
    { alias: 'tileset', src: '/sprites/tileset.png' },
  ])

  const hero = Sprite.from('hero')            // works for an alias that is already loaded
  hero.anchor.set(0.5)
  hero.position.set(app.screen.width / 2, app.screen.height / 2)
  app.stage.addChild(hero)

  app.ticker.add((ticker) => {
    hero.rotation += 0.01 * ticker.deltaTime  // v8 passes the Ticker, not a number
  })
})()
```

`preference: 'webgpu'` in `init` asks for the WebGPU renderer; the docs call it experimental and recommend WebGL for production.

### Containers and layers

```typescript
import { Container } from 'pixi.js'

const world = new Container()
const effects = new Container()
const hud = new Container()
app.stage.addChild(world, effects, hud)       // later children draw on top

world.sortableChildren = true                 // depth sort by zIndex
app.ticker.add(() => enemies.forEach((e) => { e.zIndex = e.y }))
```

### Filters

```typescript
import { BlurFilter, ColorMatrixFilter, DisplacementFilter, Sprite } from 'pixi.js'

background.filters = [new BlurFilter({ strength: 4 })]
const grayscale = new ColorMatrixFilter()
grayscale.desaturate()
deadEnemy.filters = [grayscale]

const map = Sprite.from('displacement-map')
map.texture.source.style.addressMode = 'repeat'
waterLayer.filters = [new DisplacementFilter({ sprite: map, scale: 20 })]
app.stage.addChild(map)                        // the map sprite must be on the stage to be sampled
```

Release a filter's memory with `container.filters = null`. Blend filters such as `HardMixBlend` need `import 'pixi.js/advanced-blend-modes'`. More effects live in the separate `pixi-filters` package.

### Spritesheet animation

```typescript
import { AnimatedSprite, Assets } from 'pixi.js'

const sheet = await Assets.load('/sprites/hero.json')   // TexturePacker or AssetPack JSON
const walk = new AnimatedSprite(sheet.animations['walk'])
walk.animationSpeed = 0.15
walk.play()
app.stage.addChild(walk)

walk.textures = sheet.animations['attack']               // switch clips
walk.play()
```

### Text and Graphics

```typescript
import { Assets, FillGradient, Graphics, Text } from 'pixi.js'

await Assets.load({ src: '/fonts/press-start-2p.woff2', data: { family: 'Press Start 2P' } })

const scoreText = new Text({
  text: 'Score: 0',
  style: {
    fontFamily: 'Press Start 2P',
    fontSize: 24,
    fill: new FillGradient({ type: 'linear', colorStops: [{ offset: 0, color: '#ffffff' }, { offset: 1, color: '#00ff88' }] }),
    stroke: { color: '#000000', width: 4 },
    dropShadow: { color: '#000000', distance: 2 },
  },
})

const healthBar = new Graphics()
healthBar.rect(0, 0, 200, 20).fill(0x333333)
healthBar.rect(2, 2, 196 * hp, 16).fill(0x00ff00)   // v8: shape first, then fill()/stroke()
```

Gradients are `FillGradient` objects in v8; an array of colours as `fill` was v7 syntax. Changing `text.text` re-rasterizes the text, so for a score that changes every frame use `BitmapText`.

### Many objects: ParticleContainer

```typescript
import { Particle, ParticleContainer, Texture } from 'pixi.js'

const sparks = new ParticleContainer({ dynamicProperties: { position: true, rotation: true, vertex: false, color: false } })
for (let i = 0; i < 50_000; i++) {
  sparks.addParticle(new Particle({ texture: Texture.from('particle'), x: Math.random() * 800, y: Math.random() * 600 }))
}
app.stage.addChild(sparks)
```

Particles have no children, events or filters; use `addParticle`/`removeParticle` instead of `addChild`. Properties not listed as dynamic are uploaded only when you call `sparks.update()`. The API is marked experimental.

## Examples

### Example 1: Animated hero in a platformer

**User prompt:** "Load hero.json and make the character walk, then switch to attack when I press space."

Load the sheet with `Assets.load('/sprites/hero.json')`, create an `AnimatedSprite` from `sheet.animations['walk']`, call `play()`, and on `keydown` for `Space` set `textures` to `sheet.animations['attack']`, `loop = false`, then `play()` and restore `walk` in `onComplete`. Result: the sprite loops the walk cycle and plays a single attack animation on each key press.

### Example 2: Rain of 100,000 particles

**User prompt:** "My falling-snow effect with 20,000 Sprites runs at 20 fps. Make it smooth."

Replace the `Sprite` objects with `Particle` objects in one `ParticleContainer` with `dynamicProperties: { position: true }`, and in the ticker update each `particle.y += speed * ticker.deltaTime`, wrapping at the bottom. Result: one batched draw call; 100,000 flakes stay at the display refresh rate on a typical laptop.

## Guidelines

- Always `await app.init()` before touching `app.canvas`, `app.stage` or `app.screen`.
- Keep layers in separate containers; draw order inside a container is child order unless `sortableChildren` is on.
- Spritesheets batch best: sprites that share a texture atlas draw together, and mixing sprite, graphics and text objects alternately breaks batches.
- Filters, masks and blend modes cost render passes. Use few, and prefer rectangle masks (scissor) over sprite masks.
- Textures are garbage-collected after about 3600 idle frames; call `destroy()` on objects you remove. `sprite.destroy(true)` also destroys the texture, which breaks other sprites that share it, so use `sprite.destroy()` for shared textures and `Assets.unload(alias)` to free an asset.
- Pool objects that appear and disappear often (bullets, particles) instead of creating them every frame.
- For a plain static page or a simple chart, SVG or Canvas 2D is lighter than PixiJS.
- Using React? Use the `@pixi/react` package instead of mixing imperative setup into components.

Files in this skill

  • SKILL.md5.6 KB
  • _scores.json1.9 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…