What’s New

pixijs v8.18.0

v8.18.0
Added
  • Add graphicsContextToSvg() function to export Graphics or GraphicsContext to a self-contained SVG string
  • Add mask channel selection option to setMask() to pick which texture channel (red or alpha) drives visibility
  • Allow preference parameter to accept an array of renderer types in autoDetectRenderer and Application.init
  • Add domContainerRoot getter to Application to access the HTMLDivElement wrapping DOMContainer elements
  • Add width option to MeshRope to allow explicit rope thickness decoupled from texture height
  • Add defaultAnchor option to renderer.generateTexture() and textureOptions parameter to RenderTexture.create()
Changed
  • Text/HTMLText/BitmapText with wordWrap: true and non-left align now return the true rendered width from text.width instead of reporting wordWrapWidth
Fixed
  • Text.width and word wrap returning incorrect values
  • Stroke-only Graphics masks now render correctly on Canvas renderer
  • Skip _applyMipRange for single-mip textures on iOS 18.0–18.1
  • Stale TextureMatrix when pooled textures reuse the same reference
  • Unhandled actions in GraphicsPath.transform() switch statement
  • VideoSource play/mediaReady recursion before video dimensions are known
💾 Download

Installation:

npm install pixi.js@8.18.0

Development Build:

Production Build:

Documentation:

Changed

https://github.com/pixijs/pixijs/compare/v8.17.1...v8.18.0

🚨 Behavior Change
  • fix: text.width and word wrap returning incorrect values by @Zyie in https://github.com/pixijs/pixijs/pull/12007
    • Text/HTMLText/BitmapText with wordWrap: true and non-left align (center/right/justify) now return the true rendered width from text.width instead of reporting wordWrapWidth. If you relied on text.width === wordWrapWidth for layout, use wordWrapWidth directly or wrap the text in a sized container.
    const text = new Text({
        text: 'hello',
        style: { wordWrap: true, wordWrapWidth: 800, align: 'center' },
    });
    // before: text.width === 800
    // after:  text.width reflects the rendered string width
    
🎁 Added
  • feat: add graphicsContextToSvg() for Graphics → SVG export by @GoodBoyDigital in https://github.com/pixijs/pixijs/pull/11989
    • Adds graphicsContextToSvg(source, precision?), a pure function that serializes a Graphics or GraphicsContext to a self-contained SVG string. Supports rects, circles, ellipses, rounded rects, polygons, bezier/quadratic/arc paths, strokes, holes (via fill-rule="evenodd"), and linear/radial gradients.
    import { Graphics, graphicsContextToSvg } from 'pixi.js';
    
    const g = new Graphics()
        .rect(0, 0, 100, 50)
        .fill({ color: 0xff0000 })
        .circle(150, 25, 25)
        .stroke({ color: 0x0000ff, width: 4 });
    
    const svgString = graphicsContextToSvg(g, 2);
    await navigator.clipboard.writeText(svgString);
    
  • feat: add mask channel selection for sprite masks by @Zyie in https://github.com/pixijs/pixijs/pull/11987
    • setMask() gains a channel option ('red' | 'alpha') to pick which texture channel drives visibility, matching how design tools like Figma apply PNG masks. Default remains 'red'.
    import { Assets, Sprite } from 'pixi.js';
    
    const photo = new Sprite(await Assets.load('photo.png'));
    const maskSprite = new Sprite(await Assets.load('mask-alpha.png'));
    
    photo.setMask({
        mask: maskSprite,
        channel: 'alpha',
    });
    
  • feat: allow preference to accept an array of renderer types by @Zyie in https://github.com/pixijs/pixijs/pull/11963
    • autoDetectRenderer and Application.init now accept an array of renderer names for preference, letting you restrict the fallback chain (e.g. disable WebGPU entirely) rather than only reorder it. A new RendererPreference type is exported.
    import { Application, autoDetectRenderer } from 'pixi.js';
    
    const renderer = await autoDetectRenderer({
        preference: ['webgl', 'canvas'],
    });
    
    const app = new Application();
    await app.init({ preference: ['webgl', 'canvas'] });
    
  • feat: provide a getter to the domElement via app.domContainerRoot by @carlos22 in https://github.com/pixijs/pixijs/pull/11974
    • Application exposes a read-only domContainerRoot getter returning the HTMLDivElement that wraps all DOMContainer elements, so apps can add CSS classes, inline styles, or customize the DOM overlay root.
    import { Application } from 'pixi.js';
    
    const app = new Application();
    await app.init({ resizeTo: window });
    
    app.domContainerRoot.classList.add('pixi-dom-layer');
    app.domContainerRoot.style.pointerEvents = 'auto';
    
  • feat: add width option to MeshRope by @mehmetcanakbay in https://github.com/pixijs/pixijs/pull/11990
    • MeshRope now accepts an explicit width for rope thickness, decoupling it from the texture's height. Omitting width preserves the previous texture.height default.
    import { MeshRope, Point, Texture } from 'pixi.js';
    
    const points = [new Point(0, 0), new Point(100, 50), new Point(200, 0)];
    
    const rope = new MeshRope({
        texture: Texture.from('snake.png'),
        points,
        width: 40,
    });
    
  • feat: add a default anchor to texture generation by @ksv90 in https://github.com/pixijs/pixijs/pull/12011
    • renderer.generateTexture() accepts a defaultAnchor option that's forwarded onto the produced Texture. RenderTexture.create() also gains a textureOptions parameter to pass through fields like defaultAnchor to the underlying Texture.
    import { Graphics, Sprite } from 'pixi.js';
    
    const shape = new Graphics().circle(0, 0, 50).fill(0xff3366);
    
    const texture = app.renderer.generateTexture({
        target: shape,
        defaultAnchor: { x: 0.5, y: 0.5 },
    });
    
    const sprite = new Sprite(texture);
    sprite.position.set(200, 200); // centered by default
    
🐛 Fixed
🧹 Chores
New Contributors
View original