PixiJS Layers (@pixi/layers)

repository·main·Indexed 42 days ago

https://github.com/pixijs-userland/layers

A high-performance layering system for PixiJS version 2.1.0 that decouples rendering order from the scene graph hierarchy. It enables advanced depth management, Y-sorting via zOrder, and the use of Layers and Groups to control object rendering independently of their position in the scene tree.

Tokens
4.6K
Snippets
19
Records
24
Agent score
53%

What's inside PixiJS Layers

  1. How to use Layers and Groups

    main

    The core concept of @pixi/layers is to decouple the scene tree hierarchy from the rendering order.

    1. Create a Layer: A Layer extends PIXI.Container and acts as a rendering bucket.
    2. Assign Objects to Layers: Instead of using standard parent-child relationships for rendering order, assign a parentLayer to a DisplayObject or Container.
    3. Use Groups for Cross-Stage Logic: A Group defines a logical collection of objects. A Layer can be bound to a Group. This allows objects to maintain their logical grouping even if they move between different Stage instances.

    Critical Requirement: You must create a Stage and set it as your scene's root for the library to function correctly.

    import { Layer, Group } from '@pixi/layers';
    
    // Basic Layer usage
    const layer = new Layer();
    const bunnySprite = PIXI.Sprite.from('bunny.png');
    
    // Assign sprite to render inside the layer instead of its direct parent
    bunnySprite.parentLayer = layer;
    
    // Using Groups for persistent logical grouping
    const lightGroup = new Group();
    bunnySprite.parentGroup = lightGroup;
    const lightLayer = new Layer(lightGroup); // Only one layer per stage can be bound to the same group
  2. Apply mixins for Canvas and Particles

    main

    If you are using specific PixiJS renderers or containers, you must apply the corresponding mixin to ensure compatibility. This should be called once the modules are loaded.

    // For @pixi/canvas-renderer
    import { CanvasRenderer } from 'pixi.js-legacy';
    import { applyCanvasMixin } from '@pixi/layers';
    applyCanvasMixin(CanvasRenderer);
    
    // For @pixi/particles
    import { ParticleContainer } from 'pixi.js';
    import { applyParticleMixin } from '@pixi/layers';
    applyParticleMixin(ParticleContainer);
  3. Use the Layer class to manage rendering order

    main

    A Layer is a specialized Container used to group DisplayObjects that should be rendered together, separate from the standard scene graph hierarchy. This allows you to manage z-ordering and rendering logic in a data-oriented way.

    Key characteristics:

    • Each Layer is associated with a Group which defines its sorting and rendering context.
    • Layers should be placed under a Stage (the recommended scene root).
    • You can use a Layer as a texture by enabling useRenderTexture on its associated group.
    • You can enable double buffering via useDoubleBuffer to prevent flickering when using render textures.
    import { Layer } from '@pixi/layers';
    import { Group } from './Group'; // Assuming Group is available
    
    // Create a group to define the layer's behavior
    const group = new Group(0, false);
    const layer = new Layer(group);
    
    // Add the layer to your stage
    stage.addChild(layer);
    
    // Add objects to the layer's group to have them rendered within this layer
    layer.addChild(mySprite);
  4. Initialize @pixi/layers via mixins

    main

    To use @pixi/layers, the library must apply mixins to the PixiJS base classes. This adds layer-specific properties like parentGroup, parentLayer, and zOrder to standard PixiJS DisplayObject instances. The library automatically calls applyDisplayMixin() and applyRendererMixin(Renderer) upon import, but you can also manually import and apply specific mixins for granular control.

    import { applyDisplayMixin, applyRendererMixin, applyParticleMixin, applyCanvasMixin, applyContainerRenderMixin } from '@pixi/layers';
    import { Renderer } from '@pixi/core';
    
    // Standard initialization (usually handled by the package entrypoint)
    applyDisplayMixin();
    applyRendererMixin(Renderer);
    
    // Additional mixins available for specific use cases
    applyParticleMixin();
    applyCanvasMixin();
    applyContainerRenderMixin();
  5. Fixing Filter and Mask issues on Layers

    main

    Because layer.getBounds() does not automatically account for active children, filters or stencil masks applied directly to a Layer may not work as expected.

    Use one of these three workarounds:

    1. Set a filterArea: Manually define the global screen rectangle: layer.filterArea = renderer.screen.
    2. Add a dummy child: Add a Graphics rectangle of the desired size with alpha = 0 inside the layer.
    3. Override calculateBounds: Manually override the calculateBounds method to include _activeChildren.
  6. Configure Z-Order sorting within a Layer

    main

    Layers can sort elements internally based on a zOrder property. To enable this, you must set enableSort = true on the layer's group.

    To dynamically set the sort order (e.g., based on the Y position for a pseudo-3D effect), listen to the sort event emitted by the layer.group.

    // Enable sorting in the layer
    layer.group.enableSort = true;
    
    // Set specific zOrders
    bunnySprite.zOrder = 2;
    cloudSprite.zOrder = 1;
    
    // Intercept the sort event to set zOrder dynamically (e.g., Y-sorting)
    layer.group.on('sort', function onWillSort(sprite) {
        sprite.zOrder = sprite.y; 
    });
  7. Update the Stage and check sorted children

    main

    Because @pixi/layers uses a mixin on PIXI.Renderer, it automatically calls updateStage() during the render loop. However, if you need to inspect the sorted order manually before or after rendering, you can call stage.updateStage().

    After updating, you can inspect layer._sortedChildren to see the actual rendering sequence.

    // Manually update the stage to refresh layers
    stage.updateStage();
    
    // Check the rendering order
    console.log(layer._sortedChildren);
    
    // Alternatively, after a standard render call:
    renderer.render(stage);
    console.log(layer._sortedChildren);
  8. Apply Mixin to ParticleContainer

    main

    To enable layer support for a ParticleContainer, use applyParticleMixin. This function sets layerableChildren to false on the ParticleContainer prototype and applies the container render mixin to ensure compatibility with the layering system.

    import { applyParticleMixin } from '@pixi/layers';
    
    // Assuming ParticleContainer is your particle container class
    applyParticleMixin(ParticleContainer);
  9. Clean up Stage resources with clear() and destroy()

    main

    To prevent memory leaks and garbage collection issues, you should manually clear the internal display lists used during the last rendering session when you stop using a specific display list.

    • clear(): Resets internal active layers and temporary groups.
    • destroy(options?): Clears internal state and then calls the superclass destroy method.
    stage.clear();
    // or
    stage.destroy();
  10. Apply the Renderer Mixin to PixiJS Renderer

    main

    When using @pixi/layers, the Renderer class is automatically extended with layering capabilities. However, if you are working with custom renderer implementations or need to ensure the mixin is applied, you can use applyRendererMixin. This adds internal properties like _lastDisplayOrder and _activeLayer to the renderer to track layering state during the render cycle.

    import { Renderer } from '@pixi/core';
    import { applyRendererMixin } from '@pixi/layers';
    
    applyRendererMixin(Renderer);
  11. Destroy a Layer and its resources

    main

    When a Layer is no longer needed, call destroy(). This will automatically destroy the associated LayerTextureCache and any RenderTextures (including double buffers) used by the layer, preventing memory leaks. You can pass IDestroyOptions to the method as per standard PixiJS DisplayObject behavior.

    layer.destroy();