Skip to content

PixiJS Getting Started — Complete Beginner's Guide to 2D WebGL

DodaTech Updated 2026-06-06 11 min read

PixiJS is a fast 2D WebGL renderer that creates rich interactive graphics using hardware acceleration. In this guide you'll build your first scene from scratch.

What You'll Learn

  • What PixiJS is and why it beats plain Canvas for 2D graphics
  • How to install PixiJS via npm or CDN
  • How the Application, renderer, and stage work together
  • How to create sprites from textures and position them
  • How to build a responsive interactive scene Builder

Why PixiJS Matters

Modern web applications need smooth, hardware-accelerated 2D graphics. PixiJS is the most popular WebGL 2D framework, used by thousands of games, data dashboards, and security visualization tools.

At DodaTech, we use PixiJS in Durga Antivirus Pro to render real-time threat maps, live network traffic flows, and animated security dashboards. When a threat is detected, the UI animates a heatmap overlay using PixiJS sprites — all at 60fps. This is the kind of performance you can only get with GPU-accelerated rendering.

â„šī¸ Info

Prerequisites: Basic JavaScript knowledge (variables, functions, DOM). No WebGL or graphics experience needed — we explain every concept from the ground up.

Learning Path

flowchart LR
    GS["Getting Started âŦ… You Are Here"] --> GT["Graphics & Textures"]
    GT --> AI["Animation & Interactivity"]
    AI --> TF["Text & Bitmap Fonts"]
    TF --> PB["Performance & Best Practices"]
    style GS fill:#4a90d9,stroke:#fff,color:#fff
    linkStyle default stroke:#4a90d9,stroke-width:2

PixiJS vs Canvas API vs Raw WebGL

Feature PixiJS Canvas 2D API Raw WebGL
Ease of use Easy — scene graph API Moderate — imperative drawing Hard — shaders & buffers
GPU acceleration Yes (WebGL) Software rasterization Yes
Draw calls Automatic batching Manual Manual
Filters & effects Built-in None natively You write shaders
Best for Games, dashboards, tools Simple 2D drawings 3D or custom rendering

When to use PixiJS: You need smooth 60fps rendering with hundreds of sprites, interactive elements, and visual effects — without writing shader code.

How PixiJS Works — The Big Picture

Think of PixiJS like a movie projector and your code like the film reel:

  • The renderer is the projector — it takes your scene and draws it on screen
  • The stage is the screen where everything appears
  • Sprites are paper cutouts you place on the screen
  • Textures are the stickers you stick onto those cutouts

Every frame, the projector (renderer) scans the screen (stage), checks where all the cutouts (sprites) are, and draws them. The magic is that the projector uses the GPU to do this extremely fast.

Setting Up PixiJS

Via npm (for build tools)

npm install pixi.js

Then in your JavaScript file:

import * as PIXI from 'pixi.js';

Via CDN (for HTML pages)

<script src="https://cdn.jsdelivr.net/npm/pixi.js@7.x/dist/pixi.min.js"></script>

After this, the global PIXI object is available. No build step needed — perfect for prototyping and tutorials.

The Application — Your Starting Point

The Application class is like a starter kit that creates three things at once:

  1. A renderer (the projector) — connected to a <canvas> element
  2. A stage (the screen) — a root container for all objects
  3. A ticker (the clock) — runs your animation code every frame
const app = new PIXI.Application({
  width: 800,
  height: 600,
  backgroundColor: 0x1099bb,
  resolution: window.devicePixelRatio || 1,
  autoDensity: true,
});

document.body.appendChild(app.view); // app.view is the <canvas>

Let's break this down:

Option What it does Why it matters
width / height Canvas size in CSS pixels Defines your drawing area
backgroundColor Hex color of the background 0x1099bb is a nice blue
resolution Pixel density multiplier devicePixelRatio makes text sharp on Retina displays
autoDensity Adjust CSS size automatically Prevents blurry rendering on HiDPI screens

Why set resolution? Without it, your crisp vector graphics look blurry on Retina Macs and high-end phones. The devicePixelRatio tells PixiJS to render at 2x or 3x the CSS size, then shrink it back — giving you razor-sharp visuals.

Renderer Types — What Runs Under the Hood

PixiJS tries WebGL2 first, then WebGL1, then falls back to Canvas 2D. You don't need to pick — it just works.

// Force Canvas mode if needed
const app = new PIXI.Application({ forceCanvas: true });

// Check at runtime
console.log(app.renderer.type); // 1 = WebGL, 2 = Canvas

Why does the renderer type matter? WebGL runs on the GPU, which is optimized for parallel drawing operations. Canvas 2D runs on the CPU, which is slower. For a threat visualization dashboard in Durga Antivirus Pro, WebGL means we can animate hundreds of threat nodes simultaneously without dropping frames.

The Stage — Your Root Container

The stage is a Container that acts as the root of your scene graph. Think of it like the root folder on your computer — everything you create lives inside it.

const container = new PIXI.Container();
app.stage.addChild(container);

Scene graph means: when you move a parent container, all its children move with it. This is like picking up a tray of drinks — all the cups move together.

Sprites & Textures — Paper Cutouts with Stickers

A sprite is a display object that shows an image. A texture is the image data that the sprite displays.

The analogy: a texture is a sticker, and a sprite is the paper cutout you put the sticker on. You can move the cutout around, rotate it, or scale it — the sticker moves with it.

Loading a texture from a URL

const texture = PIXI.Texture.from('https://pixijs.com/assets/bunny.png');
const bunny = new PIXI.Sprite(texture);
app.stage.addChild(bunny);

Three steps:

  1. Texture.from() — load the image and wrap it as a texture (the sticker)
  2. new PIXI.Sprite(texture) — create a sprite (the cutout) with that sticker
  3. app.stage.addChild(bunny) — place the cutout on the screen

Loading from a local file (Webpack / Vite)

import bunnyImg from './assets/bunny.png';
const texture = PIXI.Texture.from(bunnyImg);

Positioning, Rotation & Scale

Once you have a sprite, you can control its position, rotation, and scale like this:

const sprite = new PIXI.Sprite(texture);

sprite.x = 100;           // move 100px right
sprite.y = 200;           // move 200px down
sprite.rotation = Math.PI / 4;  // rotate 45 degrees
sprite.scale.set(2);      // make it 2x bigger
sprite.anchor.set(0.5);   // center the rotation point

The anchor is important. By default, anchor is at (0,0) — the top-left corner. This means rotation and scale happen around the top-left corner, which looks weird. Setting anchor.set(0.5) centers the pivot point, so rotation spins the sprite around its middle — like a spinning coin.

Responsive Auto-Resize

Make your canvas adapt to window size changes:

window.addEventListener('resize', () => {
  app.renderer.resize(window.innerWidth, window.innerHeight);
});

For a fixed aspect ratio (e.g., 16:9):

const resize = () => {
  const ratio = 16 / 9;
  let w = window.innerWidth;
  let h = window.innerHeight;
  if (w / h > ratio) w = h * ratio;
  else h = w / ratio;
  app.renderer.resize(w, h);
};
window.addEventListener('resize', resize);
resize();

Common Mistakes

Mistake Why it happens How to fix it
Sprites appear blurry Missing autoDensity and resolution Always set resolution: window.devicePixelRatio and autoDensity: true
Rotation looks wrong Anchor is at (0,0) instead of center Call sprite.anchor.set(0.5) before rotating
Image not showing Texture URL is wrong or CORS blocked Check the console for 404 errors; use same-origin or CORS-enabled URLs
Width/height is 0 You checked dimensions before first render Make sure the sprite is added to stage and a frame has passed
Canvas is tiny or huge Forgot to call document.body.appendChild(app.view) Always append the canvas to the DOM
Code runs before texture loads Texture.from() is async for remote URLs Use app.loader or ensure the image is cached

Practice Questions

  1. What does anchor.set(0.5) do and why is it useful?

    • It sets the pivot point to the center of the sprite. Without it, rotation and scale happen around the top-left corner.
  2. What is the difference between WebGL and Canvas mode in PixiJS?

    • WebGL uses the GPU for hardware-accelerated rendering. Canvas mode renders on the CPU and is significantly slower.
  3. Why does app.renderer.resize() matter for Responsive Design?

    • Without resize, the canvas stays at its initial size when the browser window changes, causing clipping or empty space.
  4. What three things does the Application constructor create?

    • A renderer (projector), a stage (screen), and a ticker (clock).
  5. How do you share the same image across multiple sprites efficiently?

    • Create one Texture and pass it to multiple Sprite instances. PixiJS batches them into a single draw call.

Challenge: Build a scene with 5 sprites positioned around a circle. Each sprite should face the center. Hint: use Math.sin and Math.cos with anchor.set(0.5).

FAQ

Why does my sprite appear at the wrong position?

: Check the anchor. Default is (0,0), meaning the top-left corner. Use anchor.set(0.5) for centered positioning.

Should I use `forceCanvas`?

: Only as a last resort. WebGL is much faster. Canvas mode is useful for testing or environments without WebGL.

How do I preload multiple assets?

: Use app.loader.add(...).load(() => { /* start */ }). The loader handles queues and progress tracking.

What is the difference between `sprite.x` and `sprite.position.x`?

: They are identical. sprite.x is a shortcut for sprite.position.x.

Can I change the canvas size after creation?

: Yes. Call app.renderer.resize(newWidth, newHeight) at any time.

Try It Yourself

Open the HTML below in your browser to run a fully interactive PixiJS scene Builder. No build tools needed — just save and open.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>PixiJS Getting Started — Scene Builder</title>
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }
    body { background: #1a1a2e; font-family: system-ui, sans-serif; display: flex; justify-content: center; padding: 20px; }
    .app { display: flex; gap: 20px; flex-wrap: wrap; }
    canvas { border-radius: 12px; box-shadow: 0 8px 32px rgba(0,0,0,0.4); }
    .panel { background: #16213e; border-radius: 12px; padding: 20px; color: #fff; width: 240px; display: flex; flex-direction: column; gap: 14px; }
    .panel h2 { font-size: 18px; margin-bottom: 4px; }
    .panel label { font-size: 13px; color: #a8b2d1; }
    .panel input[type="range"] { width: 100%; accent-color: #4a90d9; }
    .panel input[type="color"] { width: 100%; height: 40px; border: none; border-radius: 6px; cursor: pointer; }
    .btn { padding: 10px; border: none; border-radius: 8px; background: #4a90d9; color: #fff; font-weight: 600; cursor: pointer; }
    .btn:hover { background: #357abd; }
    .btn.danger { background: #e63946; }
    .stats { font-size: 12px; color: #8892b0; }
  </style>
</head>
<body>
<div class="app">
  <div id="canvas-container"></div>
  <div class="panel">
    <h2>Scene Builder</h2>
    <label>Rotation <span id="rotVal">0</span>°</label>
    <input type="range" id="rotation" min="0" max="360" value="0" />
    <label>Background Color</label>
    <input type="color" id="bgColor" value="#1099bb" />
    <label>Opacity</label>
    <input type="range" id="opacity" min="0" max="1" step="0.05" value="1" />
    <button class="btn" id="addBtn">+ Add Sprite</button>
    <button class="btn danger" id="clearBtn">Clear All</button>
    <div class="stats">Sprites: <span id="spriteCount">0</span></div>
  </div>
</div>

<script src="https://cdn.jsdelivr.net/npm/pixi.js@7.x/dist/pixi.min.js"></script>
<script>
const ASSETS = [
  'https://pixijs.com/assets/bunny.png',
  'https://pixijs.com/assets/eggHead.png',
  'https://pixijs.com/assets/flowerTop.png',
  'https://pixijs.com/assets/goblin.png',
  'https://pixijs.com/assets/helix.png',
];

const app = new PIXI.Application({
  width: 800, height: 600,
  backgroundColor: 0x1099bb,
  antialias: true,
  resolution: window.devicePixelRatio || 1,
  autoDensity: true,
});

document.getElementById('canvas-container').appendChild(app.view);

let sprites = [];
let selectedIndex = 0;

function addSprite() {
  const url = ASSETS[selectedIndex % ASSETS.length];
  const sprite = new PIXI.Sprite(PIXI.Texture.from(url));
  sprite.anchor.set(0.5);
  sprite.x = Math.random() * 700 + 50;
  sprite.y = Math.random() * 500 + 50;
  sprite.scale.set(Math.random() * 1.5 + 0.5);
  sprite.rotation = Math.random() * Math.PI * 2;
  app.stage.addChild(sprite);
  sprites.push(sprite);
  document.getElementById('spriteCount').textContent = sprites.length;
  selectedIndex++;
}

document.getElementById('rotation').addEventListener('input', e => {
  const deg = parseFloat(e.target.value);
  document.getElementById('rotVal').textContent = deg;
  sprites.forEach(s => { s.rotation = (deg * Math.PI) / 180; });
});

document.getElementById('bgColor').addEventListener('input', e => {
  app.renderer.backgroundColor = parseInt(e.target.value.slice(1), 16);
});

document.getElementById('opacity').addEventListener('input', e => {
  sprites.forEach(s => { s.alpha = parseFloat(e.target.value); });
});

document.getElementById('addBtn').addEventListener('click', addSprite);
document.getElementById('clearBtn').addEventListener('click', () => {
  sprites.forEach(s => app.stage.removeChild(s));
  sprites = [];
  document.getElementById('spriteCount').textContent = 0;
});

addSprite(); addSprite(); addSprite();

window.addEventListener('resize', () => {
  const w = Math.min(window.innerWidth - 280, 800);
  const h = Math.min(window.innerHeight - 40, 600);
  app.renderer.resize(Math.max(w, 200), Math.max(h, 200));
});
</script>
</body>
</html>

What's Next

Topic Link
Drawing shapes and managing textures {{< ref "/frontend/libraries/pixijs/pixijs-graphics-textures" >}}
Animation and interactivity {{< ref "/frontend/libraries/pixijs/pixijs-animation-interactivity" >}}
WebGL rendering fundamentals WebGL Guide
Canvas 2D API basics Canvas API Tutorial

Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro. PixiJS powers real-time threat visualization in Durga Antivirus Pro's security dashboard.

What's Next

Congratulations on completing this Pixijs Getting Started tutorial! Here's where to go from here:

  • Practice daily — Consistency is more important than long study sessions
  • Build a project — Apply what you learned by building something real
  • Explore related topics — Check out other tutorials in the same category
  • Join the community — Discuss with other learners and share your progress

Remember: every expert was once a beginner. Keep coding!

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro