pixi.js
    Preparing search index...

    Graphics

    Graphics renders shapes such as rectangles, circles, stars, and custom polygons. You can combine multiple primitives into complex shapes, and it supports gradients, textures, and masks.

    import { Graphics } from 'pixi.js';

    const graphics = new Graphics().rect(50, 50, 100, 100).fill(0xff0000);

    PixiJS v8 supports these shape primitives:

    • Line
    • Rectangle
    • Rounded Rectangle
    • Circle
    • Ellipse
    • Arc
    • Bezier / Quadratic Curves
    • Chamfer Rect
    • Fillet Rect
    • Regular Polygon
    • Star
    • Rounded Polygon
    • Rounded Shape
    const graphics = new Graphics()
    .rect(50, 50, 100, 100)
    .fill(0xff0000)
    .circle(200, 200, 50)
    .stroke(0x00ff00)
    .moveTo(300, 300)
    .lineTo(400, 400)
    .stroke({ width: 5 });

    You can load SVG path data, though complex hole geometries may render inaccurately due to Pixi's performance-optimized triangulation system.

    let shape = new Graphics().svg(`
    <svg>
    <path d="M 100 350 q 150 -300 300 0" stroke="blue" />
    </svg>
    `);

    GraphicsContext is the core of the PixiJS graphics model. It holds all drawing commands and styles, allowing the same shape data to be reused by multiple Graphics instances:

    const context = new GraphicsContext().circle(100, 100, 50).fill('red');

    const shapeA = new Graphics(context);
    const shapeB = new Graphics(context); // Shares the same geometry

    This pattern is effective when rendering repeated or animated shapes, such as frame-based SVG swaps:

    let frames = [
    new GraphicsContext().circle(100, 100, 50).fill('red'),
    new GraphicsContext().rect(0, 0, 100, 100).fill('red'),
    ];

    let graphic = new Graphics(frames[0]);

    function update() {
    graphic.context = frames[1]; // Very cheap operation
    }
    Note

    If you don't explicitly pass a GraphicsContext when creating a Graphics object, then internally, it will have its own context, accessible via myGraphics.context.

    Destroying a GraphicsContext also destroys all Graphics instances that share it.

    const context = new GraphicsContext().circle(100, 100, 50).fill('red');
    const shapeA = new Graphics(context);
    const shapeB = new Graphics(context); // Shares the same geometry

    shapeA.destroy({ context: true }); // Destroys both shapeA and shapeB

    Use .cut() to remove a shape from the previous one:

    const g = new Graphics().rect(0, 0, 100, 100).fill(0x00ff00).circle(50, 50, 20).cut(); // Creates a hole in the green rectangle
    

    Ensure the hole is fully enclosed within the shape to avoid triangulation errors.

    Methods like .rect() and .circle() don't render anything. They build a list of shapes stored in a GraphicsContext. Rendering happens when the Graphics object is added to the scene and the renderer processes it.

    const graphic = new Graphics().rect(0, 0, 200, 100).fill(0xff0000);

    app.stage.addChild(graphic); // Rendering happens here

    This means you can build, reuse, and transform Graphics objects freely without triggering GPU work.

    • Do not call .clear() and rebuild every frame. Rebuilding triggers geometry re-triangulation on the CPU. For dynamic content, swap prebuilt GraphicsContext objects instead (see the context-swapping example above).
    • Use Graphics.destroy() to clean up when done. Shared contexts are not auto-destroyed.
    • Use many simple Graphics objects over one complex one to maintain GPU batching.
    • Overlapping semi-transparent shapes blend individually. Each shape is drawn and blended in order, so two 50%-transparent overlapping circles will look different than a single 50%-transparent merged shape. To blend the entire Graphics as one unit, render it to a texture first via cacheAsTexture() or renderer.generateTexture().
    • Memory leaks: Call .destroy() when no longer needed.
    • SVG and holes: Not all SVG hole paths triangulate correctly.
    • Changing geometry: Use .clear() sparingly. Prefer swapping contexts.
    • Transparency and blend modes: These apply per primitive. Use RenderTexture to flatten effects.
    • Empty Graphics bounds: A Graphics object with no drawing instructions returns bounds of (0, 0, 0, 0). This prevents Infinity values from contaminating parent container bounds calculations.