Resize Pixi.js App and Maintain Aspect Ratio

Creating a responsive Pixi.js application requires handling browser window resizing while preserving a specific aspect ratio. This article provides a straightforward guide and code implementation to dynamically scale your Pixi.js canvas, ensuring your visual content remains perfectly proportioned and centered across desktop and mobile screens.

1. Set Up the HTML and CSS

To ensure the Pixi.js canvas centers correctly when the window resizes, use CSS Flexbox on the parent container (usually the <body> element). This prevents scrollbars and keeps the canvas perfectly aligned.

body {
    margin: 0;
    padding: 0;
    width: 100vw;
    height: 100vh;
    background-color: #1099bb; /* Matches your app background */
    display: flex;
    justify-content: center;
    align-items: center;
    overflow: hidden;
}

canvas {
    display: block;
}

2. Implement the Resize Logic in JavaScript

To maintain the aspect ratio, you must define a logical “design resolution” (e.g., 1920x1080). When the browser window resizes, calculate whether the window is wider or taller than this aspect ratio, and scale the renderer accordingly.

Below is the complete implementation for Pixi.js:

import { Application } from 'pixi.js';

// Define the logical design dimensions
const DESIGN_WIDTH = 1920;
const DESIGN_HEIGHT = 1080;
const DESIGN_RATIO = DESIGN_WIDTH / DESIGN_HEIGHT;

// Initialize Pixi.js Application
const app = new Application();
await app.init({
    width: DESIGN_WIDTH,
    height: DESIGN_HEIGHT,
    backgroundColor: 0x1099bb,
});

// Append the canvas to the HTML body
document.body.appendChild(app.canvas);

// Resize function to calculate and apply scale
function resize() {
    const windowWidth = window.innerWidth;
    const windowHeight = window.innerHeight;
    const windowRatio = windowWidth / windowHeight;

    let newWidth, newHeight;

    // Determine orientation and scale based on window aspect ratio
    if (windowRatio > DESIGN_RATIO) {
        // Window is wider than design ratio (letterbox on left/right)
        newHeight = windowHeight;
        newWidth = windowHeight * DESIGN_RATIO;
    } else {
        // Window is taller than design ratio (letterbox on top/bottom)
        newWidth = windowWidth;
        newHeight = windowWidth / DESIGN_RATIO;
    }

    // Resize the renderer
    app.renderer.resize(newWidth, newHeight);

    // Scale the stage to fit the new dimensions
    const scale = newWidth / DESIGN_WIDTH;
    app.stage.scale.set(scale);
}

// Listen for window resize events
window.addEventListener('resize', resize);

// Run the resize logic immediately on load
resize();

How It Works

  1. Design Dimensions: By defining DESIGN_WIDTH and DESIGN_HEIGHT, you establish a fixed coordinate system. You can place your game objects using these coordinate values, and Pixi.js will scale them automatically.
  2. Aspect Ratio Comparison: The code compares the browser’s current ratio (windowRatio) to your target ratio (DESIGN_RATIO).
  3. Renderer Resizing: app.renderer.resize() changes the actual resolution of the canvas drawing buffer to match the calculated dimensions.
  4. Stage Scaling: Setting app.stage.scale.set(scale) ensures that all display objects containerized within the root stage are scaled down or up proportionally, maintaining their relative positions and sizes without distortion.