Pixi.js NineSlicePlane Guide for Scalable UI

When building user interfaces in Pixi.js, scaling assets without stretching their borders or corners is a common challenge. This article explores the role of the NineSlicePlane class, explaining how it enables developers to create scalable UI elements—such as buttons, panels, and dialogue boxes—while preserving their visual integrity. We will examine the mechanics of nine-slice scaling, how it optimizes rendering performance, and how to implement it directly in your Pixi.js projects.

Understanding Nine-Slice Scaling

Nine-slice scaling (also known as 9-slicing) is a 2D texture resizing technique that splits an image into a grid of nine regions: four corners, four edges, and one center.

When the UI element is resized: * The Corners (top-left, top-right, bottom-left, bottom-right) remain entirely unscaled, preserving their original proportions and sharpness. * The Horizontal Edges (top, bottom) scale only along the horizontal (X) axis. * The Vertical Edges (left, right) scale only along the vertical (Y) axis. * The Center scales in both directions to fill the remaining space.

This technique prevents rounded corners from becoming distorted or pixelated when a UI element is stretched to fit different screen sizes or dynamic content.

The Role of NineSlicePlane in Pixi.js

In Pixi.js, the NineSlicePlane class inherits from SimplePlane and is specifically designed to handle this 9-way grid segmentation. Rather than requiring developers to manually split an image into nine separate sprite objects—which complicates positioning and increases draw calls—NineSlicePlane manages this process internally as a single mesh.

1. Maintaining Visual Fidelity

Without nine-slice scaling, scaling a rounded rectangle button horizontally causes the rounded corners to stretch oval-shaped and blurry. NineSlicePlane ensures that corner radiuses, borders, and bevels retain their exact dimensions, regardless of how wide or tall the final UI component becomes.

2. Performance Optimization

By utilizing a single WebGL mesh, NineSlicePlane groups the vertices of the nine sliced regions into one renderable object. This minimizes CPU overhead and helps keep the GPU draw call count low, which is crucial for maintaining a high framerate in graphics-intensive web applications and games.

3. Reducing Asset Load Times

Instead of creating dozens of UI graphics of varying dimensions (e.g., separate assets for small, medium, and large panels), developers can load a single, tiny base texture. This base texture can be scaled dynamically to any dimension in real-time, significantly reducing the project’s overall bundle size and loading times.

How to Implement NineSlicePlane

To create a NineSlicePlane, you define the source texture and the width/height of the padding margins for the corners.

import * as PIXI from 'pixi.js';

// Load the button texture
const texture = PIXI.Texture.from('button_template.png');

// Define the corner margins: left, top, right, bottom (in pixels)
const leftMargin = 15;
const topMargin = 15;
const rightMargin = 15;
const bottomMargin = 15;

// Create the NineSlicePlane instance
const scalableButton = new PIXI.NineSlicePlane(
    texture, 
    leftMargin, 
    topMargin, 
    rightMargin, 
    bottomMargin
);

// Set the desired dimensions
scalableButton.width = 300;
scalableButton.height = 80;

// Add to the stage
app.stage.addChild(scalableButton);

In this implementation, the 15-pixel border on all four sides of the button_template.png texture will remain unscaled, while the interior of the button stretches to fill the rest of the 300x80 area.

Key Properties for Dynamic UI Layouts

The NineSlicePlane class provides properties that make responsive UI design straightforward: