# PixiJS Documentation for LLMs
> PixiJS is the fastest, most lightweight 2D library available for the web, working across all devices and allowing you to create rich, interactive graphics and cross-platform applications using WebGL and WebGPU.
This file contains all documentation content in a single document following the llmtxt.org standard.
## Ecosystem
PixiJS itself is just a rendering engine. However, there is a foundation of a robust ecosystem of libraries and tools that enhance and expand its capabilities. These tools integrate seamlessly with PixiJS, empowering developers to create richer, more interactive applications with ease.
## Core Ecosystem Libraries
### [DevTools](https://pixijs.io/devtools/)
Optimize and debug your PixiJS projects with DevTools. This browser extension offers real-time insights into application performance, rendering hierarchies, and texture management, ensuring your projects run smoothly.
### [React Integration](https:/react.pixijs.io/)
:::info
PixiJS React requires React 19 or higher.
:::
Simplify the use of PixiJS in React applications with the Pixi-React library. This library provides bindings that allow you to manage PixiJS components as React elements, making it easy to incorporate powerful graphics into React's declarative framework.
### [Layout](https://layout.pixijs.io/)
Add flexbox-style layouting to PixiJS with the PixiJS Layout library, which is powered by Facebook’s [Yoga](https://www.yogalayout.dev/) engine. It introduces a declarative way to control positioning, alignment, and sizing of PixiJS display objects using familiar CSS-like rules.
Key features include:
- Built on Yoga for standardized, reliable layouts
- Fully opt-in: apply layout only where you need it
- Any PixiJS object can now be layout-aware
- Supports PixiJS React
- New web-style features: objectFit, objectPosition, and overflow scrolling
### [Spine Integration](https://esotericsoftware.com/spine-pixi)
Bring animations to life with Spine-Pixi. This integration combines the power of PixiJS and Spine, a leading animation tool, to create smooth, skeletal-based animations for games and interactive content.
### [Filters](https://github.com/pixijs/filters)
Transform your visuals with PixiJS Filters. This extensive collection of high-performance effects includes options like blur, glow, and color adjustments, giving you the tools to create visually stunning graphics.
### [Sound](https://github.com/pixijs/sound)
Add audio to your projects with PixiJS Sound a WebAudio API playback library, with filters.
### [UI](https://github.com/pixijs/ui)
Streamline the creation of user interfaces with PixiJS UI. This library offers pre-built components:
- Buttons
- Sliders
- Progress bars
- Lists
- Scrollbox
- Radio Groups
- Checkboxes
- Switches
All the essentials for building interactive interfaces in PixiJS.
### [AssetPack](https://pixijs.io/assetpack/)
Simplify asset management with AssetPack. This tool organizes, packages, and loads assets efficiently, reducing load times and improving resource handling for your projects.
## [PixiJS Userland](https://github.com/pixijs-userland) - Community-Driven Repositories
PixiJS Userland is a dedicated space for hosting community-driven repositories. This organization allows developers to collaborate on PixiJS-related projects and share their work with the wider community.
If you have an idea for a new library or tool, you can request access to PixiJS Userland to create and maintain a repository within the organization. This is a great opportunity to contribute to the growing PixiJS ecosystem and engage with like-minded developers.
Note that userland repositories are community-driven and may not be up to date with the latest PixiJS releases. However, they offer a wealth of resources and inspiration for developers looking to enhance their PixiJS projects.
## Getting Started with the Ecosystem
To explore these libraries, visit their respective documentation and GitHub repositories for installation instructions and usage guides. Additionally, PixiJS offers [**Creation Templates**](https://pixijs.io/create-pixi/docs/guide/creations/intro/) through the [PixiJS Create CLI](https://pixijs.io/create-pixi/) that combine many of these libraries into pre-configured setups, ideal for specific use cases and platforms.
For inspiration, you can also check out the [open-games repository](https://github.com/pixijs/open-games), which showcases a variety of games built with PixiJS and its ecosystem libraries.
---
## Quick Start
# Quick Start
---
## Try PixiJS Online
- To quickly get a taste of PixiJS, you can try it directly in our [PixiJS Playground](/8.x/playground).
---
## Creating a New Project
:::info[Prerequisites]
- Familiarity with the command line and a basic understanding of JavaScript.
- Install [Node.js](https://nodejs.org/en/) v20.0 or higher.
:::
In this section, we will introduce how to scaffold a PixiJS application on your local machine. The created project will use a pre-configured build setup, allowing you to quickly get started with PixiJS development.
Make sure your current working directory is where you want to create your project. Run the following command in your terminal:
```sh
npm create pixi.js@latest
```
This command will install and execute the [PixiJS Create](https://pixijs.io/create-pixi/) CLI and begin scaffolding your project. You will be prompted to configure your project by selecting various options, including selecting a template type for setting up your project. There are two main types of templates to choose from:
#### Creation Templates (Recommended)
Creation templates are tailored for specific platforms and include additional configurations and dependencies to streamline development for a particular use case. These templates are more opinionated and are perfect for beginners or those looking for a ready-to-go setup.
#### Bundler Templates
Bundler templates are general templates designed to scaffold a PixiJS project with a specific bundler. They include the necessary configurations and dependencies but leave the project structure flexible, making them ideal for experienced developers who prefer more control.
We recommended using the Vite + PixiJS template for most projects when using bundler templates, as it provides a modern and fast setup for PixiJS applications with minimal configuration.
After selecting your desired template, the scaffolding tool will create a new project directory with the chosen configuration. Navigate to the project directory and install the dependencies:
```bash
cd
npm install
npm run dev
```
You can also add PixiJS to an existing project:
```bash
npm install pixi.js
```
## Usage
Once you've set up your project, here's a simple example to get started with PixiJS:
```ts
import { Application, Assets, Container, Sprite } from 'pixi.js';
(async () => {
// Create a new application
const app = new Application();
// Initialize the application
await app.init({ background: '#1099bb', resizeTo: window });
// Append the application canvas to the document body
document.body.appendChild(app.canvas);
// Create and add a container to the stage
const container = new Container();
app.stage.addChild(container);
// Load the bunny texture
const texture = await Assets.load('https://pixijs.com/assets/bunny.png');
// Create a 5x5 grid of bunnies in the container
for (let i = 0; i < 25; i++) {
const bunny = new Sprite(texture);
bunny.x = (i % 5) * 40;
bunny.y = Math.floor(i / 5) * 40;
container.addChild(bunny);
}
// Move the container to the center
container.x = app.screen.width / 2;
container.y = app.screen.height / 2;
// Center the bunny sprites in local container coordinates
container.pivot.x = container.width / 2;
container.pivot.y = container.height / 2;
// Listen for animate update
app.ticker.add((time) => {
// Continuously rotate the container!
// * use delta to create frame-independent transform *
container.rotation -= 0.01 * time.deltaTime;
});
})();
```
:::warning
If using Vite you still need to wrap your code in an async function. There is an issue when using top level await with PixiJS when building for production.
This issue is known to affect Vite \<=6.0.6. Future versions of Vite may resolve this issue.
:::
---
## Architecture
# Architecture
Here's a list of the major components that make up PixiJS. Note that this list isn't exhaustive. Additionally, don't worry too much about how each component works. The goal here is to give you a feel for what's under the hood as we start exploring the engine.
### Major Components
| Component | Description |
| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Renderer** | The core of the PixiJS system is the renderer, which displays the scene graph and draws it to the screen. PixiJS will automatically determine whether to provide you the WebGPU or WebGL renderer under the hood. |
| **Container** | Main scene object which creates a scene graph: the tree of renderable objects to be displayed, such as sprites, graphics and text. See [Scene Graph](scene-graph) for more details. |
| **Assets** | The Asset system provides tools for asynchronously loading resources such as images and audio files. |
| **Ticker** | Tickers provide periodic callbacks based on a clock. Your game update logic will generally be run in response to a tick once per frame. You can have multiple tickers in use at one time. |
| **Application** | The Application is a simple helper that wraps a Loader, Ticker and Renderer into a single, convenient easy-to-use object. Great for getting started quickly, prototyping and building simple projects. |
| **Events** | PixiJS supports pointer-based interaction - making objects clickable, firing hover events, etc. |
| **Accessibility** | Woven through our display system is a rich set of tools for enabling keyboard and screen-reader accessibility. |
| **Filters** | PixiJS supports a variety of filters, including custom shaders, to apply effects to your renderable objects. |
## Extensions
PixiJS v8 is built entirely around the concept of extensions. Every system in PixiJS is implemented as a modular extension. This allows PixiJS to remain lightweight, flexible, and easy to extend.
:::info
In most cases, you won’t need to interact with the extension system directly unless you are developing a third-party library or contributing to the PixiJS ecosystem itself.
:::
## Extension Types
PixiJS supports a wide range of extension types, each serving a unique role in the architecture:
### Assets
- `ExtensionType.Asset`: Groups together loaders, resolvers, cache and detection extensions into one convenient object instead of having to register each one separately.
- `ExtensionType.LoadParser`: Loads resources like images, JSON, videos.
- `ExtensionType.ResolveParser`: Converts asset URLs into a format that can be used by the loader.
- `ExtensionType.CacheParser`: Determines caching behavior for a particular asset.
- `ExtensionType.DetectionParser`: Identifies asset format support on the current platform.
### Renderer (WebGL, WebGPU, Canvas)
- `ExtensionType.WebGLSystem`, `ExtensionType.WebGPUSystem`, `ExtensionType.CanvasSystem`: Add systems to their respective renderers. These systems can vary widely in functionality, from managing textures to accessibility features.
- `ExtensionType.WebGLPipes`, `ExtensionType.WebGPUPipes`, `ExtensionType.CanvasPipes`: Add a new rendering pipe. RenderPipes are specifically used to render Renderables like a Mesh
- `ExtensionType.WebGLPipesAdaptor`, `ExtensionType.WebGPUPipesAdaptor`, `ExtensionType.CanvasPipesAdaptor`: Adapt rendering pipes for the respective renderers.
### Application
- `ExtensionType.Application`: Used for plugins that extend the `Application` lifecycle.
For example the `TickerPlugin` and `ResizePlugin` are both application extensions.
### Environment
- `ExtensionType.Environment`: Used to detect and configure platform-specific behavior. This can be useful for configuring PixiJS to work in environments like Node.js, Web Workers, or the browser.
### Other (Primarily Internal Use)
These extension types are mainly used internally and are typically not required in most user-facing applications:
- `ExtensionType.MaskEffect`: Used by MaskEffectManager for custom masking behaviors.
- `ExtensionType.BlendMode`: A type of extension for creating a new advanced blend mode.
- `ExtensionType.TextureSource`: A type of extension that will be used to auto detect a resource type E.g `VideoSource`
- `ExtensionType.ShapeBuilder`: A type of extension for building and triangulating custom shapes used in graphics.
- `ExtensionType.Batcher`: A type of extension for creating custom batchers used in rendering.
## Creating Extensions
The `extensions` object in PixiJS is a global registry for managing extensions. Extensions must declare an `extension` field with metadata, and are registered via `extensions.add(...)`.
```ts
import { extensions, ExtensionType } from 'pixi.js';
const myLoader = {
extension: {
type: ExtensionType.LoadParser,
name: 'my-loader',
},
test(url) {
/* logic */
},
load(url) {
/* logic */
},
};
extensions.add(myLoader);
```
---
## Environments
# Using PixiJS in Different Environments
PixiJS is a highly adaptable library that can run in a variety of environments, including browsers, Web Workers, and custom execution contexts like Node.js. This guide explains how PixiJS handles different environments and how you can configure it to suit your application's needs.
## Running PixiJS in the Browser
For browser environments, PixiJS uses the `BrowserAdapter` by default, you should not need to configure anything
### Example:
```typescript
import { Application } from 'pixi.js';
const app = new Application();
await app.init({
width: 800,
height: 600,
});
document.body.appendChild(app.canvas);
```
## Running PixiJS in Web Workers
Web Workers provide a parallel execution environment, ideal for offloading rendering tasks. PixiJS supports Web Workers using the `WebWorkerAdapter`:
### Example:
```typescript
import { DOMAdapter, WebWorkerAdapter } from 'pixi.js';
// Must be set before creating anything in PixiJS
DOMAdapter.set(WebWorkerAdapter);
const app = new Application();
await app.init({
width: 800,
height: 600,
});
app.canvas; // OffscreenCanvas
```
## Custom Environments
For non-standard environments, you can create a custom adapter by implementing the `Adapter` interface. This allows PixiJS to function in environments like Node.js or headless testing setups.
### Example Custom Adapter:
```typescript
import { DOMAdapter } from 'pixi.js';
const CustomAdapter = {
createCanvas: (width, height) => {
/* custom implementation */
},
getCanvasRenderingContext2D: () => {
/* custom implementation */
},
getWebGLRenderingContext: () => {
/* custom implementation */
},
getNavigator: () => ({ userAgent: 'Custom', gpu: null }),
getBaseUrl: () => 'custom://',
fetch: async (url, options) => {
/* custom fetch */
},
parseXML: (xml) => {
/* custom XML parser */
},
};
DOMAdapter.set(CustomAdapter);
```
---
## Garbage Collection
# Managing Garbage Collection in PixiJS
Efficient resource management is crucial for maintaining optimal performance in any PixiJS application. This guide explores how PixiJS handles garbage collection, the tools it provides, and best practices for managing GPU resources effectively.
## Explicit Resource Management with `destroy`
PixiJS objects, such as textures, meshes, and other GPU-backed data, hold references that consume memory. To explicitly release these resources, call the `destroy` method on objects you no longer need. For example:
```javascript
import { Sprite } from 'pixi.js';
const sprite = new Sprite(texture);
// Use the sprite in your application
// When no longer needed
sprite.destroy();
```
Calling `destroy` ensures that the object’s GPU resources are freed immediately, reducing the likelihood of memory leaks and improving performance.
## Managing Textures with `texture.unload`
In cases where PixiJS’s automatic texture garbage collection is insufficient, you can manually unload textures from the GPU using `texture.unload()`:
```javascript
import { Texture } from 'pixi.js';
const texture = Texture.from('image.png');
// Use the texture
// When no longer needed
texture.unload();
```
This is particularly useful for applications that dynamically load large numbers of textures and require precise memory control.
## Automatic Texture Garbage Collection with `TextureGCSystem`
PixiJS also includes the `TextureGCSystem`, a system that manages GPU texture memory. By default:
- **Removes textures unused for 3600 frames** (approximately 1 hour at 60 FPS).
- **Checks every 600 frames** for unused textures.
### Customizing `TextureGCSystem`
You can adjust the behavior of `TextureGCSystem` to suit your application:
- **`textureGCActive`**: Enable or disable garbage collection. Default: `true`.
- **`textureGCMaxIdle`**: Maximum idle frames before texture cleanup. Default: `3600` frames.
- **`textureGCCheckCountMax`**: Frequency of garbage collection checks (in frames). Default: `600` frames.
Example configuration:
```javascript
import { Application } from 'pixi.js';
const app = new Application();
await app.init({
textureGCActive: true, // Enable texture garbage collection
textureGCMaxIdle: 7200, // 2 hours idle time
textureGCCheckCountMax: 1200, // Check every 20 seconds at 60 FPS
});
```
## Best Practices for Garbage Collection in PixiJS
1. **Explicitly Destroy Objects:** Always call `destroy` on objects you no longer need to ensure GPU resources are promptly released.
2. **Use Pooling:** Reuse objects with a pooling system to reduce allocation and deallocation overhead.
3. **Proactively Manage Textures:** Use `texture.unload()` for manual memory management when necessary.
By following these practices and understanding PixiJS’s garbage collection mechanisms, you can create high-performance applications that efficiently utilize system resources.
---
## Performance Tips
# Performance Tips
### General
- Only optimize when you need to! PixiJS can handle a fair amount of content off the bat
- Be mindful of the complexity of your scene. The more objects you add the slower things will end up
- Order can help, for example sprite / graphic / sprite / graphic is slower than sprite / sprite / graphic / graphic
- Some older mobile devices run things a little slower. Passing in the option `useContextAlpha: false` and `antialias: false` to the Renderer or Application can help with performance
- Culling is disabled by default as it's often better to do this at an application level or set objects to be `cullable = true`. If you are GPU-bound it will improve performance; if you are CPU-bound it will degrade performance
### Sprites
- Use Spritesheets where possible to minimize total textures
- Sprites can be batched with up to 16 different textures (dependent on hardware)
- This is the fastest way to render content
- On older devices use smaller low resolution textures
- Add the extention `@0.5x.png` to the 50% scale-down spritesheet so PixiJS will visually-double them automatically
- Draw order can be important
### Graphics
- Graphics objects are fastest when they are not modified constantly (not including the transform, alpha or tint!)
- Graphics objects are batched when under a certain size (100 points or smaller)
- Small Graphics objects are as fast as Sprites (rectangles, triangles)
- Using 100s of graphics complex objects can be slow, in this instance use sprites (you can create a texture)
### Texture
- Textures are automatically managed by a Texture Garbage Collector
- You can also manage them yourself by using `texture.destroy()`
- If you plan to destroy more than one at once add a random delay to their destruction to remove freezing
- Delay texture destroy if you plan to delete a lot of textures yourself
### Text
- Avoid changing it on every frame as this can be expensive (each time it draws to a canvas and then uploads to GPU)
- Bitmap Text gives much better performance for dynamically changing text
- Text resolution matches the renderer resolution, decrease resolution yourself by setting the `resolution` property, which can consume less memory
### Masks
- Masks can be expensive if too many are used: e.g., 100s of masks will really slow things down
- Axis-aligned Rectangle masks are the fastest (as they use scissor rect)
- Graphics masks are second fastest (as they use the stencil buffer)
- Sprite masks are the third fastest (they use filters). They are really expensive. Do not use too many in your scene!
### Filters
- Release memory: `container.filters = null`
- If you know the size of them: `container.filterArea = new Rectangle(x,y,w,h)`. This can speed things up as it means the object does not need to be measured
- Filters are expensive, using too many will start to slow things down!
### BlendModes
- Different blend modes will cause batches to break (de-optimize)
- ScreenSprite / NormalSprite / ScreenSprite / NormalSprite would be 4 draw calls
- ScreenSprite / ScreenSprite / NormalSprite / NormalSprite would be 2 draw calls
### Events
- If an object has no interactive children use `interactiveChildren = false`. The event system will then be able to avoid crawling through the object
- Setting `hitArea = new Rectangle(x,y,w,h)` as above should stop the event system from crawling through the object
---
## Render Groups
# Render Groups
## Understanding RenderGroups in PixiJS
As you delve deeper into PixiJS, especially with version 8, you'll encounter a powerful feature known as RenderGroups. Think of RenderGroups as specialized containers within your scene graph that act like mini scene graphs themselves. Here's what you need to know to effectively use Render Groups in your projects:
### What Are Render Groups?
Render Groups are essentially containers that PixiJS treats as self-contained scene graphs. When you assign parts of your scene to a Render Group, you're telling PixiJS to manage these objects together as a unit. This management includes monitoring for changes and preparing a set of render instructions specifically for the group. This is a powerful tool for optimizing your rendering process.
### Why Use Render Groups?
The main advantage of using Render Groups lies in their optimization capabilities. They allow for certain calculations, like transformations (position, scale, rotation), tint, and alpha adjustments, to be offloaded to the GPU. This means that operations like moving or adjusting the Render Group can be done with minimal CPU impact, making your application more performance-efficient.
In practice, you're utilizing Render Groups even without explicit awareness. The root element you pass to the render function in PixiJS is automatically converted into a RenderGroup as this is where its render instructions will be stored. Though you also have the option to explicitly create additional RenderGroups as needed to further optimize your project.
This feature is particularly beneficial for:
- **Static Content:** For content that doesn't change often, a Render Group can significantly reduce the computational load on the CPU. In this case static refers to the scene graph structure, not that actual values of the PixiJS elements inside it (eg position, scale of things).
- **Distinct Scene Parts:** You can separate your scene into logical parts, such as the game world and the HUD (Heads-Up Display). Each part can be optimized individually, leading to overall better performance.
### Examples
```ts
const myGameWorld = new Container({
isRenderGroup: true,
});
const myHud = new Container({
isRenderGroup: true,
});
scene.addChild(myGameWorld, myHud);
renderer.render(scene); // this action will actually convert the scene to a render group under the hood
```
Check out the [container example](../../examples/basic/container).
### Best Practices
- **Don't Overuse:** While Render Groups are powerful, using too many can actually degrade performance. The goal is to find a balance that optimizes rendering without overwhelming the system with too many separate groups. Make sure to profile when using them. The majority of the time you won't need to use them at all!
- **Strategic Grouping:** Consider what parts of your scene change together and which parts remain static. Grouping dynamic elements separately from static elements can lead to performance gains.
By understanding and utilizing Render Groups, you can take full advantage of PixiJS's rendering capabilities, making your applications smoother and more efficient. This feature represents a powerful tool in the optimization toolkit offered by PixiJS, enabling developers to create rich, interactive scenes that run smoothly across different devices.
---
## Render Layers
# Render Layers
The PixiJS Layer API provides a powerful way to control the **rendering order** of objects independently of their **logical parent-child relationships** in the scene graph. With RenderLayers, you can decouple how objects are transformed (via their logical parent) from how they are visually drawn on the screen.
Using RenderLayers ensures these elements are visually prioritized while maintaining logical parent-child relationships. Examples include:
- A character with a health bar: Ensure the health bar always appears on top of the world, even if the character moves behind an object.
- UI elements like score counters or notifications: Keep them visible regardless of the game world’s complexity.
- Highlighting Elements in Tutorials: Imagine a tutorial where you need to push back most game elements while highlighting a specific object. RenderLayers can split these visually. The highlighted object can be placed in a foreground layer to be rendered above a push back layer.
This guide explains the key concepts, provides practical examples, and highlights common gotchas to help you use the Layer API effectively.
---
### **Key Concepts**
1. **Independent Rendering Order**:
- RenderLayers allow control of the draw order independently of the logical hierarchy, ensuring objects are rendered in the desired order.
2. **Logical Parenting Stays Intact**:
- Objects maintain transformations (e.g., position, scale, rotation) from their logical parent, even when attached to RenderLayers.
3. **Explicit Object Management**:
- Objects must be manually reassigned to a layer after being removed from the scene graph or layer, ensuring deliberate control over rendering.
4. **Dynamic Sorting**:
- Within layers, objects can be dynamically reordered using `zIndex` and `sortChildren` for fine-grained control of rendering order.
---
### **Basic API Usage**
First lets create two items that we want to render, red guy and blue guy.
```typescript
const redGuy = new PIXI.Sprite('red guy');
redGuy.tint = 0xff0000;
const blueGuy = new PIXI.Sprite('blue guy');
blueGuy.tint = 0x0000ff;
stage.addChild(redGuy, blueGuy);
```

Now we know that red guy will be rendered first, then blue guy. Now in this simple example you could get away with just sorting the `zIndex` of the red guy and blue guy to help reorder.
But this is a guide about render layers, so lets create one of those.
Use `renderLayer.attach` to assign an object to a layer. This overrides the object’s default render order defined by its logical parent.
```typescript
// a layer..
const layer = new RenderLayer();
stage.addChild(layer);
layer.attach(redGuy);
```

So now our scene graph order is:
```
|- stage
|-- redGuy
|-- blueGuy
|-- layer
```
And our render order is:
```
|- stage
|-- blueGuy
|-- layer
|-- redGuy
```
This happens because the layer is now the last child in the stage. Since the red guy is attached to the layer, it will be rendered at the layer's position in the scene graph. However, it still logically remains in the same place in the scene hierarchy.
#### **3. Removing Objects from a Layer**
Now let's remove the red guy from the layer. To stop an object from being rendered in a layer, use `removeFromLayer`. Once removed from the layer, its still going to be in the scene graph, and will be rendered in its scene graph order.
```typescript
layer.detach(redGuy); // Stop rendering the rect via the layer
```

Removing an object from its logical parent (`removeChild`) automatically removes it from the layer.
```typescript
stage.removeChild(redGuy); // if the red guy was removed from the stage, it will also be removed from the layer
```

However, if you remove the red guy from the stage and then add it back to the stage, it will not be added to the layer again.
```typescript
// add red guy to his original position
stage.addChildAt(redGuy, 0);
```

You will need to reattach it to the layer yourself.
```typescript
layer.attach(redGuy); // re attach it to the layer again!
```

This may seem like a pain, but it's actually a good thing. It means that you have full control over the render order of the object, and you can change it at any time. It also means you can't accidentally add an object to a container and have it automatically re-attach to a layer that may or may not still be around - it would be quite confusing and lead to some very hard to debug bugs!
#### **5. Layer Position in Scene Graph**
The layer’s position in the scene graph determines its render priority relative to other layers and objects.
```typescript
// reparent the layer to render first in the stage
stage.addChildAt(layer, 0);
```
## 
### **Complete Example**
Here’s a real-world example that shows how to use RenderLayers to set ap player ui on top of the world.
```ts
import {
Application,
Assets,
Container,
DisplacementFilter,
RenderLayer,
Sprite,
TilingSprite,
} from 'pixi.js';
import { Fish } from './Fish';
(async () => {
// Create a new application
const app = new Application();
// Initialize the application
await app.init({ width: 630, height: 410, antialias: true });
// Append the application canvas to the document body
document.body.appendChild(app.canvas);
// move the canvas to the center of the screen
app.canvas.style.position = 'absolute';
app.canvas.style.top = `${window.innerHeight / 2 - app.canvas.height / 2}px`;
app.canvas.style.left = `${window.innerWidth / 2 - app.canvas.width / 2}px`;
// Load textures
await Assets.load([
`https://pixijs.com/assets/pond/displacement_BG.jpg`,
`https://pixijs.com/assets/pond/overlay.png`,
`https://pixijs.com/assets/pond/displacement_map.png`,
`https://pixijs.com/assets/pond/displacement_fish1.png`,
`https://pixijs.com/assets/pond/displacement_fish2.png`,
]);
const background = Sprite.from(
'https://pixijs.com/assets/pond/displacement_BG.jpg',
);
const pondContainer = new Container();
pondContainer.addChild(background);
app.stage.addChild(pondContainer);
const displacementMap = Assets.get(
'https://pixijs.com/assets/pond/displacement_map.png',
);
displacementMap.source.wrapMode = 'repeat';
const displacementSprite = Sprite.from(displacementMap);
const displacementFilter = new DisplacementFilter(displacementSprite, 40);
pondContainer.addChild(displacementSprite);
pondContainer.filters = [displacementFilter];
const uiLayer = new RenderLayer();
const fishes = [];
const names = [
'Alice',
'Bob',
'Caroline',
'David',
'Ellie',
'Frank',
'Gloria',
'Henry',
'Isabel',
'Jack',
];
const textures = [
Assets.get('https://pixijs.com/assets/pond/displacement_fish1.png'),
Assets.get('https://pixijs.com/assets/pond/displacement_fish2.png'),
];
for (let i = 0; i < 10; i++) {
const fish = new Fish(
names[i % names.length],
textures[i % textures.length],
);
fishes.push(fish);
pondContainer.addChild(fish);
fish.x = Math.random() * 630;
fish.y = Math.random() * 410;
uiLayer.attach(fish.ui);
}
const waterOverlay = TilingSprite.from(
Assets.get('https://pixijs.com/assets/pond/overlay.png'),
);
waterOverlay.width = 630;
waterOverlay.height = 410;
pondContainer.addChild(waterOverlay);
app.stage.addChild(uiLayer);
// Animate the mask
app.ticker.add(() => {
waterOverlay.tilePosition.x += 0.5;
waterOverlay.tilePosition.y += 0.5;
displacementSprite.x += 0.5;
displacementSprite.y += 0.5;
fishes.forEach((fish) => fish.update());
});
})();
```
```ts
import { Container, Sprite } from 'pixi.js';
import { CharacterUI } from './CharacterUI';
export class Fish extends Container {
ui;
_speed = 1 + Number(Math.random());
_direction = Math.random() * Math.PI * 2;
fishView;
constructor(name, texture) {
super();
this.fishView = new Sprite(texture);
this.fishView.anchor.set(0.5);
this.addChild(this.fishView);
this.ui = new CharacterUI(name, 20);
this.ui.y = 0;
this.addChild(this.ui);
}
update() {
this._direction += 0.001;
this.fishView.rotation = Math.PI - this._direction;
this.x += this._speed * Math.cos(-this._direction);
this.y += this._speed * Math.sin(-this._direction);
// wrap around the screen
const padding = 100;
const width = 630;
const height = 410;
if (this.x > width + padding) this.x -= width + padding * 2;
if (this.x < -padding) this.x += width + padding * 2;
if (this.y > height + padding) this.y -= height + padding * 2;
if (this.y < -padding) this.y += height + padding * 2;
}
}
```
```ts
import { Container, Graphics, Text } from 'pixi.js';
export class CharacterUI extends Container {
constructor(name) {
super();
const label = new Text({
text: name,
resolution: 2,
style: { fontSize: 16, fill: 0x000000 },
anchor: 0.5,
});
const padding = 10;
const bg = new Graphics()
.roundRect(
-label.width / 2 - padding,
-label.height / 2 - padding,
label.width + padding * 2,
label.height + padding * 2,
20,
)
.fill({
color: 0xffff00,
alpha: 1,
});
this.addChild(bg, label);
}
}
```
---
### **Gotchas and Things to Watch Out For**
1. **Manual Reassignment**:
- When an object is re-added to a logical parent, it does not automatically reassociate with its previous layer. Always reassign the object to the layer explicitly.
2. **Nested Children**:
- If you remove a parent container, all its children are automatically removed from layers. Be cautious with complex hierarchies.
3. **Sorting Within Layers**:
- Objects in a layer can be sorted dynamically using their `zIndex` property. This is useful for fine-grained control of render order.
```javascript
rect.zIndex = 10; // Higher values render later
layer.sortableChildren = true; // Enable sorting
layer.sortRenderLayerChildren(); // Apply the sorting
```
4. **Layer Overlap**:
- If multiple layers overlap, their order in the scene graph determines the render priority. Ensure the layering logic aligns with your desired visual output.
---
### **Best Practices**
1. **Group Strategically**: Minimize the number of layers to optimize performance.
2. **Use for Visual Clarity**: Reserve layers for objects that need explicit control over render order.
3. **Test Dynamic Changes**: Verify that adding, removing, or reassigning objects to layers behaves as expected in your specific scene setup.
By understanding and leveraging RenderLayers effectively, you can achieve precise control over your scene's visual presentation while maintaining a clean and logical hierarchy.
---
## Render Loop
# Render Loop
At the core of PixiJS lies its **render loop**, a repeating cycle that updates and redraws your scene every frame. Unlike traditional web development where rendering is event-based (e.g. on user input), PixiJS uses a continuous animation loop that provides full control over real-time rendering.
This guide provides a deep dive into how PixiJS structures this loop internally, from the moment a frame begins to when it is rendered to the screen. Understanding this will help you write more performant, well-structured applications.
## Overview
Each frame, PixiJS performs the following sequence:
1. **Tickers are executed** (user logic)
2. **Scene graph is updated** (transforms and culling)
3. **Rendering occurs** (GPU draw calls)
This cycle repeats as long as your application is running and its ticker is active.
## Step 1: Running Ticker Callbacks
The render loop is driven by the `Ticker` class, which uses `requestAnimationFrame` to schedule work. Each tick:
- Measures elapsed time since the previous frame
- Caps it based on `minFPS` and `maxFPS`
- Calls every listener registered with `ticker.add()` or `app.ticker.add()`
### Example
```ts
app.ticker.add((ticker) => {
bunny.rotation += ticker.deltaTime * 0.1;
});
```
Every callback receives the current `Ticker` instance. You can access `ticker.deltaTime` (scaled frame delta) and `ticker.elapsedMS` (unscaled delta in ms) to time animations.
## Step 2: Updating the Scene Graph
PixiJS uses a hierarchical **scene graph** to represent all visual objects. Before rendering, the graph needs to be traversed to:
- Recalculate transforms (world matrix updates)
- Apply custom logic via `onRender` handlers
- Apply culling if enabled
## Step 3: Rendering the Scene
Once the scene graph is ready, the renderer walks the display list starting at `app.stage`:
1. Applies global and local transformations
2. Batches draw calls when possible
3. Uploads geometry, textures, and uniforms
4. Issues GPU commands
All rendering is **retained mode**: objects persist across frames unless explicitly removed.
Rendering is done via either WebGL or WebGPU, depending on your environment. The renderer abstracts away the differences behind a common API.
## Full Frame Lifecycle Diagram
```plaintext
requestAnimationFrame
│
[Ticker._tick()]
│
├─ Compute elapsed time
├─ Call user listeners
│ └─ sprite.onRender
├─ Cull display objects (if enabled)
├─ Update world transforms
└─ Render stage
├─ Traverse display list
├─ Upload data to GPU
└─ Draw
```
---
## Scene Graph
# Scene Graph
Every frame, PixiJS is updating and then rendering the scene graph. Let's talk about what's in the scene graph, and how it impacts how you develop your project. If you've built games before, this should all sound very familiar, but if you're coming from HTML and the DOM, it's worth understanding before we get into specific types of objects you can render.
## The Scene Graph Is a Tree
The scene graph's root node is a container maintained by the application, and referenced with `app.stage`. When you add a sprite or other renderable object as a child to the stage, it's added to the scene graph and will be rendered and interactable. PixiJS `Containers` can also have children, and so as you build more complex scenes, you will end up with a tree of parent-child relationships, rooted at the app's stage.
(A helpful tool for exploring your project is the [Pixi.js devtools plugin](https://chrome.google.com/webstore/detail/pixijs-devtools/aamddddknhcagpehecnhphigffljadon) for Chrome, which allows you to view and manipulate the scene graph in real time as it's running!)
## Parents and Children
When a parent moves, its children move as well. When a parent is rotated, its children are rotated too. Hide a parent, and the children will also be hidden. If you have a game object that's made up of multiple sprites, you can collect them under a container to treat them as a single object in the world, moving and rotating as one.
Each frame, PixiJS runs through the scene graph from the root down through all the children to the leaves to calculate each object's final position, rotation, visibility, transparency, etc. If a parent's alpha is set to 0.5 (making it 50% transparent), all its children will start at 50% transparent as well. If a child is then set to 0.5 alpha, it won't be 50% transparent, it will be 0.5 x 0.5 = 0.25 alpha, or 75% transparent. Similarly, an object's position is relative to its parent, so if a parent is set to an x position of 50 pixels, and the child is set to an x position of 100 pixels, it will be drawn at a screen offset of 150 pixels, or 50 + 100.
Here's an example. We'll create three sprites, each a child of the last, and animate their position, rotation, scale and alpha. Even though each sprite's properties are set to the same values, the parent-child chain amplifies each change:
```ts
import { Application, Assets, Container, Sprite } from 'pixi.js';
(async () => {
// Create the application helper and add its render target to the page
const app = new Application();
await app.init({ resizeTo: window });
document.body.appendChild(app.canvas);
// Add a container to center our sprite stack on the page
const container = new Container({
x: app.screen.width / 2,
y: app.screen.height / 2,
});
app.stage.addChild(container);
// load the texture
const tex = await Assets.load('https://pixijs.com/assets/bunny.png');
// Create the 3 sprites, each a child of the last
const sprites = [];
let parent = container;
for (let i = 0; i < 3; i++) {
const wrapper = new Container();
const sprite = Sprite.from(tex);
sprite.anchor.set(0.5);
wrapper.addChild(sprite);
parent.addChild(wrapper);
sprites.push(wrapper);
parent = wrapper;
}
// Set all sprite's properties to the same value, animated over time
let elapsed = 0.0;
app.ticker.add((delta) => {
elapsed += delta.deltaTime / 60;
const amount = Math.sin(elapsed);
const scale = 1.0 + 0.25 * amount;
const alpha = 0.75 + 0.25 * amount;
const angle = 40 * amount;
const x = 75 * amount;
for (let i = 0; i < sprites.length; i++) {
const sprite = sprites[i];
sprite.scale.set(scale);
sprite.alpha = alpha;
sprite.angle = angle;
sprite.x = x;
}
});
})();
```
The cumulative translation, rotation, scale and skew of any given node in the scene graph is stored in the object's
`worldTransform` property. Similarly, the cumulative alpha value is stored in the `worldAlpha` property.
## Render Order
So we have a tree of things to draw. Who gets drawn first?
PixiJS renders the tree from the root down. At each level, the current object is rendered, then each child is rendered in order of insertion. So the second child is rendered on top of the first child, and the third over the second.
Check out this example, with two parent objects A & D, and two children B & C under A:
```ts
import { Application, Container, Sprite, Text, Texture } from 'pixi.js';
(async () => {
// Create the application helper and add its render target to the page
const app = new Application();
await app.init({ resizeTo: window });
document.body.appendChild(app.canvas);
// Label showing scene graph hierarchy
const label = new Text({
text: 'Scene Graph:\n\napp.stage\n ┗ A\n ┗ B\n ┗ C\n ┗ D',
style: { fill: '#ffffff' },
position: { x: 300, y: 100 },
});
app.stage.addChild(label);
// Helper function to create a block of color with a letter
const letters = [];
function addLetter(letter, parent, color, pos) {
const bg = new Sprite(Texture.WHITE);
bg.width = 100;
bg.height = 100;
bg.tint = color;
const text = new Text({
text: letter,
style: { fill: '#ffffff' },
});
text.anchor.set(0.5);
text.position = { x: 50, y: 50 };
const container = new Container();
container.position = pos;
container.visible = false;
container.addChild(bg, text);
parent.addChild(container);
letters.push(container);
return container;
}
// Define 4 letters
const a = addLetter('A', app.stage, 0xff0000, { x: 100, y: 100 });
const b = addLetter('B', a, 0x00ff00, { x: 20, y: 20 });
const c = addLetter('C', a, 0x0000ff, { x: 20, y: 40 });
const d = addLetter('D', app.stage, 0xff8800, { x: 140, y: 100 });
// Display them over time, in order
let elapsed = 0.0;
app.ticker.add((ticker) => {
elapsed += ticker.deltaTime / 60.0;
if (elapsed >= letters.length) {
elapsed = 0.0;
}
for (let i = 0; i < letters.length; i++) {
letters[i].visible = elapsed >= i;
}
});
})();
```
If you'd like to re-order a child object, you can use `setChildIndex()`. To add a child at a given point in a parent's list, use `addChildAt()`. Finally, you can enable automatic sorting of an object's children using the `sortableChildren` option combined with setting the `zIndex` property on each child.
## RenderGroups
As you delve deeper into PixiJS, you'll encounter a powerful feature known as Render Groups. Think of Render Groups as specialized containers within your scene graph that act like mini scene graphs themselves. Here's what you need to know to effectively use Render Groups in your projects. For more info check out the [RenderGroups overview](./render-groups.md)
## Culling
If you're building a project where a large proportion of your scene objects are off-screen (say, a side-scrolling game), you will want to _cull_ those objects. Culling is the process of evaluating if an object (or its children!) is on the screen, and if not, turning off rendering for it. If you don't cull off-screen objects, the renderer will still draw them, even though none of their pixels end up on the screen.
PixiJS provides built-in support for viewport culling. To enable culling, set `cullable = true` on your objects. You can also set `cullableChildren` to `false` to allow PixiJS to bypass the recursive culling function, which can improve performance. Additionally, you can set `cullArea` to further optimize performance by defining the area to be culled.
## Local vs Global Coordinates
If you add a sprite to the stage, by default it will show up in the top left corner of the screen. That's the origin of the global coordinate space used by PixiJS. If all your objects were children of the stage, that's the only coordinates you'd need to worry about. But once you introduce containers and children, things get more complicated. A child object at [50, 100] is 50 pixels right and 100 pixels down _from its parent_.
We call these two coordinate systems "global" and "local" coordinates. When you use `position.set(x, y)` on an object, you're always working in local coordinates, relative to the object's parent.
The problem is, there are many times when you want to know the global position of an object. For example, if you want to cull offscreen objects to save render time, you need to know if a given child is outside the view rectangle.
To convert from local to global coordinates, you use the `toGlobal()` function. Here's a sample usage:
```javascript
// Get the global position of an object, relative to the top-left of the screen
let globalPos = obj.toGlobal(new Point(0, 0));
```
This snippet will set `globalPos` to be the global coordinates for the child object, relative to [0, 0] in the global coordinate system.
## Global vs Screen Coordinates
When your project is working with the host operating system or browser, there is a third coordinate system that comes into play - "screen" coordinates (aka "viewport" coordinates). Screen coordinates represent position relative to the top-left of the canvas element that PixiJS is rendering into. Things like the DOM and native mouse click events work in screen space.
Now, in many cases, screen space is equivalent to world space. This is the case if the size of the canvas is the same as the size of the render view specified when you create you `Application`. By default, this will be the case - you'll create for example an 800x600 application window and add it to your HTML page, and it will stay that size. 100 pixels in world coordinates will equal 100 pixels in screen space. BUT! It is common to stretch the rendered view to have it fill the screen, or to render at a lower resolution and up-scale for speed. In that case, the screen size of the canvas element will change (e.g. via CSS), but the underlying render view will _not_, resulting in a mis-match between world coordinates and screen coordinates.
---
## Accessibility
# Accessibility
PixiJS includes built-in accessibility support through a DOM-based overlay system that integrates with screen readers, keyboard navigation, and other assistive technologies. It uses `` overlays to describe visual elements to screen readers
:::info
Accessibility is opt-in to reduce bundle size and must be explicitly enabled.
:::
```ts
import 'pixi.js/accessibility';
import { Container } from 'pixi.js';
const button = new Container();
button.accessible = true;
```
## **How It Works**
PixiJS places DOM `` elements over your canvas, aligned to the bounds of accessible objects. These elements:
- Can receive focus via keyboard (`tabIndex`)
- Announce `accessibleTitle` or `accessibleHint` to screen readers
- Dispatch `click`, `mouseover`, `mouseout` events as Pixi pointer events
- Use `aria-live` and `aria-label` where appropriate
## Enabling the System
To enable accessibility, you must import the module before creating your renderer:
```ts
import 'pixi.js/accessibility';
```
PixiJS automatically installs the `AccessibilitySystem` onto your renderer. You can configure how and when it's activated.
## **Configuration Options**
You can customize when and how the accessibility system activates by passing options to the `Application` constructor:
```ts
const app = new Application({
accessibilityOptions: {
enabledByDefault: true, // Enable on startup
activateOnTab: false, // Disable auto-activation via tab
deactivateOnMouseMove: false, // Keep system active with mouse use
debug: true, // Show div overlays for debugging
},
});
```
Or programmatically enable/disable the system:
```ts
app.renderer.accessibility.setAccessibilityEnabled(true);
```
## **Creating Accessible Objects**
To mark a display object as accessible and add it to the accessibility system, set the `accessible` property to `true`. This will create a `` overlay that screen readers can interact with.
```ts
const button = new Container();
button.accessible = true;
app.stage.addChild(button);
```
### **Properties for Accessible Containers**
There are several properties you can set on accessible containers to customize their behavior:
| Property | Description |
| ------------------------- | ---------------------------------------------------------------- |
| `accessible` | Enables accessibility for the object |
| `accessibleTitle` | Sets the `title` for screen readers |
| `accessibleHint` | Sets the `aria-label` |
| `accessibleText` | Alternative inner text for the div |
| `accessibleType` | Tag name used for the shadow element (`'button'`, `'div'`, etc.) |
| `accessiblePointerEvents` | CSS `pointer-events` value (`'auto'`, `'none'`, etc.) |
| `tabIndex` | Allows focus with keyboard navigation |
| `accessibleChildren` | Whether children of this container are accessible |
---
## **API Reference**
- [Overview](https://pixijs.download/release/docs/accessibility.html)
- [AccessibilitySystem](https://pixijs.download/release/docs/accessibility.AccessibilitySystem.html)
- [AccessibleOptions](https://pixijs.download/release/docs/accessibility.AccessibleOptions.html)
---
## Color
# Color
The `Color` class in PixiJS is a flexible utility for representing colors. It is used throughout the rendering pipeline for things like tints, fills, strokes, gradients, and more.
```ts
import { Color, Sprite, Texture, Graphics } from 'pixi.js';
const red = new Color('red'); // Named color
const green = new Color(0x00ff00); // Hex
const blue = new Color('#0000ff'); // Hex string
const rgba = new Color({ r: 255, g: 0, b: 0, a: 0.5 }); // RGBA object
console.log(red.toArray()); // [1, 0, 0, 1]
console.log(green.toHex()); // "#00ff00"
const sprite = new Sprite(Texture.WHITE);
sprite.tint = red; // Works directly with a Color instance
```
## Using `Color` and `ColorSource`
PixiJS supports many color formats through the `ColorSource` type:
- Color names: `'red'`, `'white'`, `'blue'`, etc.
- Hex integers: `0xffcc00`
- Hex strings: `'ffcc00'`, `'#f00'`, `'0xffcc00ff'`
- RGB(A) objects: `{ r: 255, g: 0, b: 0 }`, `{ r: 255, g: 0, b: 0, a: 0.5 }`
- RGB(A) strings: `'rgb(255,0,0)'`, `'rgba(255,0,0,0.5)'`
- RGB(A) arrays: `[1, 0, 0]`, `[1, 0, 0, 0.5]`
- Typed arrays: `Uint8Array`, `Float32Array`
- HSL/HSV objects and strings
- `Color` instances
Whenever you see a color-related property (e.g., `fill`, `tint`, `stroke`), you can use any of these formats. The library will automatically convert them to the appropriate format internally.
```ts
import { Graphics, Sprite, Texture } from 'pixi.js';
const sprite = new Sprite(Texture.WHITE);
sprite.tint = 'red'; // converted internally
const graphics = new Graphics();
graphics.fill({ color: '#00ff00' }); // Also converted internally
```
---
## API Reference
- [Color](https://pixijs.download/release/docs/color.Color.html)
---
## Events / Interaction
# Events / Interaction
PixiJS is primarily a rendering library, but it provides a flexible and performant event system designed for both mouse and touch input. This system replaces the legacy `InteractionManager` from previous versions with a unified, DOM-like federated event model.
```ts
const sprite = new Sprite(texture);
sprite.eventMode = 'static';
sprite.on('pointerdown', () => {
console.log('Sprite clicked!');
});
```
## Event Modes
To use the event system, set the `eventMode` of a `Container` (or its subclasses like `Sprite`) and subscribe to event listeners.
The `eventMode` property controls how an object interacts with the event system:
| Mode | Description |
| --------- | ------------------------------------------------------------------------------------------------------------------------ |
| `none` | Ignores all interaction events, including children. Optimized for non-interactive elements. |
| `passive` | _(default)_ Ignores self-hit testing and does not emit events, but interactive children still receive events. |
| `auto` | Participates in hit testing only if a parent is interactive. Does not emit events. |
| `static` | Emits events and is hit tested. Suitable for non-moving interactive elements like buttons. |
| `dynamic` | Same as `static`, but also receives synthetic events when the pointer is idle. Suitable for animating or moving targets. |
## Event Types
PixiJS supports a rich set of DOM-like event types across mouse, touch, and pointer input. Below is a categorized list.
### Pointer Events (Recommended for general use)
| Event Type | Description |
| ------------------- | ---------------------------------------------------------------------------------- |
| `pointerdown` | Fired when a pointer (mouse, pen, or touch) is pressed on a display object. |
| `pointerup` | Fired when the pointer is released over the display object. |
| `pointerupoutside` | Fired when the pointer is released outside the object that received `pointerdown`. |
| `pointermove` | Fired when the pointer moves over the display object. |
| `pointerover` | Fired when the pointer enters the boundary of the display object. |
| `pointerout` | Fired when the pointer leaves the boundary of the display object. |
| `pointerenter` | Fired when the pointer enters the display object (does not bubble). |
| `pointerleave` | Fired when the pointer leaves the display object (does not bubble). |
| `pointercancel` | Fired when the pointer interaction is canceled (e.g. touch lost). |
| `pointertap` | Fired when a pointer performs a quick tap. |
| `globalpointermove` | Fired on every pointer move, regardless of whether any display object is hit. |
### Mouse Events (Used for mouse-specific input)
| Event Type | Description |
| ----------------- | ------------------------------------------------------------------------------------------- |
| `mousedown` | Fired when a mouse button is pressed on a display object. |
| `mouseup` | Fired when a mouse button is released over the object. |
| `mouseupoutside` | Fired when a mouse button is released outside the object that received `mousedown`. |
| `mousemove` | Fired when the mouse moves over the display object. |
| `mouseover` | Fired when the mouse enters the display object. |
| `mouseout` | Fired when the mouse leaves the display object. |
| `mouseenter` | Fired when the mouse enters the object, does not bubble. |
| `mouseleave` | Fired when the mouse leaves the object, does not bubble. |
| `click` | Fired when a mouse click (press and release) occurs on the object. |
| `rightdown` | Fired when the right mouse button is pressed on the display object. |
| `rightup` | Fired when the right mouse button is released over the object. |
| `rightupoutside` | Fired when the right mouse button is released outside the object that received `rightdown`. |
| `rightclick` | Fired when a right mouse click (press and release) occurs on the object. |
| `globalmousemove` | Fired on every mouse move, regardless of display object hit. |
| `wheel` | Fired when the mouse wheel is scrolled while over the display object. |
### Touch Events
| Event Type | Description |
| ----------------- | ------------------------------------------------------------------------------------- |
| `touchstart` | Fired when a new touch point is placed on a display object. |
| `touchend` | Fired when a touch point is lifted from the display object. |
| `touchendoutside` | Fired when a touch point ends outside the object that received `touchstart`. |
| `touchmove` | Fired when a touch point moves across the display object. |
| `touchcancel` | Fired when a touch interaction is canceled (e.g. device gesture). |
| `tap` | Fired when a touch point taps the display object. |
| `globaltouchmove` | Fired on every touch move, regardless of whether a display object is under the touch. |
### Global Events
In previous versions of PixiJS, events such as `pointermove`, `mousemove`, and `touchmove` were fired when any move event was captured by the canvas, even if the pointer was not over a display object. This behavior changed in v8 and now these events are fired only when the pointer is over a display object.
To maintain the old behavior, you can use the `globalpointermove`, `globalmousemove`, and `globaltouchmove` events. These events are fired on every pointer/touch move, regardless of whether any display object is hit.
```ts
const sprite = new Sprite(texture);
sprite.eventMode = 'static';
sprite.on('globalpointermove', (event) => {
console.log('Pointer moved globally!', event);
});
```
## How Hit Testing Works
When an input event occurs (mouse move, click, etc.), PixiJS walks the display tree to find the top-most interactive element under the pointer:
- If `interactiveChildren` is `false` on a `Container`, its children will be skipped.
- If a `hitArea` is set, it overrides bounds-based hit testing.
- If `eventMode` is `'none'`, the element and its children are skipped.
Once the top-most interactive element is found, the event is dispatched to it. If the event bubbles, it will propagate up the display tree.
If the event is not handled, it will continue to bubble up to parent containers until it reaches the root.
### Custom Hit Area
Custom hit areas can be defined using the `hitArea` property. This property can be set on any scene object, including `Sprite`, `Container`, and `Graphics`.
Using a custom hit area allows you to define a specific area for interaction, which can be different from the object's bounding box. It also can improve performance by reducing the number of objects that need to be checked for interaction.
```ts
import { Rectangle, Sprite } from 'pixi.js';
const sprite = new Sprite(texture);
sprite.hitArea = new Rectangle(0, 0, 100, 100);
sprite.eventMode = 'static';
```
## Listening to Events
PixiJS supports both `on()`/`off()` and `addEventListener()`/`removeEventListener()` and event callbacks (`onclick: ()=> {}`) for adding and removing event listeners. The `on()` method is recommended for most use cases as it provides a more consistent API across different event types used throughout PixiJS.
### Using `on()` (from EventEmitter)
```ts
const eventFn = (e) => console.log('clicked');
sprite.on('pointerdown', eventFn);
sprite.once('pointerdown', eventFn);
sprite.off('pointerdown', eventFn);
```
### Using DOM-style Events
```ts
sprite.addEventListener(
'click',
(event) => {
console.log('Clicked!', event.detail);
},
{ once: true },
);
```
### Using callbacks
```ts
sprite.onclick = (event) => {
console.log('Clicked!', event.detail);
};
```
## Checking for Interactivity
You can check if a `Sprite` or `Container` is interactive by using the `isInteractive()` method. This method returns `true` if the object is interactive and can receive events.
```ts
if (sprite.isInteractive()) {
// true if eventMode is static or dynamic
}
```
## Custom Cursors
PixiJS allows you to set a custom cursor for interactive objects using the `cursor` property. This property accepts a string representing the CSS cursor type.
```ts
const sprite = new Sprite(texture);
sprite.eventMode = 'static';
sprite.cursor = 'pointer'; // Set the cursor to a pointer when hovering over the sprite
```
```ts
const sprite = new Sprite(texture);
sprite.eventMode = 'static';
sprite.cursor = 'url(my-cursor.png), auto'; // Set a custom cursor image
```
### Default Custom Cursors
You can also set default values to be used for all interactive objects.
```ts
// CSS style for icons
const defaultIcon = "url('https://pixijs.com/assets/bunny.png'),auto";
const hoverIcon = "url('https://pixijs.com/assets/bunny_saturated.png'),auto";
// Add custom cursor styles
app.renderer.events.cursorStyles.default = defaultIcon;
app.renderer.events.cursorStyles.hover = hoverIcon;
const sprite = new Sprite(texture);
sprite.eventMode = 'static';
sprite.cursor = 'hover';
```
---
## API Reference
- [Overview](https://pixijs.download/release/docs/events.html)
- [EventSystem](https://pixijs.download/release/docs/events.EventSystem.html)
- [Cursor](https://pixijs.download/release/docs/events.html#Cursor)
- [EventMode](https://pixijs.download/release/docs/events.html#EventMode)
- [Container](https://pixijs.download/release/docs/scene.Container.html)
- [FederatedEvent](https://pixijs.download/release/docs/events.FederatedEvent.html)
- [FederatedMouseEvent](https://pixijs.download/release/docs/events.FederatedMouseEvent.html)
- [FederatedWheelEvent](https://pixijs.download/release/docs/events.FederatedWheelEvent.html)
- [FederatedPointerEvent](https://pixijs.download/release/docs/events.FederatedPointerEvent.html)
---
## Filters / Blend Modes
# Filters / Blend Modes
PixiJS filters allow you to apply post-processing visual effects to any scene object and its children. Filters can be used for effects such as blurring, color adjustments, noise, or custom shader-based operations.
```ts
import { Sprite, BlurFilter } from 'pixi.js';
// Apply the filter
sprite.filters = [new BlurFilter({ strength: 8 })];
```
---
## Applying Filters
Applying filters is straightforward. You can assign a filter instance to the `filters` property of any scene object, such as `Sprite`, `Container`, or `Graphics`.
You can apply multiple filters by passing an array of filter instances.
```ts
import { BlurFilter, NoiseFilter } from 'pixi.js';
sprite.filters = new BlurFilter({ strength: 5 });
sprite.filters = [
new BlurFilter({ strength: 4 }),
new NoiseFilter({ noise: 0.2 }),
];
```
:::info
Order matters — filters are applied in sequence.
:::
---
## Advanced Blend Modes
PixiJS v8 introduces advanced blend modes for filters, allowing for more complex compositing effects. These blend modes can be used to create unique visual styles and effects.
To use advanced modes like `HARD_LIGHT`, you must manually import the advanced blend mode extension:
```ts
import 'pixi.js/advanced-blend-modes';
import { HardMixBlend } from 'pixi.js';
sprite.filters = [new HardMixBlend()];
```
---
## Built-In Filters Overview
PixiJS v8 provides a variety of filters out of the box:
| Filter Class | Description |
| -------------------- | ------------------------------------------- |
| `AlphaFilter` | Applies transparency to an object. |
| `BlurFilter` | Gaussian blur. |
| `ColorMatrixFilter` | Applies color transformations via a matrix. |
| `DisplacementFilter` | Distorts an object using another texture. |
| `NoiseFilter` | Adds random noise for a grainy effect. |
:::info
To explore more community filters, see [pixi-filters](https://pixijs.io/filters/docs/).
:::
**Blend Filters**: Used for custom compositing modes
| Filter Class | Description |
| ------------------ | -------------------------------------------------- |
| `ColorBurnBlend` | Darkens the base color to reflect the blend color. |
| `ColorDodgeBlend` | Brightens the base color. |
| `DarkenBlend` | Retains the darkest color components. |
| `DivideBlend` | Divides the base color by the blend color. |
| `HardMixBlend` | High-contrast blend. |
| `LinearBurnBlend` | Darkens using linear formula. |
| `LinearDodgeBlend` | Lightens using linear formula. |
| `LinearLightBlend` | Combination of linear dodge and burn. |
| `PinLightBlend` | Selective replacement of colors. |
| `SubtractBlend` | Subtracts the blend color from base. |
---
## Creating a Custom Filter
To define a custom filter in PixiJS v8, you use `Filter.from()` with shader programs and GPU resources.
```ts
import { Filter, GlProgram, Texture } from 'pixi.js';
const vertex = `
in vec2 aPosition;
out vec2 vTextureCoord;
uniform vec4 uInputSize;
uniform vec4 uOutputFrame;
uniform vec4 uOutputTexture;
vec4 filterVertexPosition( void )
{
vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;
position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;
position.y = position.y * (2.0*uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;
return vec4(position, 0.0, 1.0);
}
vec2 filterTextureCoord( void )
{
return aPosition * (uOutputFrame.zw * uInputSize.zw);
}
void main(void)
{
gl_Position = filterVertexPosition();
vTextureCoord = filterTextureCoord();
}
`;
const fragment = `
in vec2 vTextureCoord;
in vec4 vColor;
uniform sampler2D uTexture;
uniform float uTime;
void main(void)
{
vec2 uvs = vTextureCoord.xy;
vec4 fg = texture2D(uTexture, vTextureCoord);
fg.r = uvs.y + sin(uTime);
gl_FragColor = fg;
}
`;
const customFilter = new Filter({
glProgram: new GlProgram({
fragment,
vertex,
}),
resources: {
timeUniforms: {
uTime: { value: 0.0, type: 'f32' },
},
},
});
// Apply the filter
sprite.filters = [customFilter];
// Update uniform
app.ticker.add((ticker) => {
filter.resources.timeUniforms.uniforms.uTime += 0.04 * ticker.deltaTime;
});
```
:::info **Tip**
Shaders must be WebGL- or WebGPU-compatible. For dual-renderer support, include a `gpuProgram`.
:::
---
## API Reference
- [Overview](https://pixijs.download/release/docs/filters.html)
- [Filter](https://pixijs.download/release/docs/filters.Filter.html)
---
## Math
# Math
PixiJS includes a several math utilities for 2D transformations, geometry, and shape manipulation. This guide introduces the most important classes and their use cases, including optional advanced methods enabled via `math-extras`.
## Matrix
The `Matrix` class represents a 2D affine transformation matrix. It is used extensively for transformations such as scaling, translation, and rotation.
```ts
import { Matrix, Point } from 'pixi.js';
const matrix = new Matrix();
matrix.translate(10, 20).scale(2, 2);
const point = new Point(5, 5);
const result = matrix.apply(point); // result is (20, 30)
```
---
## Point and ObservablePoint
### `Point`
The Point object represents a location in a two-dimensional coordinate system, where `x` represents the position on the horizontal axis and `y` represents the position on the vertical axis. Many Pixi functions accept the `PointData` type as an alternative to `Point`, which only requires `x` and `y` properties.
```ts
import { Point } from 'pixi.js';
const point = new Point(5, 10);
point.set(20, 30); // set x and y
```
### `ObservablePoint`
Extends `Point` and triggers a callback when its values change. Used internally for reactive systems like position and scale updates.
```ts
import { Point, ObservablePoint } from 'pixi.js';
const observer = {
_onUpdate: (point) => {
console.log(`Point updated to: (${point.x}, ${point.y})`);
},
};
const reactive = new ObservablePoint(observer, 1, 2);
reactive.set(3, 4); // triggers call to _onUpdate
```
---
## Shapes
PixiJS includes several 2D shapes, used for hit testing, rendering, and geometry computations.
### `Rectangle`
Axis-aligned rectangle defined by `x`, `y`, `width`, and `height`.
```ts
import { Rectangle } from 'pixi.js';
const rect = new Rectangle(10, 10, 100, 50);
rect.contains(20, 20); // true
```
### `Circle`
Defined by `x`, `y` (center) and `radius`.
```ts
import { Circle } from 'pixi.js';
const circle = new Circle(50, 50, 25);
circle.contains(50, 75); // true
```
### `Ellipse`
Similar to `Circle`, but supports different width and height (radii).
```ts
import { Ellipse } from 'pixi.js';
const ellipse = new Ellipse(0, 0, 20, 10);
ellipse.contains(5, 0); // true
```
### `Polygon`
Defined by a list of points. Used for complex shapes and hit testing.
```ts
import { Polygon } from 'pixi.js';
const polygon = new Polygon([0, 0, 100, 0, 100, 100, 0, 100]);
polygon.contains(50, 50); // true
```
### `RoundedRectangle`
Rectangle with rounded corners, defined by a radius.
```ts
import { RoundedRectangle } from 'pixi.js';
const roundRect = new RoundedRectangle(0, 0, 100, 100, 10);
roundRect.contains(10, 10); // true
```
### `Triangle`
A convenience wrapper for defining triangles with three points.
```ts
import { Triangle } from 'pixi.js';
const triangle = new Triangle(0, 0, 100, 0, 50, 100);
triangle.contains(50, 50); // true
```
---
## Optional: `math-extras`
Importing `pixi.js/math-extras` extends `Point` and `Rectangle` with additional vector and geometry utilities.
### To enable:
```ts
import 'pixi.js/math-extras';
```
### Enhanced `Point` Methods
| Method | Description |
| ------------------------------- | ------------------------------------------------------------ |
| `add(other[, out])` | Adds another point to this one. |
| `subtract(other[, out])` | Subtracts another point from this one. |
| `multiply(other[, out])` | Multiplies this point with another point component-wise. |
| `multiplyScalar(scalar[, out])` | Multiplies the point by a scalar. |
| `dot(other)` | Computes the dot product of two vectors. |
| `cross(other)` | Computes the scalar z-component of the 3D cross product. |
| `normalize([out])` | Returns a normalized (unit-length) vector. |
| `magnitude()` | Returns the Euclidean length. |
| `magnitudeSquared()` | Returns the squared length (more efficient for comparisons). |
| `project(onto[, out])` | Projects this point onto another vector. |
| `reflect(normal[, out])` | Reflects the point across a given normal. |
### Enhanced `Rectangle` Methods
| Method | Description |
| ---------------------------- | ----------------------------------------------------- |
| `containsRect(other)` | Returns true if this rectangle contains the other. |
| `equals(other)` | Checks if all properties are equal. |
| `intersection(other[, out])` | Returns a new rectangle representing the overlap. |
| `union(other[, out])` | Returns a rectangle that encompasses both rectangles. |
---
## API Reference
- [Overview](https://pixijs.download/release/docs/maths.html)
- [Matrix](https://pixijs.download/release/docs/maths.Matrix.html)
- [Point](https://pixijs.download/release/docs/maths.Point.html)
- [ObservablePoint](https://pixijs.download/release/docs/maths.ObservablePoint.html)
- [Rectangle](https://pixijs.download/release/docs/maths.Rectangle.html)
- [Circle](https://pixijs.download/release/docs/maths.Circle.html)
- [Ellipse](https://pixijs.download/release/docs/maths.Ellipse.html)
- [Polygon](https://pixijs.download/release/docs/maths.Polygon.html)
- [RoundedRectangle](https://pixijs.download/release/docs/maths.RoundedRectangle.html)
- [Triangle](https://pixijs.download/release/docs/maths.Triangle.html)
---
## Textures
# Textures
Textures are one of the most essential components in the PixiJS rendering pipeline. They define the visual content used by Sprites, Meshes, and other renderable objects. This guide covers how textures are loaded, created, and used, along with the various types of data sources PixiJS supports.
## Texture Lifecycle
The texture system is built around two major classes:
- **`TextureSource`**: Represents a pixel source, such as an image, canvas, or video.
- **`Texture`**: Defines a view into a `TextureSource`, including sub-rectangles, trims, and transformations.
### Lifecycle Flow
```
Source File/Image -> TextureSource -> Texture -> Sprite (or other display object)
```
### Loading Textures
Textures can be loaded asynchronously using the `Assets` system:
```ts
const texture = await Assets.load('myTexture.png');
const sprite = new Sprite(texture);
```
### Preparing Textures
Even after you've loaded your textures, the images still need to be pushed to the GPU and decoded. Doing this for a large number of source images can be slow and cause lag spikes when your project first loads. To solve this, you can use the [Prepare](https://pixijs.download/release/docs/rendering.PrepareSystem.html) plugin, which allows you to pre-load textures in a final step before displaying your project.
## Texture vs. TextureSource
The `TextureSource` handles the raw pixel data and GPU upload. A `Texture` is a lightweight view on that source, with metadata such as trimming, frame rectangle, UV mapping, etc. Multiple `Texture` instances can share a single `TextureSource`, such as in a sprite sheet.
```ts
const sheet = await Assets.load('spritesheet.json');
const heroTexture = sheet.textures['hero.png'];
```
## Texture Creation
You can manually create textures using the constructor:
```ts
const mySource = new TextureSource({ resource: myImage });
const texture = new Texture({ source: mySource });
```
Set `dynamic: true` in the `Texture` options if you plan to modify its `frame`, `trim`, or `source` at runtime.
## Destroying Textures
Once you're done with a Texture, you may wish to free up the memory (both WebGL-managed buffers and browser-based) that it uses. To do so, you should call `Assets.unload('texture.png')`, or `texture.destroy()` if you have created the texture outside of Assets.
This is a particularly good idea for short-lived imagery like cut-scenes that are large and will only be used once. If a texture is destroyed that was loaded via `Assets` then the assets class will automatically remove it from the cache for you.
## Unload Texture from GPU
If you want to unload a texture from the GPU but keep it in memory, you can call `texture.source.unload()`. This will remove the texture from the GPU but keep the source in memory.
```ts
// Load the texture
const texture = await Assets.load('myTexture.png');
// ... Use the texture
// Unload the texture from the GPU
texture.source.unload();
```
## Texture Types
PixiJS supports multiple `TextureSource` types, depending on the kind of input data:
| Texture Type | Description |
| --------------------- | ----------------------------------------------------------------- |
| **ImageSource** | HTMLImageElement, ImageBitmap, SVG's, VideoFrame, etc. |
| **CanvasSource** | HTMLCanvasElement or OffscreenCanvas |
| **VideoSource** | HTMLVideoElement with optional auto-play and update FPS |
| **BufferImageSource** | TypedArray or ArrayBuffer with explicit width, height, and format |
| **CompressedSource** | Array of compressed mipmaps (Uint8Array\[]) |
## Common Texture Properties
Here are some important properties of the `Texture` class:
- `frame`: Rectangle defining the visible portion within the source.
- `orig`: Original untrimmed dimensions.
- `trim`: Defines trimmed regions to exclude transparent space.
- `uvs`: UV coordinates generated from `frame` and `rotate`.
- `rotate`: GroupD8 rotation value for atlas compatibility.
- `defaultAnchor`: Default anchor when used in Sprites.
- `defaultBorders`: Used for 9-slice scaling.
- `source`: The `TextureSource` instance.
## Common TextureSource Properties
Here are some important properties of the `TextureSource` class:
- `resolution`: Affects render size relative to actual pixel size.
- `format`: Texture format (e.g., `rgba8unorm`, `bgra8unorm`, etc.)
- `alphaMode`: Controls how alpha is interpreted on upload.
- `wrapMode` / `scaleMode`: Controls how texture is sampled outside of bounds or when scaled.
- `autoGenerateMipmaps`: Whether to generate mipmaps on upload.
You can set these properties when creating a `TextureSource`:
```ts
texture.source.scaleMode = 'linear';
texture.source.wrapMode = 'repeat';
```
---
## API Reference
- [Texture](https://pixijs.download/release/docs/rendering.Texture.html)
- [TextureSource](https://pixijs.download/release/docs/rendering.TextureSource.html)
- [TextureStyle](https://pixijs.download/release/docs/rendering.TextureStyle.html)
- [RenderTexture](https://pixijs.download/release/docs/rendering.RenderTexture.html)
---
## Ticker
# Ticker
The `Ticker` class in PixiJS provides a powerful and flexible mechanism for executing callbacks on every animation frame. It's useful for managing game loops, animations, and any time-based updates.
```ts
import { Ticker } from 'pixi.js';
const ticker = new Ticker();
ticker.add((ticker) => {
console.log(`Delta Time: ${ticker.deltaTime}`);
});
// Start the ticker
ticker.start();
```
## Adding and Removing Listeners
The `Ticker` class allows you to add multiple listeners that will be called on every frame. You can also specify a context for the callback, which is useful for maintaining the correct `this` reference.
```ts
ticker.add(myFunction, myContext);
ticker.addOnce(myFunction, myContext);
ticker.remove(myFunction, myContext);
```
## Controlling the Ticker
```ts
ticker.start(); // Begin calling listeners every frame
ticker.stop(); // Pause the ticker and cancel the animation frame
```
To automatically start the ticker when a listener is added, enable `autoStart`:
```ts
ticker.autoStart = true;
```
## Prioritizing Listeners
Listeners can be assigned a priority. Higher values run earlier.
```ts
import { UPDATE_PRIORITY } from 'pixi.js';
ticker.add(fnA, null, UPDATE_PRIORITY.HIGH); // runs before...
ticker.add(fnB, null, UPDATE_PRIORITY.NORMAL); // ...this
```
Available constants include:
- `UPDATE_PRIORITY.HIGH = 50`
- `UPDATE_PRIORITY.NORMAL = 0`
- `UPDATE_PRIORITY.LOW = -50`
## Configuring FPS
Tickers allows FPS limits to control the update rate.
### `minFPS`
Caps how _slow_ frames are allowed to be. Used to clamp `deltaTime`:
```ts
ticker.minFPS = 30; // deltaTime will never act as if below 30 FPS
```
### `maxFPS`
Limits how _fast_ the ticker runs. Useful for conserving CPU/GPU:
```ts
ticker.maxFPS = 60; // will not tick faster than 60fps
```
Set to `0` to allow unlimited framerate:
```ts
ticker.maxFPS = 0;
```
---
## API Reference
- [Ticker](https://pixijs.download/release/docs/ticker.Ticker.html)
- [Application](https://pixijs.download/release/docs/app.Application.html)
---
## Mixing PixiJS and Three.js
# Mixing PixiJS and Three.js
In many projects, developers aim to harness the strengths of both 3D and 2D graphics. Combining the advanced 3D rendering capabilities of Three.js with the speed and versatility of PixiJS for 2D can result in a powerful, seamless experience. Together, these technologies create opportunities for dynamic and visually compelling applications. Lets see how to do this.
:::info NOTE
This guide assumes PixiJS will be used as the top layer to deliver UI over a 3D scene rendered by Three.js. However, developers can render either in any order, as many times as needed. This flexibility allows for creative and dynamic applications.
:::
---
### What You’ll Learn
- Setting up PixiJS and Three.js to share a single WebGL context.
- Using `resetState` to manage renderer states.
- Avoiding common pitfalls when working with multiple renderers.
---
### Setting Up
#### Step 1: Initialize Three.js Renderer and Scene
Three.js will handle the 3D rendering the creation of the dom element and context.
```javascript
const WIDTH = window.innerWidth;
const HEIGHT = window.innerHeight;
const threeRenderer = new THREE.WebGLRenderer({
antialias: true,
stencil: true, // so masks work in pixijs
});
threeRenderer.setSize(WIDTH, HEIGHT);
threeRenderer.setClearColor(0xdddddd, 1);
document.body.appendChild(threeRenderer.domElement);
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(70, WIDTH / HEIGHT);
camera.position.z = 50;
scene.add(camera);
const boxGeometry = new THREE.BoxGeometry(10, 10, 10);
const basicMaterial = new THREE.MeshBasicMaterial({ color: 0x0095dd });
const cube = new THREE.Mesh(boxGeometry, basicMaterial);
cube.rotation.set(0.4, 0.2, 0);
scene.add(cube);
```
:::info NOTE
We used the dom element and context created by the three.js renderer to pass to the pixijs renderer.
This was the simplest way to ensure that the two renderers were using the same WebGL context. You could have done it the other way round
if you wanted to.
:::
#### Step 2: Initialize PixiJS Renderer and Stage
PixiJS will handle the 2D overlay.
```javascript
const pixiRenderer = new PIXI.WebGLRenderer();
await pixiRenderer.init({
context: threeRenderer.getContext(),
width: WIDTH,
height: HEIGHT,
clearBeforeRender: false, // Prevent PixiJS from clearing the Three.js render
});
const stage = new PIXI.Container();
const amazingUI = new PIXI.Graphics()
.roundRect(20, 80, 100, 100, 5)
.roundRect(220, 80, 100, 100, 5)
.fill(0xffff00);
stage.addChild(amazingUI);
```
---
### Rendering Loop
To ensure smooth transitions between the renderers, reset their states before each render:
```javascript
function render() {
// Render the Three.js scene
threeRenderer.resetState();
threeRenderer.render(scene, camera);
// Render the PixiJS stage
pixiRenderer.resetState();
pixiRenderer.render({ container: stage });
requestAnimationFrame(render);
}
requestAnimationFrame(render);
```
---
### Example: Combining 3D and 2D Elements
Here’s the complete example integrating PixiJS and Three.js:
```ts
// Import required classes from PixiJS and Three.js
import { Container, Graphics, Text, WebGLRenderer } from 'pixi.js';
import * as THREE from 'three';
// Self-executing async function to set up the demo
(async () => {
// Initialize window dimensions
let WIDTH = window.innerWidth;
let HEIGHT = window.innerHeight;
// === THREE.JS SETUP ===
// Create Three.js WebGL renderer with antialiasing and stencil buffer
const threeRenderer = new THREE.WebGLRenderer({
antialias: true,
stencil: true,
});
// Configure Three.js renderer size and background color
threeRenderer.setSize(WIDTH, HEIGHT);
threeRenderer.setClearColor(0xdddddd, 1); // Light gray background
document.body.appendChild(threeRenderer.domElement);
// Create Three.js scene
const scene = new THREE.Scene();
// Set up perspective camera with 70° FOV
const threeCamera = new THREE.PerspectiveCamera(70, WIDTH / HEIGHT);
threeCamera.position.z = 50; // Move camera back to see the scene
scene.add(threeCamera);
// Create a simple cube mesh
const boxGeometry = new THREE.BoxGeometry(30, 30, 30);
const basicMaterial = new THREE.MeshBasicMaterial({ color: 0x0095dd }); // Blue color
const cube = new THREE.Mesh(boxGeometry, basicMaterial);
scene.add(cube);
// === PIXI.JS SETUP ===
// Create PixiJS renderer that shares the WebGL context with Three.js
const pixiRenderer = new WebGLRenderer();
// Initialize PixiJS renderer with shared context
await pixiRenderer.init({
context: threeRenderer.getContext(),
width: WIDTH,
height: HEIGHT,
clearBeforeRender: false, // Don't clear the canvas as Three.js will handle that
});
// Create PixiJS scene graph
const stage = new Container();
// Create a yellow rounded rectangle UI element
const uiLayer = new Graphics().roundRect(20, 80, 300, 300, 20).fill(0xffff00);
// Add text overlay
const text = new Text({
text: 'Pixi and Three.js',
style: { fontFamily: 'Arial', fontSize: 24, fill: 'black' },
});
uiLayer.addChild(text);
stage.addChild(uiLayer);
// Animation loop
function loop() {
// Rotate cube continuously
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
// Animate UI layer position using sine wave
uiLayer.y = ((Math.sin(Date.now() * 0.001) + 1) * 0.5 * WIDTH) / 2;
// Render Three.js scene
threeRenderer.resetState();
threeRenderer.render(scene, threeCamera);
// Render PixiJS scene
pixiRenderer.resetState();
pixiRenderer.render({ container: stage });
// Continue animation loop
requestAnimationFrame(loop);
}
// Start animation loop
requestAnimationFrame(loop);
// Handle window resizing
window.addEventListener('resize', () => {
WIDTH = window.innerWidth;
HEIGHT = window.innerHeight;
// Update Three.js renderer
threeRenderer.setSize(WIDTH, HEIGHT);
// Update Three.js camera aspect ratio so it renders correctly
threeCamera.aspect = WIDTH / HEIGHT;
threeCamera.updateProjectionMatrix();
// Update PixiJS renderer
pixiRenderer.resize(WIDTH, HEIGHT);
});
})();
```
---
### Gotchas
- **Enable Stencil Buffers:**
- When creating the Three.js renderer, ensure `stencil` is set to `true`. This allows PixiJS masks to work correctly.
- **Keep Dimensions in Sync:**
- Ensure both renderers use the same `width` and `height` to avoid visual mismatches—so be careful when resizing one, you need to resize the other!
- **Pass the WebGL Context:**
- Pass the WebGL context from Three.js to PixiJS during initialization using `pixiRenderer.init({ context: threeRenderer.getContext() });`.
- **Disable Clear Before Render:**
- Set `clearBeforeRender: false` when initializing the PixiJS renderer. This prevents PixiJS from clearing the Three.js content that was rendered before it.
- Alternatively you can set `clear: false` in the `pixiRenderer.render()` call. eg `pixiRenderer.render({ container: stage, clear: false });`.
- **Manage Render Order:**
- In this example, Three.js is rendered first, followed by PixiJS for UI layers. However, this order is flexible. You can render pixi -> three -> pixi is you want, just make sure you reset the state when switching renderer.
- **Separate Resources:**
- Remember that resources like textures are not shared between PixiJS and Three.js. A PixiJS texture cannot be directly used as a Three.js texture and vice versa.
---
### Conclusion
Mixing PixiJS and Three.js can be a powerful way to create dynamic and visually appealing applications. By carefully managing the rendering loop and states, you can achieve seamless transitions between 3D and 2D layers. This approach allows you to leverage the strengths of both technologies, creating applications that are both visually stunning and performant.
This technique can be used with other renderers too - as long as they have their own way of resetting their state (which the main ones do) you can mix them. Popular 3D engines like Babylon.js and PlayCanvas both support state management through their respective APIs, making them compatible with this mixing approach. This gives you the flexibility to choose the 3D engine that best suits your needs while still leveraging PixiJS's powerful 2D capabilities.
---
## v8 Migration Guide
# v8 Migration Guide
Welcome to the PixiJS v8 Migration Guide! This document is designed to help you smoothly transition your projects from PixiJS v7 to the latest and greatest PixiJS v8. Please follow these steps to ensure a successful migration.
## Table of Contents
1. [Introduction](#introduction)
2. [Breaking Changes](#breaking-changes)
3. [Deprecated Features](#deprecated-features)
4. [Resources](#resources)
## 1. Introduction {#introduction}
PixiJS v8 introduces several exciting changes and improvements that dramatically enhance the performance of the renderer. While we've made efforts to keep the migration process as smooth as possible, some breaking changes are inevitable. This guide will walk you through the necessary steps to migrate your PixiJS v7 project to PixiJS v8.
## 2. Breaking Changes {#breaking-changes}
Before diving into the migration process, let's review the breaking changes introduced in PixiJS v8. Make sure to pay close attention to these changes as they may impact your existing codebase.
### Should I Upgrade?
Generally, the answer is yes! But currently, there may be reasons that suggest it's best not to upgrade just yet. Ask yourself the following question:
- **Does your project leverage existing Pixi libraries that have not yet been migrated to v8?**
We are working hard to migrate our key libraries to v8 but did not want this to be a blocker for those who are using pure Pixi. This means some libraries will not have a v8 counterpart just yet. It's best to hold off on migration if this is the case for you.
**Migrated**
- Filters
- Sound
- Gif
- Storybook
- UI
- Open Games
**Migrating Right Now:**
- React
- Spine (esoteric version)
**To Be Migrated:**
- Pixi layers (rather than migrating this, we will likely incorporate it directly into PixiJS v8 as a feature)
### **New Package Structure**
Since version 5, PixiJS has utilized individual sub-packages to organize its codebase into smaller units. However, this approach led to issues, such as conflicting installations of different PixiJS versions, causing complications with internal caches.
In v8, PixiJS has reverted to a single-package structure. While you can still import specific parts of PixiJS, you only need to install the main package.
**Old:**
```ts
import { Application } from '@pixi/app';
import { Sprite } from '@pixi/sprite';
```
**New:**
```ts
import { Application, Sprite } from 'pixi.js';
```
#### Custom Builds
PixiJS uses an "extensions" system to add renderer functionality. By default, PixiJS includes many extensions for a comprehensive out-of-the-box experience. However, for full control over features and bundle size, you can manually import specific PixiJS components.
```ts
// imported by default
import 'pixi.js/accessibility';
import 'pixi.js/app';
import 'pixi.js/events';
import 'pixi.js/filters';
import 'pixi.js/sprite-tiling';
import 'pixi.js/text';
import 'pixi.js/text-bitmap';
import 'pixi.js/text-html';
import 'pixi.js/graphics';
import 'pixi.js/mesh';
import 'pixi.js/sprite-nine-slice';
// not added by default, everyone needs to import these manually
import 'pixi.js/advanced-blend-modes';
import 'pixi.js/unsafe-eval';
import 'pixi.js/prepare';
import 'pixi.js/math-extras';
import 'pixi.js/dds';
import 'pixi.js/ktx';
import 'pixi.js/ktx2';
import 'pixi.js/basis';
import { Application } from 'pixi.js';
const app = new Application();
await app.init({
manageImports: false, // disable importing the above extensions
});
```
When initializing the application, you can disable the auto-import feature, preventing PixiJS from importing any extensions automatically. You'll need to import them manually, as demonstrated above.
It should also be noted that the `pixi.js/text-bitmap`, also add `Assets` loading functionality.
Therefore if you want to load bitmap fonts **BEFORE** initialising the renderer, you will need to import this extension.
```ts
import 'pixi.js/text-bitmap';
import { Assets, Application } from 'pixi.js';
await Assets.load('my-font.fnt'); // If 'pixi.js/text-bitmap' is not imported, this will not load
await new Application().init();
```
### **Async Initialisation**
PixiJS will now need to be initialised asynchronously. With the introduction of the WebGPU renderer PixiJS will now need to be awaited before being used
**Old:**
```ts
import { Application } from 'pixi.js';
const app = new Application();
// do pixi things
```
**New:**
```ts
import { Application } from 'pixi.js';
const app = new Application();
(async () => {
await app.init({
// application options
});
// do pixi things
})();
```
With this change it also means that the `ApplicationOptions` object can now be passed into the `init` function instead of the constructor.
### ** Texture adjustments **
Textures structures have been modified to simplify what was becoming quite a mess behind the scenes in v7.
Textures no longer know or manage loading of resources. This needs to be done upfront by you or the assets manager. Textures expect full loaded resources only. This makes things so much easier to manage as the validation of a texture can essentially be done at construction time and left at that!
BaseTexture no longer exists. In stead we now have a variety of TextureSources available. A texture source combines the settings of a texture with how to upload and use that texture. In v8 there are the following texture sources:
TextureSource - a vanilla texture that you can render too or upload however you wish. (used mainly by render textures)
ImageSource - a texture source that contains an image resource of some kind (eg ImageBitmap or html image)
CanvasSource - a canvas source that contains a canvas. Used mainly for rendering canvases or rendering to a canvas (webGPU)
VideoSource - a texture source that contains a video. Takes care of updating the texture on the GPU to ensure that they stay in sync.
BufferSource - a texture source that contains a buffer. What ever you want really! make sure your buffer type and format are compatible!
CompressedSource - a texture source that handles compressed textures. Used by the GPU compressed texture formats.
Whilst the majority of the time `Assets` will return Textures you may want to make you own! More power to ya!
To create a texture source the signature differs from baseTexture. example:
```
const image = new Image();
image.onload = function(){
// create a texture source
const source = new ImageSource({
resource: image,
});
// create a texture
const texture = new Texture({
source
});
}
image.src = 'myImage.png';
```
### **Graphics API Overhaul**
There are a few key changes to the Graphics API. In fact this is probably the most changed part of v8. We have added deprecations where possible but below is the rundown of changes:
- Instead of beginning a fill or a stroke and then building a shape, v8 asks you to build your shape and then stroke / fill it. The terminology of `Line` has been replaced with the terminology of `Stroke`
**Old:**
```ts
// red rect
const graphics = new Graphics()
.beginFill(0xff0000)
.drawRect(50, 50, 100, 100)
.endFill();
// blue rect with stroke
const graphics2 = new Graphics()
.lineStyle(2, 'white')
.beginFill('blue')
.circle(530, 50, 140, 100)
.endFill();
```
**New:**
```ts
// red rect
const graphics = new Graphics().rect(50, 50, 100, 100).fill(0xff0000);
// blue rect with stroke
const graphics2 = new Graphics()
.rect(50, 50, 100, 100)
.fill('blue')
.stroke({ width: 2, color: 'white' });
```
- Shape functions have been renamed. Each drawing function has been simplified into a shorter version of its name. They have the same parameters though:
| v7 API Call | v8 API Equivalent |
| ------------------ | ----------------- |
| drawChamferRect | chamferRect |
| drawCircle | circle |
| drawEllipse | ellipse |
| drawFilletRect | filletRect |
| drawPolygon | poly |
| drawRect | rect |
| drawRegularPolygon | regularPoly |
| drawRoundedPolygon | roundPoly |
| drawRoundedRect | roundRect |
| drawRoundedShape | roundShape |
| drawStar | star |
- fills functions expect `FillStyle` options or a color, rather than a string of parameters. This also replaces `beginTextureFill`
**Old:**
```ts
const rect = new Graphics()
.beginTextureFill({ texture: Texture.WHITE, alpha: 0.5, color: 0xff0000 })
.drawRect(0, 0, 100, 100)
.endFill()
.beginFill(0xffff00, 0.5)
.drawRect(100, 0, 100, 100)
.endFill();
```
**New:**
```ts
const rect = new Graphics()
.rect(0, 0, 100, 100)
.fill({ texture: Texture.WHITE, alpha: 0.5, color: 0xff0000 })
.rect(100, 0, 100, 100)
.fill({ color: 0xffff00, alpha: 0.5 });
```
- stokes functions expect `StrokeStyle` options or a color, rather than a string of parameters. This also replaces `lineTextureStyle`
**Old:**
```ts
const rect = new Graphics()
.lineTextureStyle({texture:Texture.WHITE, width:10, color:0xFF0000})
.drawRect(0, 0, 100, 100)
.endFill()
.lineStyle(2, 0xFEEB77);
.drawRect(100, 0, 100, 100)
.endFill();
```
**New:**
```ts
const rect = new Graphics()
.rect(0, 0, 100, 100)
.stroke({ texture: Texture.WHITE, width: 10, color: 0xff0000 })
.rect(100, 0, 100, 100)
.stroke({ color: 0xfeeb77, width: 2 });
```
- holes now make use of a new `cut` function. As with `stroke` and `fill`, `cut` acts on the previous shape.
**Old:**
```ts
const rectAndHole = new Graphics()
.beginFill(0x00ff00)
.drawRect(0, 0, 100, 100)
.beginHole()
.drawCircle(50, 50, 20)
.endHole()
.endFill();
```
**New:**
```ts
const rectAndHole = new Graphics()
.rect(0, 0, 100, 100)
.fill(0x00ff00)
.circle(50, 50, 20)
.cut();
```
- `GraphicsGeometry` has been replaced with `GraphicsContext` this allows for sharing of `Graphics` data more efficiently.
**Old:**
```ts
const rect = new Graphics()
.beginFill(0xff0000)
.drawRect(50, 50, 100, 100)
.endFill();
const geometry = rect.geometry;
const secondRect = new Graphics(geometry);
```
**New:**
```ts
const context = new GraphicsContext().rect(50, 50, 100, 100).fill(0xff0000);
const rect = new Graphics(context);
const secondRect = new Graphics(context);
```
### Shader changes
As we now need to accommodate both WebGL and WebGPU shaders, the way they are constructed has been tweaked to take this into account. The main differences you will notice (this is for shaders in general) is that Textures are no longer considered uniforms (as in they cannot be included in a uniform group). Instead we have the concept of resources. A resource can be a few things including:
- TextureSource - A source texture `myTexture.source`
- TextureStyle - A texture style `myTexture.style`
- UniformGroup - A collection of number based uniforms `myUniforms = new UniformGroup({})`
- BufferResource - A buffer that is treated as a uniform group (advanced)
creating a webgl only shader now looks like this:
**old**
```ts
const shader = PIXI.Shader.from(vertex, fragment, uniforms);
```
**new**
just WebGL
```ts
const shader = Shader.from({
gl: { vertex, fragment },
resources, // resource used from above including uniform groups
});
```
WebGL and WebGPU
```ts
const shader = Shader.from({
gl: { vertex, fragment },
gpu: {
vertex: {
entryPoint: 'mainVert',
source,
},
fragment: {
entryPoint: 'mainFrag',
source,
},
},
resources, // resource used from above including uniform groups
});
```
Uniforms are also constructed in a slightly different way. When creating them, you now provide the type of variable you want it to be.
**old**
```ts
const uniformGroup = new UniformGroup({
uTime: 1,
});
uniformGroup.uniforms.uTime = 100;
```
**new**
```ts
const uniformGroup = new UniformGroup({
uTime:{value:1, type:'f32',
});
uniformGroup.uniforms.uTime = 100; // still accessed the same!
```
The best way to play and fully and get to know this new setup please check out the Mesh and Shader examples:
**old**: [v7 example](https://pixijs.com/7.x/examples/mesh-and-shaders/triangle-color)
**new**: [v8 example](https://pixijs.com/8.x/examples/mesh-and-shaders/triangle-color)
### Filters
Filters work almost exactly the same, unless you are constructing a custom one. If this is the case, the shader changes mentioned above need to taken into account.
**old**
```ts
const filter = new Filter(vertex, fragment, {
uTime: 0.0,
});
```
**new**
```ts
const filter = new Filter({
glProgram: GlProgram.from({
fragment,
vertex,
}),
resources: {
timeUniforms: {
uTime: { value: 0.0, type: 'f32' },
},
},
});
```
**old**: [v7 example](https://pixijs.com/7.x/examples/filters-advanced/custom)
**new**: [v8 example](https://pixijs.com/8.x/examples/filters-advanced/custom)
If you're using the [community filters](https://github.com/pixijs/filters), note that the `@pixi/filter-*` packages are no-longer maintained for v8, however, you can import directly from the `pixi-filters` package as sub-modules.
**\*old**
```ts
import { AdjustmentFilter } from '@pixi/filter-adjustment';
```
**\*new**
```ts
import { AdjustmentFilter } from 'pixi-filters/adjustment';
```
---
### ParticleContainer
`ParticleContainer` has been reworked in v8 to allow for far more particles than before. There are a few key changes you should be aware of:
A `ParticleContainer` no longer accepts sprites as its children. Instead, it requires a `Particle` class (or an object that implements the `IParticle` interface), which follows this interface:
```
export interface IParticle
{
x: number;
y: number;
scaleX: number;
scaleY: number;
anchorX: number;
anchorY: number;
rotation: number;
color: number;
texture: Texture;
}
```
The reason for this change is that sprites come with many extra properties and events that are generally unnecessary when dealing with large numbers of particles. This approach explicitly removes any ambiguity we had in v7, such as "Why doesn't my sprite work with filters?" or "Why can't I nest children in my sprites?" It’s a bit more predictable. Additionally, due to the lightweight nature of particles, this means we can render far more of them!
So, no functionality is lost—just an API tweak with a massive performance boost!
Particles are also not stored in the `children` array of the `ParticleContainer`, as particles are not technically part of the scene graph (for performance reasons). Instead, they are stored in a flat list called `particleChildren`, which is part of the `ParticleContainer` class. You can modify this array directly for extra speed, or you can use the `addParticle` and `removeParticle` methods to manage your particles.
Another optimization is that `ParticleContainer` does not calculate its own bounds, as doing so would negate the performance gains we've created! Instead, it's up to you to provide a `boundsArea` when initializing the `ParticleContainer`.
---
**OLD**
```ts
const container = new ParticleContainer();
for (let i = 0; i {
sprite.onViewUpdate;
});
```
The act of adding and removing the event when a sprite's texture was changed led to an unacceptable performance drop, especially when swapping many textures (imagine shooting games with lots of keyframe textures swapping). This is why we now leave that responsibility to the user.
- New Container culling approach
With this version of PixiJS we have changed how the `cullable` property works on containers. Previously culling was done for you automatically during the render loop. However, we have moved this logic out and provided users the ability to control when culling happens themselves.
With this change we have added a couple of new properties:
- `cullable` - Whether or not the container can be culled
- `cullArea` - A cull area that will be used instead of the bounds of the container
- `cullableChildren` - Whether or not the containers children can be culled. This can help optimise large scenes
**New:**
```ts
const container = new Container();
const view = new Rectangle(0, 0, 800, 600);
container.cullable = true;
container.cullArea = new Rectangle(0, 0, 400, 400);
container.cullableChildren = false;
Culler.shared.cull(myContainer, view);
renderer.render(myContainer);
```
There is also a `CullerPlugin` that can be used to automatically call `Culler.shared.cull` every frame if you want to simulate the old behaviour.
```ts
import { extensions, CullerPlugin } from 'pixi.js';
extensions.add(CullerPlugin);
```
- Renamed several mesh classes
- renamed `SimpleMesh` -> `MeshSimple`
- renamed `SimplePlane` -> `MeshPlane`
- renamed `SimpleRope` -> `MeshRope`
- Deprecations for `Assets` removed
**Old:**
```ts
import { Assets } from 'pixi.js';
Assets.add('bunny', 'bunny.png');
```
**New:**
```ts
import { Assets } from 'pixi.js';
Assets.add({ alias: 'bunny', src: 'bunny.png' });
```
- `settings` object has been removed
**Old:**
```ts
import { settings, BrowserAdapter } from 'pixi.js';
settings.RESOLUTION = 1;
settings.FAIL_IF_MAJOR_PERFORMANCE_CAVEAT = false;
settings.ADAPTER = BrowserAdapter;
```
**New:**
```ts
import { AbstractRenderer, DOMAdapter, BrowserAdapter } from 'pixi.js';
// Can also be passed into the renderer directly e.g `autoDetectRenderer({resolution: 1})`
AbstractRenderer.defaultOptions.resolution = 1;
// Can also be passed into the renderer directly e.g `autoDetectRenderer({failIfMajorPerformanceCaveat: false})`
AbstractRenderer.defaultOptions.failIfMajorPerformanceCaveat = false;
// See below for more information about changes to the adapter
DOMAdapter.set(BrowserAdapter);
```
- Adapter and Web Worker Changes
- `settings.ADAPTER` has been removed and replaced with `DOMAdapter`
- `DOMAdapter` is a static class that can be used to set the adapter for the entire application
- PixiJS has two adapters built in `BrowserAdapter` and `WebWorkerAdapter`
- `BrowserAdapter` is the default adapter and is used when running in the browser
- `WebWorkerAdapter` is used when running in a web worker
**Old:**
```ts
import { settings, WebWorkerAdapter } from 'pixi.js';
settings.ADAPTER = WebWorkerAdapter;
settings.ADAPTER.createCanvas();
```
**New:**
```ts
import { DOMAdapter, WebWorkerAdapter } from 'pixi.js';
DOMAdapter.set(WebWorkerAdapter);
DOMAdapter.get().createCanvas();
```
- Application type now accepts Renderer instead of view by @Zyie in https://github.com/pixijs/pixijs/pull/9740
This is to allow `app.renderer` to be typed correctly
**Old:**
```ts
const app = new Application();
```
**New:**
```ts
// WebGL or WebGPU renderer
const app = new Application>();
// WebGL specific renderer
const app = new Application>();
// WebGPU specific renderer
const app = new Application>();
```
* `Texture.from` no longer will load a texture from a URL.
When using `Texture.from` you will need to pass in a source such as `CanvasSource`/`ImageSource`/`VideoSource` or a resource such as `HTMLImageElement`/`HTMLCanvasElement`/`HTMLVideoElement` or a string that has been loaded through `Assets.load`
**Old:**
```ts
import { Texture } from 'pixi.js';
const texture = Texture.from('https://i.imgur.com/IaUrttj.png');
```
**New:**
```ts
import { Assets, Texture } from 'pixi.js';
await Assets.load('https://i.imgur.com/IaUrttj.png');
const texture = Texture.from('https://i.imgur.com/IaUrttj.png');
```
- The `Ticker`'s callback will now pass the `Ticker` instance instead of the delta time.
This is to allow for more control over what unit of time is used.
**Old:**
```ts
Ticker.shared.add((dt) => {
bunny.rotation += dt;
});
```
**New:**
```ts
Ticker.shared.add((ticker) => {
bunny.rotation += ticker.deltaTime;
});
```
- Text parsers have been renamed
- `TextFormat` -> `bitmapFontTextParser`
- `XMLStringFormat` -> `bitmapFontXMLStringParser`
- `XMLFormat` -> `bitmapFontXMLParser`
- The default `eventMode` is now `passive` instead of `auto`
- `utils` has been removed. All the functions are available as direct imports.
**Old:**
```ts
import { utils } from 'pixi.js';
utils.isMobile.any();
```
**New:**
```ts
import { isMobile } from 'pixi.js';
isMobile.any();
```
- `container.getBounds()` now returns a [`Bounds`](https://pixijs.download/release/docs/rendering.Bounds.html) object instead of a [`Rectangle`](https://pixijs.download/release/docs/maths.Rectangle.html) object. You can access the rectangle by using `container.getBounds().rectangle` instead.
**Old:**
```ts
const bounds = container.getBounds();
```
**New:**
```ts
const bounds = container.getBounds().rectangle;
```
- `container.cacheAsBitmap` has been replaced with `container.cacheAsTexture()`. They do the same things, except we changed the name `cacheAsTexture` as the Bitmap terminology is not really relevant to PixiJS.
**Old:**
```ts
container.cacheAsBitmap = true;
```
**New:**
```ts
container.cacheAsTexture(true);
```
## 3. Deprecated Features {#deprecated-features}
Certain features from PixiJS v7 have been deprecated in v8. While they will still work, it's recommended to update your code to use the new alternatives. Refer to the deprecated features section for details on what to replace them with.
- Leaf nodes no longer allow children
Only `Containers` can have children. This means that `Sprite`, `Mesh`, `Graphics` etc can no longer have children.
To replicate the old behaviour you can create a `Container` and add the leaf nodes to it.
**Old:**
```ts
const sprite = new Sprite();
const spriteChild = new Sprite();
sprite.addChild(spriteChild);
```
**New:**
```ts
const container = new Container();
const sprite = new Sprite();
const spriteChild = new Sprite();
container.addChild(sprite);
container.addChild(spriteChild);
```
- `Application.view` replaced with `Application.canvas`
**Old:**
```ts
const app = new Application({ view: document.createElement('canvas') });
document.body.appendChild(app.view);
```
**New:**
```ts
const app = new Application();
await app.init({ view: document.createElement('canvas') });
document.body.appendChild(app.canvas);
```
- `NineSlicePlane` renamed to `NineSliceSprite`
- `SCALE_MODES` replaced with `ScaleMode` strings
- `SCALE_MODES.NEAREST` -> `'nearest'`,
- `SCALE_MODES.LINEAR` -> `'linear'`,
- `WRAP_MODES` replaced with `WrapMode` strings
- `WRAP_MODES.CLAMP` -> `'clamp-to-edge'`,
- `WRAP_MODES.REPEAT` -> `'repeat'`,
- `WRAP_MODES.MIRRORED_REPEAT` -> `'mirror-repeat'`,
- `DRAW_MODES` replaced with `Topology` strings
- `DRAW_MODES.POINTS` -> `'point-list'`,
- `DRAW_MODES.LINES` -> `'line-list'`,
- `DRAW_MODES.LINE_STRIP` -> `'line-strip'`,
- `DRAW_MODES.TRIANGLES` -> `'triangle-list'`,
- `DRAW_MODES.TRIANGLE_STRIP` -> `'triangle-strip'`,
- Constructors have largely been changed to accept objects instead of multiple arguments
**Old:**
```ts
const blurFilter = new BlurFilter(8, 4, 1, 5);
const displacementFilter = new DisplacementFilter(sprite, 5);
const meshGeometry = new MeshGeometry(vertices, uvs, index);
const mesh = new Mesh(geometry, shader, state, drawMode);
const plane = new PlaneGeometry(width, height, segWidth, segHeight);
const nineSlicePlane = new NineSlicePlane(
texture,
leftWidth,
topHeight,
rightWidth,
bottomHeight,
);
const tileSprite = new TileSprite(texture, width, height);
const text = new Text('Hello World', style);
const bitmapText = new BitmapText('Hello World', style);
const htmlText = new HTMLText('Hello World', style);
```
**New:**
```ts
const blurFilter = new BlurFilter({
blur: 8,
quality: 4,
resolution: 1,
kernelSize: 5,
});
const displacementFilter = new DisplacementFilter({
sprite,
scale: 5,
});
const meshGeometry = new MeshGeometry({
positions: vertices,
uvs,
indices: index,
topology: 'triangle-list';
shrinkBuffersToFit: boolean;
});
const mesh = new Mesh({
geometry
shader
texture
});
const plane = new PlaneGeometry({
width,
height,
verticesX: segWidth,
verticesY: segHeight,
});
const nineSliceSprite = new NineSliceSprite({
texture,
leftWidth,
topHeight,
rightWidth,
bottomHeight,
});
const tileSprite = new TileSprite({
texture,
width,
height,
});
const text = new Text({
text: 'Hello World',
style,
});
const bitmapText = new BitmapText({
text:'Hello World',
style,
});
const htmlText = new HTMLText({
text:'Hello World',
style,
});
```
- `container.name` is now `container.label`
## 4. Resources {#resources}
- [PixiJS v8 Release Notes](https://github.com/pixijs/pixijs/releases?q=v8.0.0&expanded=true)
- [PixiJS Discord](https://discord.gg/CPTjeb28nH)
- [PixiJS Issues](https://github.com/pixijs/pixijs/issues)
---
## FAQ
# FAQ
## What is PixiJS for?
Everything! Pixi.js is a rendering library that will allow you to create rich,
interactive graphic experiences, cross-platform applications, and games without
having to dive into the WebGL API or grapple with the intricacies of browser and
device compatibility. Killer performance with a clean API, means not only will
your content be better - but also faster to build!
## Is PixiJS free?
PixiJS is and always will be free and Open Source. That said, financial contributions
are what make it possible to push PixiJS further, faster. Contributions allow us to
commission the PixiJS developer community to accelerate feature development and create
more in-depth documentation. Support Us by making a contribution via Open Collective. Go on! It will be a massive help AND make you feel good about yourself, win win ;)
## Where do I get it?
Visit our GitHub page to download the very latest version of PixiJS. This is the most up-to-date resource for PixiJS and should always be your first port of call to make sure you are using the latest version. Just click the 'Download' link in the navigation.
## How do I get started?
Right here! Take a look through the Resources section for a wealth of information including documentation, forums, tutorials and the Goodboy blog.
## Why should I use PixiJS?
Because you care about speed. PixiJS' #1 mantra has always been speed. We really do feel the need! We do everything we can to make PixiJS as streamlined, efficient and fast as possible, whilst balancing it with offering as many crucial and valuable features as we can.
## Is PixiJS a game engine?
No. PixiJS is what we've come to think of as a "creation engine". Whilst it is extremely good for making games, the core essence of PixiJS is simply moving things around on screens as quickly and efficiently as possible. It does of course happen that it is absolutely brilliant for making games though!
## Who makes PixiJS?
PixiJS is maintained by three core developers who work on the project part-time:
- Mat Groves ([@GoodBoyDigital](https://github.com/GoodBoyDigital))
- Sean Burns ([@Zyie](https://github.com/Zyie))
- Matt Karl ([@bigtimebuddy](https://github.com/bigtimebuddy))
The project thrives thanks to our highly active community of contributors and sponsors. As part-time maintainers, your sponsorship directly supports our ability to improve PixiJS, fix bugs, and create better documentation. Consider supporting our work through [GitHub Sponsors](https://github.com/sponsors/pixijs) or [Open Collective](https://opencollective.com/pixijs).
## I found a bug. What should I do?
Two things - lets us know via the PixiJS GitHub community and even better yet, if you know how, post a fix! Our Community is stronger in numbers so we're always keen to welcome new contributors into the team to help us shape what PixiJS becomes next.
---
## Culler Plugin
# Culler Plugin
The `CullerPlugin` automatically skips rendering for offscreen objects in your scene. It does this by using the renderer's screen bounds to determine whether containers (and optionally their children) intersect the view. If they don't, they are **culled**, reducing rendering and update overhead.
PixiJS does not enable this plugin by default. You must manually register it using the `extensions` system.
## When Should You Use It?
Culling is ideal for:
- Large scenes with many offscreen elements
- Scrollable or camera-driven environments (e.g. tilemaps, world views)
- Optimizing render performance without restructuring your scene graph
## Usage
```ts
const app = new Application();
await app.init({
width: 800,
height: 600,
backgroundColor: 0x222222,
});
extensions.add(CullerPlugin);
const world = new Container();
world.cullable = true;
world.cullableChildren = true;
const sprite = new Sprite.from('path/to/image.png');
sprite.cullable = true; // Enable culling for this sprite
world.addChild(sprite);
app.stage.addChild(world);
```
### Enabling the Culler Plugin
To enable automatic culling in your application:
```ts
import { extensions, CullerPlugin } from 'pixi.js';
extensions.add(CullerPlugin);
```
This will override the default `render()` method on your `Application` instance to call `Culler.shared.cull()` before rendering:
```ts
// Internally replaces:
app.renderer.render({ container: app.stage });
// With:
Culler.shared.cull(app.stage, app.renderer.screen);
app.renderer.render({ container: app.stage });
```
### Configuring Containers for Culling
By default, containers are **not culled**. To enable culling for a container, set the following properties:
```ts
container.cullable = true; // Enables culling for this container
container.cullableChildren = true; // Enables recursive culling for children
```
### Optional: Define a Custom Cull Area
You can define a `cullArea` to override the default bounds check (which uses global bounds):
```ts
container.cullArea = new Rectangle(0, 0, 100, 100);
```
This is useful for containers with many children where bounding box calculations are expensive or inaccurate.
---
## Manual Culling with `Culler`
If you’re not using the plugin but want to manually cull before rendering:
```ts
import { Culler } from 'pixi.js';
const stage = new Container();
// Configure stage and children...
Culler.shared.cull(stage, { x: 0, y: 0, width: 800, height: 600 });
renderer.render({ container: stage });
```
---
## API Reference
- [CullerPlugin](https://pixijs.download/release/docs/app.CullerPlugin.html)
---
## Application
# Application
The `Application` class provides a modern, extensible entry point to set up rendering in PixiJS. It abstracts common tasks like renderer setup and ticker updates, and is designed to support both WebGL and WebGPU via async initialization.
## Creating an Application
Creating an application requires two steps: constructing an instance, then initializing it asynchronously using `.init()`:
```ts
import { Application } from 'pixi.js';
const app = new Application();
await app.init({
width: 800,
height: 600,
backgroundColor: 0x1099bb,
});
document.body.appendChild(app.canvas);
```
### ApplicationOptions Reference
The `.init()` method of `Application` accepts a `Partial` object with the following configuration options:
| Option | Type | Default | Description |
| ------------------------ | ----------------------------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `autoStart` | `boolean` | `true` | Whether to start rendering immediately after initialization. Setting to `false` will not stop the shared ticker if it's already running. |
| `resizeTo` | `Window \| HTMLElement` | — | Element to auto-resize the renderer to match. |
| `sharedTicker` | `boolean` | `false` | Use the shared ticker instance if `true`; otherwise, a private ticker is created. |
| `preference` | `'webgl' \| 'webgpu'` | `webgl` | Preferred renderer type. |
| `useBackBuffer` | `boolean` | `false` | _(WebGL only)_ Use the back buffer when required. |
| `forceFallbackAdapter` | `boolean` | `false` | _(WebGPU only)_ Force usage of fallback adapter. |
| `powerPreference` | `'high-performance' \| 'low-power'` | `undefined` | Hint for GPU power preference (WebGL & WebGPU). |
| `antialias` | `boolean` | — | Enables anti-aliasing. May impact performance. |
| `autoDensity` | `boolean` | — | Adjusts canvas size based on `resolution`. Applies only to `HTMLCanvasElement`. |
| `background` | `ColorSource` | — | Alias for `backgroundColor`. |
| `backgroundAlpha` | `number` | `1` | Alpha transparency for background (0 = transparent, 1 = opaque). |
| `backgroundColor` | `ColorSource` | `'black'` | Color used to clear the canvas. Accepts hex, CSS color, or array. |
| `canvas` | `ICanvas` | — | A custom canvas instance (optional). |
| `clearBeforeRender` | `boolean` | `true` | Whether the renderer should clear the canvas each frame. |
| `context` | `WebGL2RenderingContext \| null` | `null` | User-supplied rendering context (WebGL). |
| `depth` | `boolean` | — | Enable a depth buffer in the main view. Always `true` for WebGL. |
| `height` | `number` | `600` | Initial height of the renderer (in pixels). |
| `width` | `number` | `800` | Initial width of the renderer (in pixels). |
| `hello` | `boolean` | `false` | Log renderer info and version to the console. |
| `multiView` | `boolean` | `false` | Enable multi-canvas rendering. |
| `preferWebGLVersion` | `1 \| 2` | `2` | Preferred WebGL version. |
| `premultipliedAlpha` | `boolean` | `true` | Assume alpha is premultiplied in color buffers. |
| `preserveDrawingBuffer` | `boolean` | `false` | Preserve buffer between frames. Needed for `toDataURL`. |
| `resolution` | `number` | 1 | The resolution of the renderer. |
| `skipExtensionImports` | `boolean` | `false` | Prevent automatic import of default PixiJS extensions. |
| `textureGCActive` | `boolean` | `true` | Enable garbage collection for GPU textures. |
| `textureGCCheckCountMax` | `number` | `600` | Frame interval between GC runs (textures). |
| `textureGCMaxIdle` | `number` | `3600` | Max idle frames before destroying a texture. |
| `textureGCAMaxIdle` | `number` | — | (Appears undocumented; placeholder for internal GC controls.) |
### Customizing Application Options Per Renderer Type
You can also override properties based on the renderer type by using the `WebGLOptions` or `WebGPUOptions` interfaces. For example:
```ts
import { Application } from 'pixi.js';
const app = new Application();
await app.init({
width: 800,
height: 600,
backgroundColor: 0x1099bb,
webgl: {
antialias: true,
},
webgpu: {
antialias: false,
},
});
document.body.appendChild(app.canvas);
```
---
## Built-In Plugins
PixiJS includes:
- ✅ **Ticker Plugin** — Updates every frame → [Guide](./ticker-plugin.md)
- ✅ **Resize Plugin** — Resizes renderer/canvas → [Guide](./resize-plugin.md)
- ➕ **Optional: Culler Plugin** - Culls objects that are out of frame → [Guide](./culler-plugin.md)
---
## Creating a Custom Application Plugin
You can create custom plugins for the `Application` class. A plugin must implement the `ApplicationPlugin` interface, which includes `init()` and `destroy()` methods. You can also specify the `extension` type, which is `ExtensionType.Application` for application plugins.
Both functions are called with `this` set as the `Application` instance e.g `this.renderer` or `this.stage` is available.
The `init()` method is called when the application is initialized and passes the options from the `application.init` call, and the `destroy()` method is called when the application is destroyed.
```ts
import type { ApplicationOptions, ApplicationPlugin, ExtensionType } from 'pixi.js';
const myPlugin: ApplicationPlugin = {
extension: ExtensionType.Application;
init(options: ApplicationOptions) {
console.log('Custom plugin init:', this, options);
},
destroy() {
console.log('Custom plugin destroy');
},
};
```
Register with:
```ts
import { extensions } from 'pixi.js';
extensions.add(myPlugin);
```
### Adding Types
If you are using TypeScript, or are providing a plugin for others to use, you can extend the `ApplicationOptions` interface to include your custom plugins options.
```ts
declare global {
namespace PixiMixins {
interface ApplicationOptions {
myPlugin?: import('./myPlugin').PluginOptions | null;
}
}
}
await app.init({
myPlugin: {
customOption: true, // Now TypeScript will know about this option
},
});
```
---
## API Reference
- [Overview](https://pixijs.download/release/docs/app.html)
- [Application](https://pixijs.download/release/docs/app.Application.html)
- [ApplicationOptions](https://pixijs.download/release/docs/app.ApplicationOptions.html)
- [AutoDetectOptions](https://pixijs.download/release/docs/rendering.AutoDetectOptions.html)
- [WebGLOptions](https://pixijs.download/release/docs/rendering.WebGLOptions.html)
- [WebGPUOptions](https://pixijs.download/release/docs/rendering.WebGPUOptions.html)
- [SharedRendererOptions](https://pixijs.download/release/docs/rendering.SharedRendererOptions.html)
- [TickerPlugin](https://pixijs.download/release/docs/app.TickerPlugin.html)
- [ResizePlugin](https://pixijs.download/release/docs/app.ResizePlugin.html)
- [CullerPlugin](https://pixijs.download/release/docs/app.CullerPlugin.html)
---
## Resize Plugin
# Resize Plugin
The `ResizePlugin` provides automatic resizing functionality for PixiJS applications. When enabled, it listens to window or element resize events and resizes the application's renderer accordingly.
This is useful for:
- Making the canvas responsive to the browser window
- Maintaining aspect ratio or fitting to containers
- Handling layout changes without manual resize calls
By default, PixiJS adds this plugin when initializing an `Application`, but you can also register it manually if you're using a custom setup.
---
## Usage
```ts
import { Application } from 'pixi.js';
const app = new Application();
await app.init({
width: 800,
height: 600,
resizeTo: window,
});
```
### Default Behavior
- When using `Application.init()` with no overrides, the `ResizePlugin` is installed automatically:
- When `resizeTo` is set, the renderer automatically adjusts to match the dimensions of the target (`window` or `HTMLElement`).
- Resizing is throttled using `requestAnimationFrame` to prevent performance issues during rapid resize events.
- You can trigger a resize manually with `app.resize()` or cancel a scheduled resize with `app.cancelResize()`.
### Manual Registration
If you're managing extensions manually:
```ts
import { extensions, ResizePlugin } from 'pixi.js';
extensions.add(ResizePlugin);
```
### Custom Resize Target
You can specify a custom target for resizing. This is useful if you want to resize the canvas to fit a specific element rather than the entire window.
```ts
await app.init({
resizeTo: document.getElementById('game-container'),
});
```
---
## API Reference
- [`ResizePlugin`](https://pixijs.download/release/docs/app.ResizePlugin.html)
---
## Ticker Plugin
# Ticker Plugin
The `TickerPlugin` provides a built-in update loop for your PixiJS `Application`. This loop calls `.render()` at a regular cadence—by default, once per animation frame—and integrates with PixiJS's `Ticker` system for precise control over frame-based updates.
PixiJS includes this plugin automatically when you initialize an `Application`, but you can also opt out and add it manually.
## Usage
```ts
const app = new Application();
await app.init({
sharedTicker: false,
autoStart: true,
});
app.ticker.add((ticker) => {
// Custom update logic here
bunny.rotation += 1 * ticker.deltaTime;
});
```
### Default Behavior
The `TickerPlugin` is included automatically unless disabled:
```ts
const app = new Application();
await app.init({
autoStart: true, // Automatically starts the render loop
sharedTicker: false, // Use a dedicated ticker
});
```
### Manual Registration
If you're managing extensions yourself:
```ts
import { extensions, TickerPlugin } from 'pixi.js';
extensions.add(TickerPlugin);
```
# Shared vs Custom Ticker
The plugin supports two modes:
| Option | Description |
| --------------------- | ------------------------------------------------------------ |
| `sharedTicker: true` | Uses `Ticker.shared`, shared across all applications. |
| `sharedTicker: false` | Creates a private ticker instance scoped to the application. |
### Behavior Differences
- If using a **shared ticker**, other code may also be registering updates, so the order of execution can vary.
- If using a **custom ticker**, you get complete control over timing and update order.
---
## Lifecycle Control
You can manually stop and start the ticker:
```ts
app.stop(); // Stop automatic rendering
app.start(); // Resume
```
This is useful for:
- Pausing the game or animation
- Performance throttling on inactive tabs
- Managing visibility events
---
## API Reference
- [TickerPlugin](https://pixijs.download/release/docs/app.TickerPlugin.html)
- [Ticker](https://pixijs.download/release/docs/ticker.Ticker.html)
---
## Background Loader
# Background Loader
PixiJS provides a **background loader** that allows you to load assets in the background while your application is running. This is useful for loading large assets or multiple assets without blocking the main thread. This can help improve the responsiveness of your application, reduce the initial loading time, and potentially void showing multiple loading screens to the user.
## Loading Bundles
The most effective way to use the background loader is to load bundles of assets. Bundles are groups of assets that are related to each other in some way, such as all the assets for a specific screen or level in your game. By loading bundles in the background, you can ensure that the assets are available when you need them without blocking the main thread.
```ts
const manifest = {
bundles: [
{
name: 'home-screen',
assets: [
{ alias: 'flowerTop', src: 'https://pixijs.com/assets/flowerTop.png' },
],
},
{
name: 'game-screen',
assets: [
{ alias: 'eggHead', src: 'https://pixijs.com/assets/eggHead.png' },
],
},
],
};
// Initialize the asset system with a manifest
await Assets.init({ manifest });
// Start loading both bundles in the background
Assets.backgroundLoadBundle(['game-screen']);
// Load only the first screen assets immediately
const resources = await Assets.loadBundle('home-screen');
```
## Loading Individual Assets
You can also load individual assets in the background using the `Assets.backgroundLoad()` method. This is useful for loading assets that are not part of a bundle or for loading additional assets after the initial load.
```ts
// Load an individual asset in the background
Assets.backgroundLoad({
alias: 'flowerTop',
src: 'https://pixijs.com/assets/flowerTop.png',
});
// Load another asset in the background
Assets.backgroundLoad({
alias: 'eggHead',
src: 'https://pixijs.com/assets/eggHead.png',
});
```
## API Reference
- [Assets](https://pixijs.download/release/docs/assets.Assets.html)
- [BackgroundLoader](https://pixijs.download/release/docs/assets.BackgroundLoader.html)
---
## Compressed Textures
# Compressed Textures
Compressed textures significantly reduce memory usage and GPU upload time, especially on mobile devices or lower-end hardware. PixiJS supports multiple compressed texture formats, but **you must configure the appropriate loaders** before using them.
## Supported Compressed Texture Formats
PixiJS provides built-in support for several widely-used compressed texture formats:
| Format | File Extension | Description |
| --------- | -------------- | ----------------------------------------------------------------------- |
| **DDS** | `.dds` | DirectDraw Surface format, supports DXT variants (S3TC) |
| **KTX** | `.ktx` | Khronos format, supports ETC and other schemes |
| **KTX2** | `.ktx2` | Modern container supporting Basis Universal and Supercompressed formats |
| **Basis** | `.basis` | Highly compressed format that can transcode to multiple GPU formats |
## Registering Loaders
PixiJS does **not automatically include compressed texture support**. To use these formats, you must explicitly import the necessary loaders before loading any assets:
```ts
import 'pixi.js/dds';
import 'pixi.js/ktx';
import 'pixi.js/ktx2';
import 'pixi.js/basis';
```
:::info
You only need to import the loaders for the formats you're using. These imports must run **before** any call to `Assets.load`.
:::
## Using Compressed Textures in Assets
Once loaders are registered, you can load compressed textures just like any other asset:
```ts
import 'pixi.js/ktx2'; // Import the KTX2 loader
import { Assets } from 'pixi.js';
await Assets.load('textures/background.ktx2');
```
PixiJS will parse and upload the texture using the correct loader and GPU-compatible transcoding path based on the user's device.
---
## Integration with AssetPack
[**AssetPack**](https://pixijs.io/assetpack) supports automatic generation of compressed texture variants during the build step. You can:
- Convert `.png` or `.jpg` files into `.basis`, `.ktx2`, or `.dds` formats.
- Reference compressed files in your manifest using the same aliases or wildcard patterns.
- Use the **same manifest and loading workflow** — PixiJS will resolve and load the best available variant based on the device.
### Example
Your manifest might include:
```json
{
"bundles": [
{
"name": "scene",
"assets": [
{
"alias": "bg",
"src": ["assets/bg.ktx2", "assets/bg.basis", "assets/bg.png"]
}
]
}
]
}
```
PixiJS will try to load `bg.ktx2` or `bg.basis` first if the device supports it, falling back to `bg.png` as needed.
---
## Assets
# Assets
PixiJS has the `Assets` singleton which is used to streamline resource loading. It’s modern, Promise-based, cache-aware, and highly extensible—making it the one stop shop for all PixiJS resource management!
```ts
import { Assets } from 'pixi.js';
await Assets.init({ ... });
const texture = await Assets.load('path/to/hero.png');
```
## Key Capabilities
- **Asynchronous loading** of assets via Promises or async/await.
- **Caching** prevents redundant network requests.
- **Built-in support** for common media formats (images, video, fonts).
- **Custom parsers** and **resolvers** for flexibility.
- **Background loading, manifest-based bundles,** and **smart fallbacks**.
## Supported File Types
| Type | Extensions | Loaders |
| ------------------- | ---------------------------------------------------------------- | --------------------------------- |
| Textures | `.png`, `.jpg`, `.gif`, `.webp`, `.avif`, `.svg` | `loadTextures`, `loadSvg` |
| Video Textures | `.mp4`, `.m4v`, `.webm`, `.ogg`, `.ogv`, `.h264`, `.avi`, `.mov` | `loadVideoTextures` |
| Sprite Sheets | `.json` | `spritesheetAsset` |
| Bitmap Fonts | `.fnt`, `.xml`, `.txt` | `loadBitmapFont` |
| Web Fonts | `.ttf`, `.otf`, `.woff`, `.woff2` | `loadWebFont` |
| JSON | `.json` | `loadJson` |
| Text | `.txt` | `loadTxt` |
| Compressed Textures | `.basis`, `.dds`, `.ktx`, `.ktx2` | `loadBasis`, `loadDDS`, `loadKTX` |
> Need more? Add custom parsers!
---
## Getting started
### Loading Assets
Loading an asset with PixiJS is as simple as calling `Assets.load()` and passing in the asset’s URL. This function returns a `Promise` that resolves to the loaded resource—whether that’s a texture, font, JSON, or another supported format.
You can provide either an **absolute URL** (e.g. from a CDN):
```ts
const texture = await Assets.load('https://example.com/assets/hero.png');
```
Or a **relative path** within your project:
```ts
const texture = await Assets.load('assets/hero.png');
```
PixiJS will **_typically_** automatically determine how to load the asset based on its **file extension** and will cache the result to avoid redundant downloads.
```typescript
import { Application, Assets, Texture } from 'pixi.js';
const app = new Application();
// Application must be initialized before loading assets
await app.init({ backgroundColor: 0x1099bb });
// Load a single asset
const bunnyTexture = await Assets.load('path/to/bunny.png');
const sprite = new Sprite(bunnyTexture);
// Load multiple assets at once
const textures = await Assets.load(['path/to/bunny.png', 'path/to/cat.png']);
const bunnySprite = new Sprite(textures['path/to/bunny.png']);
const catSprite = new Sprite(textures['path/to/cat.png']);
```
### Repeated Loads Are Safe
`Assets` caches by URL or alias. Requests for the same resource return the **same texture**.
```ts
const p1 = await Assets.load('bunny.png');
const p2 = await Assets.load('bunny.png');
console.log(p1 === p2); // true
```
### Asset Aliases
You can also use aliases to refer to assets instead of their full URLs. This provides a more convenient way to manage assets, especially when you have long or complex URLs.
```ts
await Assets.load({ alias: 'bunny', src: 'path/to/bunny.png' });
const bunnyTexture = Assets.get('bunny');
```
All Asset APIs support aliases, including `Assets.load()`, `Assets.get()`, and `Assets.unload()`.
There is more complex ways of defining assets and you can read about them in the [Resolver](./resolver.md) section.
### Retrieving Loaded Assets
You can also retrieve assets that have already been loaded using `Assets.get()`:
```ts
await Assets.load('path/to/bunny.png');
const bunnyTexture = Assets.get('path/to/bunny.png');
const sprite = new Sprite(bunnyTexture);
```
This is useful for when you have preloaded your assets elsewhere in your code and want to access them later without having to pass round references from the initial load.
### Unloading Assets
To unload an asset, you can use `Assets.unload()`. This will remove the asset from the cache and free up memory. Note that if you try to access the asset after unloading it, you will need to load it again.
```ts
await Assets.load('path/to/bunny.png');
const bunnyTexture = Assets.get('path/to/bunny.png');
const sprite = new Sprite(bunnyTexture);
// Unload the asset
await Assets.unload('path/to/bunny.png');
```
### Customizing Asset Loading
You can customize the asset loading process by providing options to the `Assets.init()` method. This allows you to set preferences for how assets are loaded, specify a base path for assets, and more.
```ts
import { Assets } from 'pixi.js';
await Assets.init({...});
```
| Option | Type | Description |
| --------------------- | ------------------------- | ------------------------------------------------------------- |
| `basePath` | `string` | Prefix applied to all relative asset paths (e.g. for CDNs). |
| `defaultSearchParams` | `string` | A default URL parameter string to append to all assets loaded |
| `skipDetections` | `boolean` | Skip environment detection parsers for assets. |
| `manifest` | `Manifest` | A descriptor of named asset bundles and their contents. |
| `preferences` | `AssetPreferences` | Specifies preferences for each loader |
| `bundleIdentifier` | `BundleIdentifierOptions` | **Advanced** - Override how bundlesIds are generated. |
---
## Advanced Usage
There are several advanced features available in the `Assets` API that can help you manage your assets more effectively.
You can read more about these features in the rest of the documentation:
- [Resolving Assets](./resolver.md)
- [Manifests & Bundles (Recommended)](./manifest.md)
- [Background Loading](./background-loader.md)
- [Compressed Textures](./compressed-textures.md)
---
## API Reference
- [Overview](https://pixijs.download/release/docs/assets.html)
- [Assets](https://pixijs.download/release/docs/assets.Assets.html)
---
## Manifests & Bundles
# Manifests & Bundles
PixiJS has a structured and scalable approach to asset management through **Manifests** and **Bundles**. This is the recommended way to manage assets in your PixiJS applications, especially for larger projects or those that require dynamic loading of assets based on context or user interaction. This guide explains what they are, how to use them, and how to generate them efficiently using [AssetPack](https://github.com/pixijs/AssetPack) — a tool designed to automate manifest and bundle creation.
---
## What Is a Manifest?
A **Manifest** is a descriptor object that defines your asset loading strategy. It lists all bundles, each of which contains grouped assets by name and alias. This structure allows for lazy-loading assets based on application context (e.g. load screen assets, level-specific content, etc.).
```js
const manifest = {
bundles: [
{
name: 'load-screen',
assets: [
{ alias: 'background', src: 'sunset.png' },
{ alias: 'bar', src: 'load-bar.{png,webp}' },
],
},
{
name: 'game-screen',
assets: [
{ alias: 'character', src: 'robot.png' },
{ alias: 'enemy', src: 'bad-guy.png' },
],
},
],
};
```
### Initializing With a Manifest
To initialize PixiJS asset handling with a manifest:
```js
import { Assets } from 'pixi.js';
await Assets.init({ manifest });
```
Once initialized, you can load bundles by name:
```js
const loadScreenAssets = await Assets.loadBundle('load-screen');
const gameScreenAssets = await Assets.loadBundle('game-screen');
```
It should be noted that you can still load assets directly without loading an entire bundle via their alias:
```js
await Assets.init({ manifest });
const background = await Assets.load('background');
const bar = await Assets.load('bar');
```
---
## What Is a Bundle?
A **Bundle** is a group of assets that are identified by a shared name. While bundles can be pre-defined in a manifest, they can also be dynamically registered at runtime.
### Adding a Bundle Dynamically
This approach is helpful for scenarios where you want to define bundles on the fly:
```js
import { Assets } from 'pixi.js';
Assets.addBundle('animals', [
{ alias: 'bunny', src: 'bunny.png' },
{ alias: 'chicken', src: 'chicken.png' },
{ alias: 'thumper', src: 'thumper.png' },
]);
const assets = await Assets.loadBundle('animals');
// or load a specific asset from the bundle
const bunny = await Assets.load('bunny');
```
---
## Recommended Tool: AssetPack
Managing manifests and bundles manually can be error-prone. [**AssetPack**](https://pixijs.io/assetpack) is a CLI tool that scans your assets folder and generates optimized manifests and bundles automatically.
### Key Benefits
- Organizes assets by directory or pattern
- Supports output in PixiJS manifest format
- Reduces boilerplate and risk of manual mistakes
You can integrate AssetPack into your build pipeline to generate the manifest file and load it using `Assets.init({ manifest })`.
---
## Resolver
# Resolver
In PixiJS, asset management centers around the concept of `UnresolvedAsset` and `ResolvedAsset`. This system is designed to support multi-format assets, conditional loading, and runtime optimization based on platform capabilities (e.g., WebP support, device resolution, or performance constraints).
Rather than specifying a fixed URL, developers describe what assets _could_ be loaded — and PixiJS selects the best option dynamically.
## Resolver Lifecycle
The resolution process involves four key steps:
1. **UnresolvedAsset Creation**
Assets defined using a string or object are internally normalized into `UnresolvedAsset` instances. These include metadata such as aliases, wildcard paths, parser hints, and custom data.
2. **Source Expansion**
The `src` field of an `UnresolvedAsset` can be a string or array of strings. PixiJS expands any wildcard patterns (e.g. `myAsset@{1,2}x.{png,webp}`) into a list of concrete candidate URLs.
3. **Best-Match Selection**
PixiJS evaluates all candidate URLs and uses platform-aware heuristics to pick the most suitable source. Factors include supported formats (e.g. WebP vs PNG), device pixel ratio, and custom configuration such as preferred formats.
4. **ResolvedAsset Output**
The result is a `ResolvedAsset` containing a specific URL and all required metadata, ready to be passed to the relevant parser and loaded into memory.
## Using Unresolved Assets
An `UnresolvedAsset` is the primary structure used to define assets in PixiJS. It allows you to specify the source URL(s), alias(es), and any additional data needed for loading. They are more complex, but are also more powerful.
| Field | Type | Description |
| ------------------ | -------------------- | ---------------------------------------------------------------------------- |
| `alias` | `string \| string[]` | One or more aliases used to reference this asset later. |
| `src` | `string \| string[]` | Path or paths to one or more asset candidates. Supports wildcards. |
| `loadParser` (opt) | `string` | A specific parser to handle the asset (e.g. `'loadTextures'`, `'loadJson'`). |
| `data` (opt) | `any` | Extra data to pass into the loader. This varies by parser type. |
## Examples
### Loading a Single Asset
```ts
import { Assets } from 'pixi.js';
await Assets.load({
alias: 'bunny',
src: 'images/bunny.png',
});
```
### Loading with Explicit Parser and Loader Options
```ts
await Assets.load({
alias: 'bunny',
src: 'images/bunny.png',
loadParser: 'loadTextures',
data: {
alphaMode: 'no-premultiply-alpha',
},
});
```
### Using Wildcards for Responsive and Format-Aware Loading
```ts
await Assets.load({
alias: 'bunny',
src: 'images/bunny@{0.5,1,2}x.{png,webp}',
});
```
This pattern expands internally to:
```ts
[
'images/bunny@0.5x.png',
'images/bunny@0.5x.webp',
'images/bunny@1x.png',
'images/bunny@1x.webp',
'images/bunny@2x.png',
'images/bunny@2x.webp',
];
```
PixiJS will select the best match depending on runtime capabilities (e.g. chooses WebP if supported, 2x if on a high-res display).
---
## Related Tools and Features
- **AssetPack**: If you're managing large asset sets, [AssetPack](https://pixijs.io/assetpack) can generate optimized manifests using glob patterns and output `UnresolvedAsset` structures automatically.
- **Asset Manifests & Bundles**: Use [manifests and bundles](./manifest.md) to predefine groups of unresolved assets and load them via `Assets.loadBundle`.
---
## SVG's
# SVG's
### Overview
PixiJS provides powerful support for rendering SVGs, allowing developers to integrate scalable vector graphics seamlessly into their projects. This guide explores different ways to use SVGs in PixiJS, covering real-time rendering, performance optimizations, and potential pitfalls.
---
### Why Use SVGs?
SVGs have several advantages over raster images like PNGs:
✅ **Smaller File Sizes** – SVGs can be significantly smaller than PNGs, especially for large but simple shapes. A high-resolution PNG may be several megabytes, while an equivalent SVG could be just a few kilobytes.
✅ **Scalability** – SVGs scale without losing quality, making them perfect for responsive applications and UI elements.
✅ **Editable After Rendering** – Unlike textures, SVGs rendered via Graphics can be modified dynamically (e.g., changing stroke colors, modifying shapes).
✅ **Efficient for Simple Graphics** – If the graphic consists of basic shapes and paths, SVGs can be rendered efficiently as vector graphics.
However, SVGs can also be computationally expensive to parse, particularly for intricate illustrations with many paths or effects.
---
### Ways to Render SVGs in PixiJS
PixiJS offers two primary ways to render SVGs:
1. **As a Texture** – Converts the SVG into a texture for rendering as a sprite.
2. **As a Graphics Object** – Parses the SVG and renders it as vector geometry.
Each method has its advantages and use cases, which we will explore below.
---
## 1. Rendering SVGs as Textures
### Overview
SVGs can be loaded as textures and used within Sprites. This method is efficient but does not retain the scalability of vector graphics.
### Example
```ts
const svgTexture = await Assets.load('tiger.svg');
const mySprite = new Sprite(svgTexture);
```
```ts
import { Application, Graphics } from 'pixi.js';
(async () => {
// Create a new application
const app = new Application();
// Initialize the application
await app.init({
antialias: true,
backgroundColor: 'white',
resizeTo: window,
});
// Append the application canvas to the document body
document.body.appendChild(app.canvas);
const graphics = new Graphics().svg(`
`);
app.stage.addChild(graphics);
})();
```
```ts
import { Application, Assets, Graphics } from 'pixi.js';
(async () => {
// Create a new application
const app = new Application();
// Initialize the application
await app.init({ antialias: true, resizeTo: window });
// Append the application canvas to the document body
document.body.appendChild(app.canvas);
const tigerSvg = await Assets.load({
src: 'https://pixijs.com/assets/tiger.svg',
data: {
parseAsGraphicsContext: true,
},
});
const graphics = new Graphics(tigerSvg);
// line it up as this svg is not centered
const bounds = graphics.getLocalBounds();
graphics.pivot.set(
(bounds.x + bounds.width) / 2,
(bounds.y + bounds.height) / 2,
);
graphics.position.set(app.screen.width / 2, app.screen.height / 2);
app.stage.addChild(graphics);
app.ticker.add(() => {
graphics.rotation += 0.01;
graphics.scale.set(2 + Math.sin(graphics.rotation));
});
})();
```
```ts
import { Application, Assets, Sprite } from 'pixi.js';
(async () => {
// Create a new application
const app = new Application();
// Initialize the application
await app.init({ antialias: true, resizeTo: window });
// Append the application canvas to the document body
document.body.appendChild(app.canvas);
const tigerTexture = await Assets.load({
src: 'https://pixijs.com/assets/tiger.svg',
});
const sprite = new Sprite(tigerTexture);
// line it up as this svg is not centered
const bounds = sprite.getLocalBounds();
sprite.pivot.set(
(bounds.x + bounds.width) / 2,
(bounds.y + bounds.height) / 2,
);
sprite.position.set(app.screen.width / 2, app.screen.height / 2);
app.stage.addChild(sprite);
app.ticker.add(() => {
sprite.rotation += 0.01;
sprite.scale.set(2 + Math.sin(sprite.rotation));
});
})();
```
```ts
import { Application, Assets, Sprite } from 'pixi.js';
(async () => {
// Create a new application
const app = new Application();
// Initialize the application
await app.init({ antialias: true, resizeTo: window });
// Append the application canvas to the document body
document.body.appendChild(app.canvas);
const tigerTexture = await Assets.load({
src: 'https://pixijs.com/assets/tiger.svg',
data: {
resolution: 4,
},
});
const sprite = new Sprite(tigerTexture);
// line it up as this svg is not centered
const bounds = sprite.getLocalBounds();
sprite.pivot.set(
(bounds.x + bounds.width) / 2,
(bounds.y + bounds.height) / 2,
);
sprite.position.set(app.screen.width / 2, app.screen.height / 2);
app.stage.addChild(sprite);
app.ticker.add(() => {
sprite.rotation += 0.01;
sprite.scale.set(2 + Math.sin(sprite.rotation));
});
})();
```
### Scaling Textures
You can specify a resolution when loading an SVG as a texture to control its size:
This does increase memory usage, but it be of a higher fidelity.
```ts
const svgTexture = await Assets.load('path/to.svg', {
resolution: 4, // will be 4 times as big!
});
const mySprite = new Sprite(svgTexture);
```
This ensures the texture appears at the correct size and resolution.
### Pros & Cons
✅ **Fast to render** (rendered as a quad, not geometry)
✅ **Good for static images**
✅ **Supports resolution scaling for precise sizing**
✅ **Ideal for complex SVGs that do not need crisp vector scaling** (e.g., UI components with fixed dimensions)
❌ **Does not scale cleanly** (scaling may result in pixelation)
❌ **Less flexibility** (cannot modify the shape dynamically)
❌ **Texture Size Limit** A texture can only be up to 4096x4096 pixels, so if you need to render a larger SVG, you will need to use the Graphics method.
### Best Use Cases
- Background images
- Decorative elements
- Performance-critical applications where scaling isn’t needed
- Complex SVGs that do not require crisp vector scaling (e.g., fixed-size UI components)
---
## 2. Rendering SVGs as Graphics
### Overview
PixiJS can render SVGs as real scalable vector graphics using the `Graphics` class.
### Example
```ts
const graphics = new Graphics().svg('');
```
If you want to use the same SVG multiple times, you can use `GraphicsContext` to share the parsed SVG data across multiple graphics objects, improving performance by parsing it once and reusing it.
```ts
const context = new GraphicsContext().svg('');
const graphics1 = new Graphics(context);
const graphics2 = new Graphics(context);
```
### Loading SVGs as Graphics
Instead of passing an SVG string directly, you can load an SVG file using PixiJS’s `Assets.load` method. This will return a `GraphicsContext` object, which can be used to create multiple `Graphics` objects efficiently.
```ts
const svgContext = await Assets.load('path/to.svg', {
parseAsGraphicsContext: true, // If false, it returns a texture instead.
});
const myGraphics = new Graphics(svgContext);
```
Since it's loaded via `Assets.load`, it will be cached and reused, much like a texture.
### Pros & Cons
✅ **Retains vector scalability** (no pixelation when zooming)
✅ **Modifiable after rendering** (change colors, strokes, etc.)
✅ **Efficient for simple graphics**
✅ **fast rendering if SVG structure does not change** (no need to reparse)
❌ **More expensive to parse** (complex SVGs can be slow to render)
❌ **Not ideal for static images**
### Best Use Cases
- Icons and UI elements that need resizing
- A game world that needs to remain crisp as a player zooms in
- Interactive graphics where modifying the SVG dynamically is necessary
---
## SVG Rendering Considerations
### Supported Features
PixiJS supports most SVG features that can be rendered in a Canvas 2D context. Below is a list of common SVG features and their compatibility:
| Feature | Supported |
| --------------------------------------- | --------- |
| Basic Shapes (rect, circle, path, etc.) | ✅ |
| Gradients | ✅ |
| Stroke & Fill Styles | ✅ |
| Text Elements | ❌ |
| Filters (Blur, Drop Shadow, etc.) | ❌ |
| Clipping Paths | ✅ |
| Patterns | ❌ |
| Complex Paths & Curves | ✅ |
### Performance Considerations
- **Complex SVGs:** Large or intricate SVGs can slow down rendering start up due to high parsing costs. Use `GraphicsContext` to cache and reuse parsed data.
- **Vector vs. Texture:** If performance is a concern, consider using SVGs as textures instead of rendering them as geometry. However, keep in mind that textures take up more memory.
- **Real-Time Rendering:** Avoid rendering complex SVGs dynamically. Preload and reuse them wherever possible.
---
## Best Practices & Gotchas
### Best Practices
✅ **Use Graphics for scalable and dynamic SVGs**
✅ **Use Textures for performance-sensitive applications**
✅ **Use `GraphicsContext` to avoid redundant parsing**
✅ **Consider `resolution` when using textures to balance quality and memory**
### Gotchas
⚠ **Large SVGs can be slow to parse** – Optimize SVGs before using them in PixiJS.
⚠ **Texture-based SVGs do not scale cleanly** – Use higher resolution if necessary.
⚠ **Not all SVG features are supported** – Complex filters and text elements may not work as expected.
---
By understanding how PixiJS processes SVGs, developers can make informed decisions on when to use `Graphics.svg()`, `GraphicsContext`, or SVG textures, balancing quality and performance for their specific use case.
---
## Renderers
# Renderers
PixiJS renderers are responsible for drawing your scene to a canvas using either **WebGL/WebGL2** or **WebGPU**. These renderers are high-performance GPU-accelerated engines and are composed of modular systems that manage everything from texture uploads to rendering pipelines.
All PixiJS renderers inherit from a common base, which provides consistent methods such as `.render()`, `.resize()`, and `.clear()` as well as shared systems for managing the canvas, texture GC, events, and more.
## Renderer Types
| Renderer | Description | Status |
| ---------------- | ------------------------------------------------------------------ | --------------- |
| `WebGLRenderer` | Default renderer using WebGL/WebGL2. Well supported and stable. | ✅ Recommended |
| `WebGPURenderer` | Modern GPU renderer using WebGPU. More performant, still maturing. | 🚧 Experimental |
| `CanvasRenderer` | Fallback renderer using 2D canvas. | ❌ Coming-soon |
:::info
The WebGPU renderer is feature complete, however, inconsistencies in browser implementations may lead to unexpected behavior. It is recommended to use the WebGL renderer for production applications.
:::
## Creating a Renderer
You can use `autoDetectRenderer()` to create the best renderer for the environment:
```ts
import { autoDetectRenderer } from 'pixi.js';
const renderer = await autoDetectRenderer({
preference: 'webgpu', // or 'webgl'
});
```
Or construct one explicitly:
```ts
import { WebGLRenderer, WebGPURenderer } from 'pixi.js';
const renderer = new WebGLRenderer();
await renderer.init(options);
```
## Rendering a Scene
To render a scene, you can use the `render()` method. This will draw the specified container to the screen or a texture:
```ts
import { Container } from 'pixi.js';
const container = new Container();
renderer.render(container);
// or provide a complete set of options
renderer.render({
target: container,
clear: true, // clear the screen before rendering
transform: new Matrix(), // optional transform to apply to the container
});
```
## Resizing the Renderer
To resize the renderer, use the `resize()` method. This will adjust the canvas size and update the resolution:
```ts
renderer.resize(window.innerWidth, window.innerHeight);
```
## Generating Textures
You can generate textures from containers using the `generateTexture()` method. This is useful for creating textures from dynamic content:
```ts
import { Sprite } from 'pixi.js';
const sprite = new Sprite();
const texture = renderer.generateTexture(sprite);
```
## Resetting State
To reset the renderer's state, use the `resetState()` method. This is useful when mixing PixiJS with other libraries like Three.js:
```ts
function render() {
// Render the Three.js scene
threeRenderer.resetState();
threeRenderer.render(scene, camera);
// Render the PixiJS stage
pixiRenderer.resetState();
pixiRenderer.render({ container: stage });
requestAnimationFrame(render);
}
requestAnimationFrame(render);
```
See our full guide on [mixing PixiJS with Three.js](../../third-party/mixing-three-and-pixi.mdx) for more details.
---
## API Reference
- [Overview](https://pixijs.download/release/docs/rendering.html)
- [AbstractRenderer](https://pixijs.download/release/docs/rendering.AbstractRenderer.html)
- [WebGLRenderer](https://pixijs.download/release/docs/rendering.WebGLRenderer.html)
- [WebGPURenderer](https://pixijs.download/release/docs/rendering.WebGPURenderer.html)
- [AutoDetectRenderer](https://pixijs.download/release/docs/rendering.html#autoDetectRenderer)
---
## Cache As Texture
# Cache As Texture
### Using `cacheAsTexture` in PixiJS
The `cacheAsTexture` function in PixiJS is a powerful tool for optimizing rendering in your applications. By rendering a container and its children to a texture, `cacheAsTexture` can significantly improve performance for static or infrequently updated containers. Let's explore how to use it effectively, along with its benefits and considerations.
:::info[Note]
`cacheAsTexture` is PixiJS v8's equivalent of the previous `cacheAsBitmap` functionality. If you're migrating from v7 or earlier, simply replace `cacheAsBitmap` with `cacheAsTexture` in your code.
:::
---
### What Is `cacheAsTexture`?
When you set `container.cacheAsTexture()`, the container is rendered to a texture. Subsequent renders reuse this texture instead of rendering all the individual children of the container. This approach is particularly useful for containers with many static elements, as it reduces the rendering workload.
To update the texture after making changes to the container, call:
```javascript
container.updateCacheTexture();
```
and to turn it off, call:
```javascript
container.cacheAsTexture(false);
```
---
### Basic Usage
Here's an example that demonstrates how to use `cacheAsTexture`:
```javascript
import * as PIXI from 'pixi.js';
(async () => {
// Create a new application
const app = new Application();
// Initialize the application
await app.init({ background: '#1099bb', resizeTo: window });
// Append the application canvas to the document body
document.body.appendChild(app.canvas);
// load sprite sheet..
await Assets.load('https://pixijs.com/assets/spritesheet/monsters.json');
// holder to store aliens
const aliens = [];
const alienFrames = [
'eggHead.png',
'flowerTop.png',
'helmlok.png',
'skully.png',
];
let count = 0;
// create an empty container
const alienContainer = new Container();
alienContainer.x = 400;
alienContainer.y = 300;
app.stage.addChild(alienContainer);
// add a bunch of aliens with textures from image paths
for (let i = 0; i < 100; i++) {
const frameName = alienFrames[i % 4];
// create an alien using the frame name..
const alien = Sprite.from(frameName);
alien.tint = Math.random() * 0xffffff;
alien.x = Math.random() * 800 - 400;
alien.y = Math.random() * 600 - 300;
alien.anchor.x = 0.5;
alien.anchor.y = 0.5;
aliens.push(alien);
alienContainer.addChild(alien);
}
// this will cache the container and its children as a single texture
// so instead of drawing 100 sprites, it will draw a single texture!
alienContainer.cacheAsTexture();
})();
```
In this example, the `container` and its children are rendered to a single texture, reducing the rendering overhead when the scene is drawn.
Play around with the example [here](../../../../examples/basic/cache-as-texture.mdx).
### Advanced Usage
Instead of enabling cacheAsTexture with true, you can pass a configuration object which is very similar to texture source options.
```typescript
container.cacheAsTexture({
resolution: 2,
antialias: true,
});
```
- `resolution` is the resolution of the texture. By default this is the same as you renderer or application.
- `antialias` is the antialias mode to use for the texture. Much like the resolution this defaults to the renderer or application antialias mode.
---
### Benefits of `cacheAsTexture`
- **Performance Boost**: Rendering a complex container as a single texture avoids the need to process each child element individually during each frame.
- **Optimized for Static Content**: Ideal for containers with static or rarely updated children.
---
### Advanced Details
- **Memory Tradeoff**: Each cached texture requires GPU memory. Using `cacheAsTexture` trades rendering speed for increased memory usage.
- **GPU Limitations**: If your container is too large (e.g., over 4096x4096 pixels), the texture may fail to cache, depending on GPU limitations.
---
### How It Works Internally
Under the hood, `cacheAsTexture` converts the container into a render group and renders it to a texture. It uses the same texture cache mechanism as filters:
```javascript
container.enableRenderGroup();
container.renderGroup.cacheAsTexture = true;
```
Once the texture is cached, updating it via `updateCacheTexture()` is efficient and incurs minimal overhead. Its as fast as rendering the container normally.
---
### Best Practices
#### **DO**:
- **Use for Static Content**: Apply `cacheAsTexture` to containers with elements that don't change frequently, such as a UI panel with static decorations.
- **Leverage for Performance**: Use `cacheAsTexture` to render complex containers as a single texture, reducing the overhead of processing each child element individually every frame. This is especially useful for containers that contain expensive effects eg filters.
- **Switch of Antialiasing**: setting antialiasing to false can give a small performance boost, but the texture may look a bit more pixelated around its children's edges.
- **Resolution**: Do adjust the resolution based on your situation, if something is scaled down, you can use a lower resolution.If something is scaled up, you may want to use a higher resolution. But be aware that the higher the resolution the larger the texture and memory footprint.
#### **DON'T**:
- **Apply to Very Large Containers**: Avoid using `cacheAsTexture` on containers that are too large (e.g., over 4096x4096 pixels), as they may fail to cache due to GPU limitations. Instead, split them into smaller containers.
- **Overuse for Dynamic Content**: Flick `cacheAsTexture` on / off frequently on containers, as this results in constant re-caching, negating its benefits. Its better to Cache as texture when you once, and then use `updateCacheTexture` to update it.
- **Apply to Sparse Content**: Do not use `cacheAsTexture` for containers with very few elements or sparse content, as the performance improvement will be negligible.
- **Ignore Memory Impact**: Be cautious of GPU memory usage. Each cached texture consumes memory, so overusing `cacheAsTexture` can lead to resource constraints.
---
### Gotchas
- **Rendering Depends on Scene Visibility**: The cache updates only when the containing scene is rendered. Modifying the layout after setting `cacheAsTexture` but before rendering your scene will be reflected in the cache.
- **Containers are rendered with no transform**: Cached items are rendered at their actual size, ignoring transforms like scaling. For instance, an item scaled down by 50%, its texture will be cached at 100% size and then scaled down by the scene.
- **Caching and Filters**: Filters may not behave as expected with `cacheAsTexture`. To cache the filter effect, wrap the item in a parent container and apply `cacheAsTexture` to the parent.
- **Reusing the texture**: If you want to create a new texture based on the container, its better to use `const texture = renderer.generateTexture(container)` and share that amongst you objects!
By understanding and applying `cacheAsTexture` strategically, you can significantly enhance the rendering performance of your PixiJS projects. Happy coding!
---
## Container
# Container
The `Container` class is the foundation of PixiJS's scene graph system. Containers act as groups of scene objects, allowing you to build complex hierarchies, organize rendering layers, and apply transforms or effects to groups of objects.
## What Is a Container?
A `Container` is a general-purpose node that can hold other display objects, **including other containers**. It is used to structure your scene, apply transformations, and manage rendering and interaction.
Containers are **not** rendered directly. Instead, they delegate rendering to their children.
```ts
import { Container, Sprite } from 'pixi.js';
const group = new Container();
const sprite = Sprite.from('bunny.png');
group.addChild(sprite);
```
## Managing Children
PixiJS provides a robust API for adding, removing, reordering, and swapping children in a container:
```ts
const container = new Container();
const child1 = new Container();
const child2 = new Container();
container.addChild(child1, child2);
container.removeChild(child1);
container.addChildAt(child1, 0);
container.swapChildren(child1, child2);
```
You can also remove a child by index or remove all children within a range:
```ts
container.removeChildAt(0);
container.removeChildren(0, 2);
```
To keep a child’s world transform while moving it to another container, use `reparentChild` or `reparentChildAt`:
```ts
otherContainer.reparentChild(child);
```
### Events
Containers emit events when children are added or removed:
```ts
group.on('childAdded', (child, parent, index) => { ... });
group.on('childRemoved', (child, parent, index) => { ... });
```
### Finding Children
Containers support searching children by `label` using helper methods:
```ts
const child = new Container({ label: 'enemy' });
container.addChild(child);
container.getChildByLabel('enemy');
container.getChildrenByLabel(/^enemy/); // all children whose label starts with "enemy"
```
Set `deep = true` to search recursively through all descendants.
```ts
container.getChildByLabel('ui', true);
```
### Sorting Children
Use `zIndex` and `sortableChildren` to control render order within a container:
```ts
child1.zIndex = 1;
child2.zIndex = 10;
container.sortableChildren = true;
```
Call `sortChildren()` to manually re-sort if needed:
```ts
container.sortChildren();
```
:::info
Use this feature sparingly, as sorting can be expensive for large numbers of children.
:::
## Optimizing with Render Groups
Containers can be promoted to **render groups** by setting `isRenderGroup = true` or calling `enableRenderGroup()`.
Use render groups for UI layers, particle systems, or large moving subtrees.
See the [Render Groups guide](../../../concepts/render-groups.md) for more details.
```ts
const uiLayer = new Container({ isRenderGroup: true });
```
## Cache as Texture
The `cacheAsTexture` function in PixiJS is a powerful tool for optimizing rendering in your applications. By rendering a container and its children to a texture, `cacheAsTexture` can significantly improve performance for static or infrequently updated containers.
When you set `container.cacheAsTexture()`, the container is rendered to a texture. Subsequent renders reuse this texture instead of rendering all the individual children of the container. This approach is particularly useful for containers with many static elements, as it reduces the rendering workload.
:::info[Note]
`cacheAsTexture` is PixiJS v8's equivalent of the previous `cacheAsBitmap` functionality. If you're migrating from v7 or earlier, simply replace `cacheAsBitmap` with `cacheAsTexture` in your code.
:::
```ts
const container = new Container();
const sprite = Sprite.from('bunny.png');
container.addChild(sprite);
// enable cache as texture
container.cacheAsTexture();
// update the texture if the container changes
container.updateCacheTexture();
// disable cache as texture
container.cacheAsTexture(false);
```
For more advanced usage, including setting cache options and handling dynamic content, refer to the [Cache as Texture guide](./cache-as-texture.md).
---
## API Reference
- [Container](https://pixijs.download/release/docs/scene.Container.html)
- [ContainerOptions](https://pixijs.download/release/docs/scene.ContainerOptions.html)
- [RenderContainer](https://pixijs.download/release/docs/scene.RenderContainer.html)
---
## Graphics Fill
# Graphics Fill
If you are new to graphics, please check out the [graphics guide](../graphics) here. This guide dives a bit deeper into a specific aspect of graphics: how to fill them! The `fill()` method in PixiJS is particularly powerful, enabling you to fill shapes with colors, textures, or gradients. Whether you're designing games, UI components, or creative tools, mastering the `fill()` method is essential for creating visually appealing and dynamic graphics. This guide explores the different ways to use the `fill()` method to achieve stunning visual effects.
:::info Note
The `fillStyles` discussed here can also be applied to Text objects!
:::
## Basic Color Fills
When creating a `Graphics` object, you can easily fill it with a color using the `fill()` method. Here's a simple example:
```ts
const obj = new Graphics()
.rect(0, 0, 200, 100) // Create a rectangle with dimensions 200x100
.fill('red'); // Fill the rectangle with a red color
```

This creates a red rectangle. PixiJS supports multiple color formats for the `fill()` method. Developers can choose a format based on their needs. For example, CSS color strings are user-friendly and readable, hexadecimal strings are compact and widely used in design tools, and numbers are efficient for programmatic use. Arrays and Color objects offer precise control, making them ideal for advanced graphics.
- CSS color strings (e.g., 'red', 'blue')
- Hexadecimal strings (e.g., '#ff0000')
- Numbers (e.g., `0xff0000`)
- Arrays (e.g., `[255, 0, 0]`)
- Color objects for precise color control
### Examples:
```ts
// Using a number
const obj1 = new Graphics().rect(0, 0, 100, 100).fill(0xff0000);
// Using a hex string
const obj2 = new Graphics().rect(0, 0, 100, 100).fill('#ff0000');
// Using an array
const obj3 = new Graphics().rect(0, 0, 100, 100).fill([255, 0, 0]);
// Using a Color object
const color = new Color();
const obj4 = new Graphics().rect(0, 0, 100, 100).fill(color);
```
## Fill with a Style Object
For more advanced fills, you can use a `FillStyle` object. This allows for additional customization, such as setting opacity:
```ts
const obj = new Graphics().rect(0, 0, 100, 100).fill({
color: 'red',
alpha: 0.5, // 50% opacity
});
```

## Fill with Textures
Filling shapes with textures is just as simple:
```ts
const texture = await Assets.load('assets/image.png');
const obj = new Graphics().rect(0, 0, 100, 100).fill(texture);
```

### Local vs. Global Texture Space
Textures can be applied in two coordinate spaces:
- **Local Space** (Default): The texture coordinates are mapped relative to the shape's dimensions and position. The texture coordinates use a normalized coordinate system where (0,0) is the top-left and (1,1) is the bottom-right of the shape, regardless of its actual pixel dimensions. For example, if you have a 300x200 pixel texture filling a 100x100 shape, the texture will be scaled to fit exactly within those 100x100 pixels. The texture's top-left corner (0,0) will align with the shape's top-left corner, and the texture's bottom-right corner (1,1) will align with the shape's bottom-right corner, stretching or compressing the texture as needed.
```ts
const shapes = new PIXI.Graphics()
.rect(50, 50, 100, 100)
.circle(250, 100, 50)
.star(400, 100, 6, 60, 40)
.roundRect(500, 50, 100, 100, 10)
.fill({
texture,
textureSpace: 'local', // default!
});
```

- **Global Space**: Set `textureSpace: 'global'` to make the texture position and scale relative to the Graphics object's coordinate system. Despite the name, this isn't truly "global" - the texture remains fixed relative to the Graphics object itself, maintaining its position even when the object moves or scales. See how the image goes across all the shapes (in the same graphics) below:
```ts
const shapes = new PIXI.Graphics()
.rect(50, 50, 100, 100)
.circle(250, 100, 50)
.star(400, 100, 6, 60, 40)
.roundRect(500, 50, 100, 100, 10)
.fill({
texture,
textureSpace: 'global',
});
```

### Using Matrices with Textures
To modify texture coordinates, you can apply a transformation matrix, which is a mathematical tool used to scale, rotate, or translate the texture. If you're unfamiliar with transformation matrices, they allow for precise control over how textures are rendered, and you can explore more about them [here](https://learnwebgl.brown37.net/10_surface_properties/texture_mapping_transforms.html#:~:text=Overview%C2%B6,by%2D4%20transformation%20matrix).
```ts
const matrix = new Matrix().scale(0.5, 0.5);
const obj = new Graphics().rect(0, 0, 100, 100).fill({
texture: texture,
matrix: matrix, // scale the texture down by 2
});
```

### Texture Gotcha's
1. **Sprite Sheets**: If using a texture from a sprite sheet, the entire source texture will be used. To use a specific frame, create a new texture:
```ts
const spriteSheetTexture = Texture.from('assets/my-sprite-sheet.png');
const newTexture = renderer.generateTexture(Sprite.from(spriteSheetTexture));
const obj = new Graphics().rect(0, 0, 100, 100).fill(newTexture);
```
2. **Power of Two Textures**: Textures should be power-of-two dimensions for proper tiling in WebGL1 (WebGL2 and WebGPU are fine).
## Fill with Gradients
PixiJS supports both linear and radial gradients, which can be created using the `FillGradient` class. Gradients are particularly useful for adding visual depth and dynamic styling to shapes and text.
### Linear Gradients
Linear gradients create a smooth color transition along a straight line. Here is an example of a simple linear gradient:
```ts
const gradient = new FillGradient({
type: 'linear',
colorStops: [
{ offset: 0, color: 'yellow' },
{ offset: 1, color: 'green' },
],
});
const obj = new Graphics().rect(0, 0, 100, 100).fill(gradient);
```

You can control the gradient direction with the following properties:
- `start {x, y}`: These define the starting point of the gradient. For example, in a linear gradient, this is where the first color stop is positioned. These values are typically expressed in relative coordinates (0 to 1), where `0` represents the left/top edge and `1` represents the right/bottom edge of the shape.
- `end {x, y}`: These define the ending point of the gradient. Similar to `start {x, y}`, these values specify where the last color stop is positioned in the shape's local coordinate system.
Using these properties, you can create various gradient effects, such as horizontal, vertical, or diagonal transitions. For example, setting `start` to `{x: 0, y: 0}` and `end` to `{x: 1, y: 1}` would result in a diagonal gradient from the top-left to the bottom-right of the shape.
```ts
const diagonalGradient = new FillGradient({
type: 'linear',
start: { x: 0, y: 0 },
end: { x: 1, y: 1 },
colorStops: [
{ offset: 0, color: 'yellow' },
{ offset: 1, color: 'green' },
],
});
```

### Radial Gradients
Radial gradients create a smooth color transition in a circular pattern. Unlike linear gradients, they blend colors from one circle to another. Here is an example of a simple radial gradient:
```ts
const gradient = new FillGradient({
type: 'radial',
colorStops: [
{ offset: 0, color: 'yellow' },
{ offset: 1, color: 'green' },
],
});
const obj = new Graphics().rect(0, 0, 100, 100).fill(gradient);
```

You can control the gradient's shape and size using the following properties:
- `center {x, y}`: These define the center of the inner circle where the gradient starts. Typically, these values are expressed in relative coordinates (0 to 1), where `0.5` represents the center of the shape.
- `innerRadius`: The radius of the inner circle. This determines the size of the gradient's starting point.
- `outerCenter {x, y}`: These define the center of the outer circle where the gradient ends. Like `center {x, y}`, these values are also relative coordinates.
- `outerRadius`: The radius of the outer circle. This determines the size of the gradient's ending point.
By adjusting these properties, you can create a variety of effects, such as small, concentrated gradients or large, expansive ones. For example, setting a small `r0` and a larger `r1` will create a gradient that starts does not start to transition until the inner circle radius is reached.
```ts
const radialGradient = new FillGradient({
type: 'radial',
center: { x: 0.5, y: 0.5 },
innerRadius: 0.25,
outerCenter: { x: 0.5, y: 0.5 },
outerRadius: 0.5,
colorStops: [
{ offset: 0, color: 'blue' },
{ offset: 1, color: 'red' },
],
});
const obj = new Graphics().rect(0, 0, 100, 100).fill(gradient);
```

### Gradient Gotcha's
1. **Memory Management**: Use `fillGradient.destroy()` to free up resources when gradients are no longer needed.
2. **Animation**: Update existing gradients instead of creating new ones for better performance.
3. **Custom Shaders**: For complex animations, custom shaders may be more efficient.
4. **Texture and Matrix Limitations**: Under the hood, gradient fills set both the texture and matrix properties internally. This means you cannot use a texture fill or matrix transformation at the same time as a gradient fill.
### Combining Textures and Colors
You can combine a texture or gradients with a color tint and alpha to achieve more complex and visually appealing effects. This allows you to overlay a color on top of the texture or gradient, adjusting its transparency with the alpha value.
```ts
const gradient = new FillGradient({
colorStops: [
{ offset: 0, color: 'blue' },
{ offset: 1, color: 'red' },
],
});
const obj = new Graphics().rect(0, 0, 100, 100).fill({
fill: gradient,
color: 'yellow',
alpha: 0.5,
});
```

```ts
const obj = new Graphics().rect(0, 0, 100, 100).fill({
texture: texture,
color: 'yellow',
alpha: 0.5,
});
```

---
Hopefully, this guide has shown you how easy and powerful fills can be when working with graphics (and text!). By mastering the `fill()` method, you can unlock endless possibilities for creating visually dynamic and engaging graphics in PixiJS. Have fun!
---
## Graphics Pixel Line
import { Sandpack } from '@codesandbox/sandpack-react';
import { dracula } from '@codesandbox/sandpack-themes';
# Graphics Pixel Line
The `pixelLine` property is a neat feature of the PixiJS Graphics API that allows you to create lines that remain 1 pixel thick, regardless of scaling or zoom level. As part of the Graphics API, it gives developers all the power PixiJS provides for building and stroking shapes. This feature is especially useful for achieving crisp, pixel-perfect visuals, particularly in retro-style or grid-based games, technical drawing, or UI rendering.
In this guide, we'll dive into how this property works, its use cases, and the caveats you should be aware of when using it.
---
```ts
import { Application, Container, Graphics, Text } from 'pixi.js';
/**
* Creates a grid pattern using Graphics lines
* @param graphics - The Graphics object to draw on
* @returns The Graphics object with the grid drawn
*/
function buildGrid(graphics) {
// Draw 10 vertical lines spaced 10 pixels apart
for (let i = 0; i < 11; i++) {
// Move to top of each line (x = i*10, y = 0)
graphics
.moveTo(i * 10, 0)
// Draw down to bottom (x = i*10, y = 100)
.lineTo(i * 10, 100);
}
// Draw 10 horizontal lines spaced 10 pixels apart
for (let i = 0; i < 11; i++) {
// Move to start of each line (x = 0, y = i*10)
graphics
.moveTo(0, i * 10)
// Draw across to end (x = 100, y = i*10)
.lineTo(100, i * 10);
}
return graphics;
}
(async () => {
// Create and initialize a new PixiJS application
const app = new Application();
await app.init({ antialias: true, resizeTo: window });
document.body.appendChild(app.canvas);
// Create two grids - one with pixel-perfect lines and one without
const gridPixel = buildGrid(new Graphics()).stroke({
color: 0xffffff,
pixelLine: true,
width: 1,
});
const grid = buildGrid(new Graphics()).stroke({
color: 0xffffff,
pixelLine: false,
});
// Position the grids side by side
grid.x = -100;
grid.y = -50;
gridPixel.y = -50;
// Create a container to hold both grids
const container = new Container();
container.addChild(grid, gridPixel);
// Center the container on screen
container.x = app.screen.width / 2;
container.y = app.screen.height / 2;
app.stage.addChild(container);
// Animation variables
let count = 0;
// Add animation to scale the grids over time
app.ticker.add(() => {
count += 0.01;
container.scale = 1 + (Math.sin(count) + 1) * 2;
});
// Add descriptive label
const label = new Text({
text: 'Grid Comparison: Standard Lines (Left) vs Pixel-Perfect Lines (Right)',
style: { fill: 0xffffff },
});
// Position label in top-left corner
label.position.set(20, 20);
label.width = app.screen.width - 40;
label.scale.y = label.scale.x;
app.stage.addChild(label);
})();
```
## How to use `pixelLine`?
Here’s a simple example:
```ts
// Create a Graphics object and draw a pixel-perfect line
let graphics = new Graphics()
.moveTo(0, 0)
.lineTo(100, 100)
.stroke({ color: 0xff0000, pixelLine: true });
// Add it to the stage
app.stage.addChild(graphics);
// Even if we scale the Graphics object, the line remains 1 pixel wide
graphics.scale.set(2);
```
In this example, no matter how you transform or zoom the `Graphics` object, the red line will always appear 1 pixel thick on the screen.
---
## Why Use `pixelLine`?
Pixel-perfect lines can be incredibly useful in a variety of scenarios. Here are some common use cases:
### 1. **Retro or Pixel Art Games**
- Pixel art games rely heavily on maintaining sharp, precise visuals. The `pixelLine` property ensures that lines do not blur or scale inconsistently with other pixel elements.
- Example: Drawing pixel-perfect grids for tile-based maps.
```ts
// Create a grid of vertical and horizontal lines
const grid = new Graphics();
// Draw 10 vertical lines spaced 10 pixels apart
// Draw vertical lines
for (let i = 0; i < 10; i++) {
// Move to top of each line (x = i*10, y = 0)
grid
.moveTo(i * 10, 0)
// Draw down to bottom (x = i*10, y = 100)
.lineTo(i * 10, 100);
}
// Draw horizontal lines
for (let i = 0; i < 10; i++) {
// Move to start of each line (x = 0, y = i*10)
grid
.moveTo(0, i * 10)
// Draw across to end (x = 100, y = i*10)
.lineTo(100, i * 10);
}
// Stroke all lines in white with pixel-perfect width
grid.stroke({ color: 0xffffff, pixelLine: true });
```
---
### 2. **UI and HUD Elements**
- For UI elements such as borders, separators, or underlines, a consistent 1-pixel thickness provides a professional, clean look.
- Example: Drawing a separator line in a menu or a progress bar border.
```ts
// Create a separator line that will always be 1 pixel thick
const separator = new Graphics()
// Start at x=0, y=50
.moveTo(0, 50)
// Draw a horizontal line 200 pixels to the right
.lineTo(200, 50)
// Stroke in green with pixel-perfect 1px width
.stroke({ color: 0x00ff00, pixelLine: true });
```
---
### 3. **Debugging and Prototyping**
- Use pixel-perfect lines to debug layouts, collision boxes, or grids. Since the lines don’t scale, they offer a consistent reference point during development.
- Example: Displaying collision boundaries in a physics-based game.
```ts
// Create a debug box with pixel-perfect stroke
const graphicsBox = new Graphics()
.rect(0, 0, 100, 100)
.stroke({ color: 0xff00ff, pixelLine: true });
/**
* Updates the debug box to match the bounds of a given object
* @param {Container} obj - The object to draw bounds for
*/
function drawDebugBounds(obj) {
// Get the bounds of the object
let bounds = obj.getBounds().rectangle;
// Position and scale the debug box to match the bounds
// this is faster than using `moveTo` and `lineTo` each frame!
graphicsBox.position.set(bounds.x, bounds.y);
graphicsBox.scale.set(bounds.width / 100, bounds.height / 100);
}
```
---
## How it works
This is achieved under the hood using WebGL or WebGPU's native line rendering methods when `pixelLine` is set to `true`.
Fun fact its actually faster to draw a pixel line than a regular line. This is because of two main factors:
1. **Simpler Drawing Process**: Regular lines in PixiJS (when `pixelLine` is `false`) need extra steps to be drawn. PixiJS has to figure out the thickness of the line and create a shape that looks like a line but is actually made up of triangles.
2. **Direct Line Drawing**: When using `pixelLine`, we can tell the graphics card "just draw a line from point A to point B" and it knows exactly what to do. This is much simpler and faster than creating and filling shapes.
Think of it like drawing a line on paper - `pixelLine` is like using a pen to draw a straight line, while regular lines are like having to carefully color in a thin rectangle. The pen method is naturally faster and simpler!
## Caveats and Gotchas
While the `pixelLine` property is incredibly useful, there are some limitations and things to keep in mind:
### 1. **Its 1px thick, thats it!**
- The line is always 1px thick, there is no way to change this as its using the GPU to draw the line.
### 2. **Hardware may render differently**
- Different GPUs and graphics hardware may render the line slightly differently due to variations in how they handle line rasterization. For example, some GPUs may position the line slightly differently or apply different anti-aliasing techniques. This is an inherent limitation of GPU line rendering and is beyond PixiJS's control.
### 4. **Scaling Behavior**
- While the line thickness remains constant, other properties (e.g., position or start/end points) are still affected by scaling. This can sometimes create unexpected results if combined with other scaled objects. This is a feature not a bug :)
### Example: Box with Pixel-Perfect Stroke
Here's an example of a filled box with a pixel-perfect stroke. The box itself scales and grows, but the stroke remains 1 pixel wide:
```ts
// Create a Graphics object and draw a filled box with a pixel-perfect stroke
let box = new Graphics()
.rect(0, 0, 100, 100)
.fill('white')
.stroke({ color: 0xff0000, pixelLine: true });
// Add it to the stage
app.stage.addChild(box);
// Scale the box
box.scale.set(2);
```
In this example, the blue box grows as it scales, but the red stroke remains at 1 pixel thickness, providing a crisp outline regardless of the scaling.
---
## When to Avoid Using `pixelLine`
- **You want a line that is not 1px thick:** Don't use `pixelLine`.
- **You want the line to scale:** Don't use `pixelLine`
---
## Conclusion
The `pixelLine` property is a super useful to have in the PixiJS toolbox for developers looking to create sharp, pixel-perfect lines that remain consistent under transformation. By understanding its strengths and limitations, you can incorporate it into your projects for clean, professional results in both visual and functional elements.
---
## Graphics
# Graphics
[Graphics](https://pixijs.download/release/docs/scene.Graphics.html) is a powerful and flexible tool for rendering shapes such as rectangles, circles, stars, and custom polygons. It can also be used to create complex shapes by combining multiple primitives, and it supports advanced features like gradients, textures, and masks.
```ts
import { Graphics } from 'pixi.js';
const graphics = new Graphics().rect(50, 50, 100, 100).fill(0xff0000);
```
## **Available Shapes**
PixiJS v8 supports a variety of shape primitives:
### Basic Primitives
- Line
- Rectangle
- Rounded Rectangle
- Circle
- Ellipse
- Arc
- Bezier / Quadratic Curves
### Advanced Primitives
- Chamfer Rect
- Fillet Rect
- Regular Polygon
- Star
- Rounded Polygon
- Rounded Shape
```ts
const graphics = new Graphics()
.rect(50, 50, 100, 100)
.fill(0xff0000)
.circle(200, 200, 50)
.stroke(0x00ff00)
.lineStyle(5)
.moveTo(300, 300)
.lineTo(400, 400);
```
### SVG Support
You can also load SVG path data, although complex hole geometries may render inaccurately due to Pixi's performance-optimized triangulation system.
```ts
let shape = new Graphics().svg(`
`);
```
## **GraphicsContext**
The `GraphicsContext` class is the core of PixiJS's new graphics model. It holds all the drawing commands and styles, allowing the same shape data to be reused by multiple `Graphics` instances:
```ts
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 particularly effective when rendering repeated or animated shapes, such as frame-based SVG swaps:
```ts
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
}
```
:::info
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
When you destroy a `GraphicsContext`, all `Graphics` instances that share it will also be destroyed. This is a crucial point to remember, as it can lead to unexpected behavior if you're not careful.
```ts
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
```
## **Creating Holes**
Use `.cut()` to remove a shape from the previous one:
```ts
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.
## **Graphics Is About Building, Not Drawing**
Despite the terminology of functions like `.rect()` or `.circle()`, `Graphics` does not immediately draw anything. Instead, each method builds up a list of geometry primitives stored inside a `GraphicsContext`. These are then rendered when the object is drawn to the screen or used in another context, such as a mask.
```ts
const graphic = new Graphics().rect(0, 0, 200, 100).fill(0xff0000);
app.stage.addChild(graphic); // The rendering happens here
```
You can think of `Graphics` as a blueprint builder: it defines what to draw, but not when to draw it. This is why `Graphics` objects can be reused, cloned, masked, and transformed without incurring extra computation until they're actually rendered.
## **Performance Best Practices**
- **Do not clear and rebuild graphics every frame**. If your content is dynamic, prefer swapping prebuilt `GraphicsContext` objects instead of recreating them.
- **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.
- **Avoid transparent overlap** unless you understand blend modes; overlapping semi-transparent primitives will interact per primitive, not post-composition.
## **Caveats and Gotchas**
- **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` if you want to flatten effects.
---
## **API Reference**
- [Graphics](https://pixijs.download/release/docs/scene.Graphics.html)
- [GraphicsContext](https://pixijs.download/release/docs/scene.GraphicsContext.html)
- [FillStyle](https://pixijs.download/release/docs/scene.FillStyle.html)
- [StrokeStyle](https://pixijs.download/release/docs/scene.StrokeStyle.html)
---
## Scene Objects
# Scene Objects
In PixiJS, scene objects are the building blocks of your application’s display hierarchy. They include **containers**, **sprites**, **text**, **graphics**, and other drawable entities that make up the **scene graph**—the tree-like structure that determines what gets rendered, how, and in what order.
## Containers vs. Leaf Nodes
Scene objects in PixiJS can be divided into **containers** and **leaf nodes**:
### Containers
`Container` is the **base class** for all scene objects in v8 (replacing the old `DisplayObject`).
- Can have children.
- Commonly used to group objects and apply transformations (position, scale, rotation) to the group.
- Examples: `Application.stage`, user-defined groups.
```ts
const group = new Container();
group.addChild(spriteA);
group.addChild(spriteB);
```
### Leaf Nodes
Leaf nodes are renderable objects that should not have children. In v8, **only containers should have children**.
Examples of leaf nodes include:
- `Sprite`
- `Text`
- `Graphics`
- `Mesh`
- `TilingSprite`
- `HTMLText`
Attempting to add children to a leaf node will not result in a runtime error, however, you may run into unexpected rendering behavior. Therefore, If nesting is required, wrap leaf nodes in a `Container`.
**Before v8 (invalid in v8):**
```ts
const sprite = new Sprite();
sprite.addChild(anotherSprite); // ❌ Invalid in v8
```
**v8 approach:**
```ts
const group = new Container();
group.addChild(sprite);
group.addChild(anotherSprite); // ✅ Valid
```
## Transforms
All scene objects in PixiJS have several properties that control their position, rotation, scale, and alpha. These properties are inherited by child objects, allowing you to apply transformations to groups of objects easily.
You will often use these properties to position and animate objects in your scene.
| Property | Description |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **position** | X- and Y-position are given in pixels and change the position of the object relative to its parent, also available directly as `object.x` / `object.y` |
| **rotation** | Rotation is specified in radians, and turns an object clockwise (0.0 - 2 \* Math.PI) |
| **angle** | Angle is an alias for rotation that is specified in degrees instead of radians (0.0 - 360.0) |
| **pivot** | Point the object rotates around, in pixels - also sets origin for child objects |
| **alpha** | Opacity from 0.0 (fully transparent) to 1.0 (fully opaque), inherited by children |
| **scale** | Scale is specified as a percent with 1.0 being 100% or actual-size, and can be set independently for the x and y axis |
| **skew** | Skew transforms the object in x and y similar to the CSS skew() function, and is specified in radians |
| **anchor?** | Anchor is a percentage-based offset for the sprite's position and rotation. This is different from the `pivot` property, which is a pixel-based offset. |
### **Anchor vs Pivot**
Some leaf nodes have an additional property called `anchor`, which is a percentage-based offset for the nodes position and rotation. This is different from the `pivot` property, which is a pixel-based offset. Understanding the difference between anchor and pivot is critical when positioning or rotating a node.
:::info
Setting either pivot or anchor visually moves the node. This differs from CSS where changing `transform-origin` does not affect the element's position.
:::
#### **Anchor**
- Available only on `Sprite`
- Defined in normalized values `(0.0 to 1.0)`
- `(0, 0)` is the top-left, `(0.5, 0.5)` is the center
- Changes both position and rotation origin
```ts
sprite.anchor.set(0.5); // center
sprite.rotation = Math.PI / 4; // Rotate 45 degrees around the center
```
#### **Pivot**
- Available on all `Container`s
- Defined in **pixels**, not normalized
```ts
const sprite = new Sprite(texture);
sprite.width = 100;
sprite.height = 100;
sprite.pivot.set(50, 50); // Center of the container
container.rotation = Math.PI / 4; // Rotate 45 degrees around the pivot
```
## Measuring Bounds
There are two types of bounds in PixiJS:
- **Local bounds** represent the object’s dimensions in its own coordinate space. Use `getLocalBounds()`.
- **Global bounds** represent the object's bounding box in world coordinates. Use `getBounds()`.
```ts
const local = container.getLocalBounds();
const global = container.getBounds();
```
If performance is critical you can also provide a custom `boundsArea` to avoid per-child measurement entirely.
### Changing size
To change the size of a container, you can use the `width` and `height` properties. This will scale the container to fit the specified dimensions:
```ts
const container = new Container();
container.width = 100;
container.height = 200;
```
Setting the `width` and `height` individually can be an expensive operation, as it requires recalculating the bounds of the container and its children. To avoid this, you can use `setSize()` to set both properties at once:
```ts
const container = new Container();
container.setSize(100, 200);
const size = container.getSize(); // { width: 100, height: 200 }
```
This method is more efficient than setting `width` and `height` separately, as it only requires one bounds calculation.
## Masking Scene Objects
PixiJS supports **masking**, allowing you to restrict the visible area of a scene object based on another object's shape.
This is useful for creating effects like cropping, revealing, or hiding parts of your scene.
### Types of Masks
- **Graphics-based masks**: Use a `Graphics` object to define the shape.
- **Sprite-based masks**: Use a `Sprite` or other renderable object.
```ts
const shape = new Graphics().circle(100, 100, 50).fill(0x000000);
const maskedSprite = new Sprite(texture);
maskedSprite.mask = shape;
stage.addChild(shape);
stage.addChild(maskedSprite);
```
### Inverse Masks
To create an inverse mask, you can use the `setMask` property and set its `inverse` option to `true`. This will render everything outside the mask.
```ts
const inverseMask = new Graphics().rect(0, 0, 200, 200).fill(0x000000);
const maskedContainer = new Container();
maskedContainer.setMask({ mask: inverseMask, inverse: true });
maskedContainer.addChild(sprite);
stage.addChild(inverseMask);
stage.addChild(maskedContainer);
```
### Notes on Masking
- The mask is **not rendered**; it's used only to define the visible area. However, it must be added to the display list.
- Only one mask can be assigned per object.
- For advanced blending, use **alpha masks** or **filters** (covered in later guides).
## Filters
Another common use for Container objects is as hosts for filtered content. Filters are an advanced, WebGL/WebGPU-only feature that allows PixiJS to perform per-pixel effects like blurring and displacements. By setting a filter on a Container, the area of the screen the Container encompasses will be processed by the filter after the Container's contents have been rendered.
```ts
const container = new Container();
const sprite = new Sprite(texture);
const filter = new BlurFilter({ strength: 8, quality: 4, kernelSize: 5 });
container.filters = [filter];
container.addChild(sprite);
```
:::info
Filters should be used somewhat sparingly. They can slow performance and increase memory usage if used too often in a scene.
:::
Below are list of filters available by default in PixiJS. There is, however, a community repository with [many more filters](https://github.com/pixijs/filters).
| Filter | Description |
| ------------------ | ------------------------------------------------------------------------------------------------------------- |
| AlphaFilter | Similar to setting `alpha` property, but flattens the Container instead of applying to children individually. |
| BlurFilter | Apply a blur effect |
| ColorMatrixFilter | A color matrix is a flexible way to apply more complex tints or color transforms (e.g., sepia tone). |
| DisplacementFilter | Displacement maps create visual offset pixels, for instance creating a wavy water effect. |
| NoiseFilter | Create random noise (e.g., grain effect). |
Under the hood, each Filter we offer out of the box is written in both glsl (for WebGL) and wgsl (for WebGPU). This means all filters should work on both renderers.
## Tinting
You can tint any scene object by setting the `tint` property. It modifies the color of the rendered pixels, similar to multiplying a tint color over the object.
```ts
const sprite = new Sprite(texture);
sprite.tint = 0xff0000; // Red tint
sprite.tint = 'red'; // Red tint
```
The `tint` is inherited by child objects unless they specify their own. If only part of your scene should be tinted, place it in a separate container.
A value of `0xFFFFFF` disables tinting.
```ts
const sprite = new Sprite(texture);
sprite.tint = 0x00ff00; // Green tint
sprite.tint = 0xffffff; // No tint
```
PixiJS supports a variety of color formats and you can find more information from the [Color documentation](../color.md).
## Blend Modes
Blend modes determine how colors of overlapping objects are combined. PixiJS supports a variety of blend modes, including:
- `normal`: Default blend mode.
- `add`: Adds the colors of the source and destination pixels.
- `multiply`: Multiplies the colors of the source and destination pixels.
- `screen`: Inverts the colors, multiplies them, and inverts again.
We also support may more advanced blend modes, such as `subtract`, `difference`, and `overlay`. You can find the full list of blend modes in the [Blend Modes documentation](../filters.md#advanced-blend-modes).
```ts
const sprite = new Sprite(texture);
sprite.blendMode = 'multiply'; // Multiply blend mode
```
## Interaction
PixiJS provides a powerful interaction system that allows you to handle user input events like clicks/hovers. To enable interaction on a scene object, can be as simple as setting its `interactive` property to `true`.
```ts
const sprite = new Sprite(texture);
sprite.interactive = true;
sprite.on('click', (event) => {
console.log('Sprite clicked!', event);
});
```
We have a detailed guide on [Interaction](../events.md) that covers how to set up and manage interactions, including hit testing, pointer events, and more. We highly recommend checking it out.
## Using `onRender`
The `onRender` callback allows you to run logic every frame when a scene object is rendered. This is useful for lightweight animation and update logic:
```ts
const container = new Container();
container.onRender = () => {
container.rotation += 0.01;
};
```
Note: In PixiJS v8, this replaces the common v7 pattern of overriding `updateTransform`, which no longer runs every frame. The `onRender` function is registered with the render group the container belongs to.
To remove the callback:
```ts
container.onRender = null;
```
---
## API Reference
- [Overview](https://pixijs.download/release/docs/scene.html)
- [Container](https://pixijs.download/release/docs/scene.Container.html)
- [ParticleContainer](https://pixijs.download/release/docs/scene.ParticleContainer.html)
- [Sprite](https://pixijs.download/release/docs/scene.Sprite.html)
- [TilingSprite](https://pixijs.download/release/docs/scene.TilingSprite.html)
- [NineSliceSprite](https://pixijs.download/release/docs/scene.NineSliceSprite.html)
- [Graphics](https://pixijs.download/release/docs/scene.Graphics.html)
- [Mesh](https://pixijs.download/release/docs/scene.Mesh.html)
- [Text](https://pixijs.download/release/docs/scene.Text.html)
- [Bitmap Text](https://pixijs.download/release/docs/scene.BitmapText.html)
- [HTMLText](https://pixijs.download/release/docs/scene.HTMLText.html)
---
## Mesh
# Mesh
PixiJS v8 offers a powerful `Mesh` system that provides full control over geometry, UVs, indices, shaders, and WebGL/WebGPU state. Meshes are ideal for custom rendering effects, advanced distortion, perspective manipulation, or performance-tuned rendering pipelines.
```ts
import { Texture, Mesh, MeshGeometry, Shader } from 'pixi.js';
const geometry = new MeshGeometry({
positions: new Float32Array([0, 0, 100, 0, 100, 100, 0, 100]),
uvs: new Float32Array([0, 0, 1, 0, 1, 1, 0, 1]),
indices: new Uint32Array([0, 1, 2, 0, 2, 3]),
});
const shader = Shader.from({
gl: {
vertex: `
attribute vec2 aPosition;
attribute vec2 aUV;
varying vec2 vUV;
void main() {
gl_Position = vec4(aPosition / 100.0 - 1.0, 0.0, 1.0);
vUV = aUV;
}
`,
fragment: `
precision mediump float;
varying vec2 vUV;
uniform sampler2D uSampler;
void main() {
gl_FragColor = texture2D(uSampler, vUV);
}
`,
},
resources: {
uSampler: Texture.from('image.png').source,
},
});
const mesh = new Mesh({ geometry, shader });
app.stage.addChild(mesh);
```
## **What Is a Mesh?**
A mesh is a low-level rendering primitive composed of:
- **Geometry**: Vertex positions, UVs, indices, and other attributes
- **Shader**: A GPU program that defines how the geometry is rendered
- **State**: GPU state configuration (e.g. blending, depth, stencil)
With these elements, you can build anything from simple quads to curved surfaces and procedural effects.
## **MeshGeometry**
All meshes in PixiJS are built using the `MeshGeometry` class. This class allows you to define the vertex positions, UV coordinates, and indices that describe the mesh's shape and texture mapping.
```ts
const geometry = new MeshGeometry({
positions: Float32Array, // 2 floats per vertex
uvs: Float32Array, // matching number of floats
indices: Uint32Array, // 3 indices per triangle
topology: 'triangle-list',
});
```
You can access and modify buffers directly:
```ts
geometry.positions[0] = 50;
geometry.uvs[0] = 0.5;
geometry.indices[0] = 1;
```
## Built-in Mesh Types
### MeshSimple
A minimal wrapper over `Mesh` that accepts vertex, UV, and index arrays directly. Suitable for fast static or dynamic meshes.
```ts
const mesh = new MeshSimple({
texture: Texture.from('image.png'),
vertices: new Float32Array([0, 0, 100, 0, 100, 100, 0, 100]),
uvs: new Float32Array([0, 0, 1, 0, 1, 1, 0, 1]),
indices: new Uint32Array([0, 1, 2, 0, 2, 3]),
});
```
- Use `autoUpdate = true` to update geometry per frame.
- Access `mesh.vertices` to read/write data.
### MeshRope
Bends a texture along a series of control points, often used for trails, snakes, and animated ribbons.
```ts
const points = [new Point(0, 0), new Point(100, 0), new Point(200, 50)];
const rope = new MeshRope({
texture: Texture.from('snake.png'),
points,
textureScale: 1, // optional
});
```
- `textureScale > 0` repeats texture; `0` stretches it.
- `autoUpdate = true` re-evaluates geometry each frame.
### MeshPlane
A flexible subdivided quad mesh, suitable for distortion or grid-based warping.
```ts
const plane = new MeshPlane({
texture: Texture.from('image.png'),
verticesX: 10,
verticesY: 10,
});
```
- Automatically resizes on texture update when `autoResize = true`.
### PerspectiveMesh
A special subclass of `MeshPlane` that applies perspective correction by transforming the UVs.
```ts
const mesh = new PerspectiveMesh({
texture: Texture.from('image.png'),
verticesX: 20,
verticesY: 20,
x0: 0,
y0: 0,
x1: 300,
y1: 30,
x2: 280,
y2: 300,
x3: 20,
y3: 280,
});
```
- Set corner coordinates via `setCorners(...)`.
- Ideal for emulating 3D projection in 2D.
---
## **API Reference**
- [Mesh](https://pixijs.download/release/docs/scene.Mesh.html)
- [MeshGeometry](https://pixijs.download/release/docs/scene.MeshGeometry.html)
- [MeshSimple](https://pixijs.download/release/docs/scene.MeshSimple.html)
- [MeshRope](https://pixijs.download/release/docs/scene.MeshRope.html)
- [MeshPlane](https://pixijs.download/release/docs/scene.MeshPlane.html)
- [PerspectiveMesh](https://pixijs.download/release/docs/scene.PerspectiveMesh.html)
- [Shader](https://pixijs.download/release/docs/rendering.Shader.html)
- [Texture](https://pixijs.download/release/docs/rendering.Texture.html)
---
## NineSlice Sprite
# NineSlice Sprite
`NineSliceSprite` is a specialized type of `Sprite` that allows textures to be resized while preserving the corners and edges. It is particularly useful for building scalable UI elements like buttons, panels, or windows with rounded or decorated borders.
```ts
import { NineSliceSprite, Texture } from 'pixi.js';
const nineSlice = new NineSliceSprite({
texture: Texture.from('button.png'),
leftWidth: 15,
topHeight: 15,
rightWidth: 15,
bottomHeight: 15,
width: 200,
height: 80,
});
app.stage.addChild(nineSlice);
```
You can also pass just a texture, and the slice values will fall back to defaults or be inferred from the texture’s `defaultBorders`.
## **How NineSlice Works**
Here’s how a nine-slice texture is divided:
```js
A B
+---+----------------------+---+
C | 1 | 2 | 3 |
+---+----------------------+---+
| | | |
| 4 | 5 | 6 |
| | | |
+---+----------------------+---+
D | 7 | 8 | 9 |
+---+----------------------+---+
Areas:
- 1, 3, 7, 9: Corners (remain unscaled)
- 2, 8: Top/Bottom center (stretched horizontally)
- 4, 6: Left/Right center (stretched vertically)
- 5: Center (stretched in both directions)
```
This ensures that decorative corners are preserved and the center content can scale as needed.
## **Width and Height Behavior**
Setting `.width` and `.height` on a `NineSliceSprite` updates the **geometry vertices**, not the texture UVs. This allows the texture to repeat or stretch correctly based on the slice regions. This also means that the `width` and `height` properties are not the same as the `scale` properties.
```ts
// The texture will stretch to fit the new dimensions
nineSlice.width = 300;
nineSlice.height = 100;
// The nine-slice will increase in size uniformly
nineSlice.scale.set(2); // Doubles the size
```
### **Original Width and Height**
If you need to know the original size of the nine-slice, you can access it through the `originalWidth` and `originalHeight` properties. These values are set when the `NineSliceSprite` is created and represent the dimensions of the texture before any scaling or resizing is applied.
```ts
console.log(nineSlice.originalWidth);
console.log(nineSlice.originalHeight);
```
## **Dynamic Updates**
You can change slice dimensions or size at runtime:
```ts
nineSlice.leftWidth = 20;
nineSlice.topHeight = 25;
```
Each setter triggers a geometry update to reflect the changes.
---
## **API Reference**
- [NineSliceSprite](https://pixijs.download/release/docs/scene.NineSliceSprite.html)
---
## Particle Container
# Particle Container
PixiJS v8 introduces a high-performance particle system via the `ParticleContainer` and `Particle` classes. Designed for rendering vast numbers of lightweight visuals—like sparks, bubbles, bunnies, or explosions—this system provides raw speed by stripping away all non-essential overhead.
:::warning **Experimental API Notice**
The Particle API is stable but **experimental**. Its interface may evolve in future PixiJS versions. We welcome feedback to help guide its development.
:::
```ts
import { ParticleContainer, Particle, Texture } from 'pixi.js';
const texture = Texture.from('bunny.png');
const container = new ParticleContainer({
dynamicProperties: {
position: true, // default
scale: false,
rotation: false,
color: false,
},
});
for (let i = 0; i < 100000; i++) {
const particle = new Particle({
texture,
x: Math.random() * 800,
y: Math.random() * 600,
});
container.addParticle(particle);
}
app.stage.addChild(container);
```
## **Why Use ParticleContainer?**
- **Extreme performance**: Render hundreds of thousands or even millions of particles with high FPS.
- **Lightweight design**: Particles are more efficient than `Sprite`, lacking extra features like children, events, or filters.
- **Fine-grained control**: Optimize rendering by declaring which properties are dynamic (updated every frame) or static (set once).
### **Performance Tip: Static vs. Dynamic**
- **Dynamic properties** are uploaded to the GPU every frame.
- **Static properties** are uploaded only when `update()` is called.
Declare your needs explicitly:
```ts
const container = new ParticleContainer({
dynamicProperties: {
position: true,
rotation: true,
scale: false,
color: false,
},
});
```
If you later modify a static property or the particle list, you must call:
```ts
container.update();
```
## **Limitations and API Differences**
`ParticleContainer` is designed for speed and simplicity. As such, it doesn't support the full `Container` API:
### ❌ Not Available:
- `addChild()`, `removeChild()`
- `getChildAt()`, `setChildIndex()`
- `swapChildren()`, `reparentChild()`
### ✅ Use Instead:
- `addParticle(particle)`
- `removeParticle(particle)`
- `removeParticles(beginIndex, endIndex)`
- `addParticleAt(particle, index)`
- `removeParticleAt(index)`
These methods operate on the `.particleChildren` array and maintain the internal GPU buffers correctly.
## **Creating a Particle**
A `Particle` supports key display properties, and is far more efficient than `Sprite`.
### **Particle Example**
```ts
const particle = new Particle({
texture: Texture.from('spark.png'),
x: 200,
y: 100,
scaleX: 0.8,
scaleY: 0.8,
rotation: Math.PI / 4,
tint: 0xff0000,
alpha: 0.5,
});
```
You can also use the shorthand:
```ts
const particle = new Particle(Texture.from('spark.png'));
```
---
## **API Reference**
- [ParticleContainer](https://pixijs.download/release/docs/scene.ParticleContainer.html)
- [Particle](https://pixijs.download/release/docs/scene.Particle.html)
---
## Sprite
# Sprite
Sprites are the foundational visual elements in PixiJS. They represent a single image to be displayed on the screen. Each [Sprite](https://pixijs.download/release/docs/scene.Sprite.html) contains a [Texture](https://pixijs.download/release/docs/rendering.Texture.html) to be drawn, along with all the transformation and display state required to function in the scene graph.
```ts
import { Assets, Sprite } from 'pixi.js';
const texture = await Assets.load('path/to/image.png');
const sprite = new Sprite(texture);
sprite.anchor.set(0.5);
sprite.position.set(100, 100);
sprite.scale.set(2);
sprite.rotation = Math.PI / 4; // Rotate 45 degrees
```
## Updating the Texture
If you change the texture of a sprite, it will automatically:
- Rebind listeners for texture updates
- Recalculate width/height if set so that the visual size remains the same
- Trigger a visual update
```ts
const texture = Assets.get('path/to/image.png');
sprite.texture = texture;
```
## **Scale vs Width/Height**
Sprites inherit `scale` from `Container`, allowing for percentage-based resizing:
```ts
sprite.scale.set(2); // Double the size
```
Sprites also have `width` and `height` properties that act as _convenience setters_ for `scale`, based on the texture’s dimensions:
```ts
sprite.width = 100; // Automatically updates scale.x
// sets: sprite.scale.x = 100 / sprite.texture.orig.width;
```
---
## API Reference
- [Sprite](https://pixijs.download/release/docs/scene.Sprite.html)
- [Texture](https://pixijs.download/release/docs/rendering.Texture.html)
- [Assets](https://pixijs.download/release/docs/assets.Assets.html)
---
## Bitmap Text
# Bitmap Text
`BitmapText` is a high-performance text rendering solution in PixiJS. Unlike the `Text` class, which rasterizes each string into a new texture, `BitmapText` draws characters from a pre-generated texture atlas. This design allows you to render tens of thousands of text objects with minimal overhead.
```ts
import { Assets, BitmapText } from 'pixi.js';
await Assets.load('fonts/MyFont.fnt');
const text = new BitmapText({
text: 'Loaded font!',
style: {
fontFamily: 'MyFont',
fontSize: 32,
fill: '#ffcc00',
},
});
```
## **Why Use `BitmapText`?**
- ✅ **Fast rendering**: Perfect for HUDs, score counters, timers, etc.
- ✅ **No per-frame rasterization**: Text changes are cheap.
- ✅ **Efficient memory usage**: Shares glyph textures across all instances.
- ✅ **Supports MSDF/SDF fonts**: Crisp scaling without blurring.
**Ideal use cases**:
- Frequently updating text
- Large numbers of text instances
- High-performance or mobile projects
## **How to Load and Use Bitmap Fonts**
### Font Loading
PixiJS supports AngelCode BMFont format and MSDF-compatible `.fnt` and `.xml` files. You can load these files using the `Assets` API.
Once loaded, you can create a `BitmapText` instance with the loaded font using the `fontFamily` property.
```ts
import { Assets, BitmapText } from 'pixi.js';
await Assets.load('fonts/MyFont.fnt');
const text = new BitmapText({
text: 'Loaded font!',
style: {
fontFamily: 'MyFont',
fontSize: 32,
fill: '#ffcc00',
},
});
```
### MSDF and SDF Fonts
PixiJS supports **MSDF** (multi-channel signed distance field) and **SDF** formats for crisp, resolution-independent text. These fonts remain sharp at any size and scale.
You can generate MSDF/SDF fonts using tools like [AssetPack](https://pixijs.io/assetpack/) which can take a `.ttf` or `.otf` font and generate a bitmap font atlas with MSDF/SDF support.
Using MSDF/SDF fonts is similar to using regular bitmap fonts and just requires you to load the appropriate font file:
```ts
import { Assets, BitmapText } from 'pixi.js';
await Assets.load('fonts/MyMSDFFont.fnt');
const text = new BitmapText({
text: 'Loaded MSDF font!',
style: {
fontFamily: 'MyMSDFFont',
},
});
```
# **Limitations and Caveats**
### ❌ Cannot Update Resolution
`BitmapText.resolution` is not mutable. It must be handled by the `BitmapFont`
```ts
text.resolution = 2;
// ⚠️ [BitmapText] dynamically updating the resolution is not supported.
```
### ⚠️ Large Character Sets Not Practical
Bitmap fonts are limited by texture size. CJK or emoji-rich sets may require too much memory. Use `Text` or `HTMLText` for dynamic internationalization or emoji support.
---
## **API Reference**
- [BitmapText](https://pixijs.download/release/docs/scene.BitmapText.html)
- [BitmapFont](https://pixijs.download/release/docs/text.BitmapFont.html)
- [Assets](https://pixijs.download/release/docs/assets.Assets.html)
- [TextStyle](https://pixijs.download/release/docs/text.TextStyle.html)
- [FillStyle](https://pixijs.download/release/docs/scene.FillStyle.html)
- [StrokeStyle](https://pixijs.download/release/docs/scene.StrokeStyle.html)
---
## Text (Canvas)
# Text (Canvas)
The `Text` class in PixiJS allows you to render styled, dynamic strings as display objects in your scene. Under the hood, PixiJS rasterizes the text using the browser’s canvas text API, then converts that into a texture. This makes `Text` objects behave like sprites: they can be moved, rotated, scaled, masked, and rendered efficiently.
```ts
import { Text, TextStyle, Assets } from 'pixi.js';
// Load font before use
await Assets.load({
src: 'my-font.woff2',
data: {
family: 'MyFont', // optional
}
});
const myText = new Text({
text: 'Hello PixiJS!',
style: {
fill: '#ffffff',
fontSize: 36,
fontFamily: 'MyFont',
}
anchor: 0.5
});
app.stage.addChild(myText);
```
## Text Styling
The `TextStyle` class allows you to customize the appearance of your text. You can set properties like:
- `fontFamily`
- `fontSize`
- `fontWeight`
- `fill` (color)
- `align`
- `stroke` (outline)
See the guide on [TextStyle](./style.md) for more details.
## **Changing Text Dynamically**
You can update the text string or its style at runtime:
```ts
text.text = 'Updated!';
text.style.fontSize = 40; // Triggers re-render
```
:::warning
Changing text or style re-rasterizes the object. Avoid doing this every frame unless necessary.
:::
## Text Resolution
The `resolution` property of the `Text` class determines the pixel density of the rendered text. By default, it uses the resolution of the renderer.
However, you can set text resolution independently from the renderer for sharper text, especially on high-DPI displays.
```ts
const myText = new Text('Hello', {
resolution: 2, // Higher resolution for sharper text
});
// change resolution
myText.resolution = 1; // Reset to default
```
## Font Loading
PixiJS supports loading custom fonts via the `Assets` API. It supports many of the common font formats:
- `woff`
- `woff2`
- `ttf`
- `otf`
It is recommended to use `woff2` for the best performance and compression.
```js
await Assets.load({
src: 'my-font.woff2',
data: {},
});
```
Below is a list of properties you can pass in the `data` object when loading a font:
| Property | Description |
| ------------------- | ------------------------------------------------------- |
| **family** | The font family name. |
| **display** | The display property of the FontFace interface. |
| **featureSettings** | The featureSettings property of the FontFace interface. |
| **stretch** | The stretch property of the FontFace interface. |
| **style** | The style property of the FontFace interface. |
| **unicodeRange** | The unicodeRange property of the FontFace interface. |
| **variant** | The variant property of the FontFace interface. |
| **weights** | The weights property of the FontFace interface. |
---
## API Reference
- [Text](https://pixijs.download/release/docs/scene.Text.html)
- [TextStyle](https://pixijs.download/release/docs/text.TextStyle.html)
- [FillStyle](https://pixijs.download/release/docs/scene.FillStyle.html)
- [StrokeStyle](https://pixijs.download/release/docs/scene.StrokeStyle.html)
---
## HTML Text
# HTML Text
`HTMLText` enables styled, formatted HTML strings to be rendered as part of the PixiJS scene graph. It uses an SVG `` to embed browser-native HTML inside your WebGL canvas.
This makes it ideal for rendering complex typography, inline formatting, emojis, and layout effects that are hard to replicate using traditional canvas-rendered text.
```ts
import { HTMLText } from 'pixi.js';
const html = new HTMLText({
text: 'Hello PixiJS!',
style: {
fontFamily: 'Arial',
fontSize: 24,
fill: '#ff1010',
align: 'center',
},
});
app.stage.addChild(html);
```
## **Why Use `HTMLText`?**
- ✅ Supports inline tags like `, `, ``, etc.
- ✅ Compatible with emojis, Unicode, and RTL text
- ✅ Fine-grained layout control via CSS
- ✅ Tag-based style overrides (`, `, etc.)
## **Async Rendering Behavior**
HTML text uses SVG `` to draw HTML inside the canvas. As a result:
- Rendering occurs **asynchronously**. Typically after the next frame.
- Text content is not immediately visible after instantiation.
## **Styling HTMLText**
`HTMLTextStyle` extends `TextStyle` and adds:
- **HTML-aware tag-based styles** via `tagStyles`
- **CSS override support** via `cssOverrides`
```ts
const fancy = new HTMLText({
text: 'Red, Blue',
style: {
fontFamily: 'DM Sans',
fontSize: 32,
fill: '#ffffff',
tagStyles: {
red: { fill: 'red' },
blue: { fill: 'blue' },
},
},
});
```
### **CSS Overrides**
You can apply CSS styles to the text using the `cssOverrides` property. This allows you to set properties like `text-shadow`, `text-decoration`, and more.
```ts
fancy.style.addOverride('text-shadow: 2px 2px 4px rgba(0,0,0,0.5)');
```
---
## **API Reference**
- [HTMLText](https://pixijs.download/release/docs/scene.HTMLText.html)
- [HTMLTextStyle](https://pixijs.download/release/docs/text.HTMLTextStyle.html)
---
## Text
# Text
Text is essential in games and applications, and PixiJS provides three different systems to cover different needs:
- **`Text`**: High-quality, styled raster text
- **`BitmapText`**: Ultra-fast, GPU-optimized bitmap fonts
- **`HTMLText`**: Richly formatted HTML inside the Pixi scene
Each approach has tradeoffs in fidelity, speed, and flexibility. Let’s look at when and how to use each one.
## `Text`: Rich Dynamic Text with Styles
The `Text` class renders using the browser's native text engine, and then converts the result into a texture. This allows for:
- Full CSS-like font control
- Drop shadows, gradients, and alignment
- Support for dynamic content and layout
**Use it when**:
- You need detailed font control
- Text changes occasionally
- Fidelity is more important than speed
**Avoid when**:
- You're changing text every frame
- You need to render hundreds of instances
---
## `BitmapText`: High-Performance Glyph Rendering
`BitmapText` uses a pre-baked bitmap font image for glyphs, bypassing font rasterization entirely. This gives:
- High rendering speed
- Ideal for thousands of changing labels
- Low memory usage
**Use it when**:
- You need to render lots of dynamic text
- You prioritize performance over styling
- You predefine the characters and styles
**Avoid when**:
- You need fine-grained style control
- You change fonts or font sizes frequently
To use `BitmapText`, you must first register a bitmap font via:
- `BitmapFont.from(...)` to create on the fly, or
- `Assets.load(...)` if using a 3rd-party BMFont or AngelCode export
---
## `HTMLText`: Styled HTML Inside the Scene
`HTMLText` lets you render actual HTML markup in your PixiJS scene. This allows:
- `, `, `` style formatting
- Fine layout and text flow
- Emoji, RTL, links, and more
**Use it when**:
- You want complex HTML-style markup
- Static or semi-dynamic content
- Your users expect "document-like" layout
**Avoid when**:
- You need pixel-perfect performance
- You're rendering hundreds of text blocks
- You need GPU text effects
## Next Steps
Each text type has a corresponding guide that covers setup, font loading, style options, and limitations in more detail:
- [Text Guide →](./canvas.md)
- [BitmapText Guide →](./bitmap.md)
- [HTMLText Guide →](./html.md)
---
## API Reference
- [Text](https://pixijs.download/release/docs/scene.Text.html)
- [BitmapText](https://pixijs.download/release/docs/scene.BitmapText.html)
- [HTMLText](https://pixijs.download/release/docs/scene.HTMLText.html)
- [TextStyle](https://pixijs.download/release/docs/text.TextStyle.html)
- [BitmapFont](https://pixijs.download/release/docs/text.BitmapFont.html)
- [FillStyle](https://pixijs.download/release/docs/scene.FillStyle.html)
- [StrokeStyle](https://pixijs.download/release/docs/scene.StrokeStyle.html)
---
## Text Style
# Text Style
The `TextStyle` class encapsulates all visual styling properties for text. You can define colors, font families, stroke, shadows, alignment, line spacing, word wrapping, and more.
A `TextStyle` instance can be reused across multiple `Text` objects, making your code cleaner and improving memory efficiency.
```ts
import { TextStyle } from 'pixi.js';
const style = new TextStyle({
fontFamily: 'Arial',
fontSize: 30,
fill: '#ffffff',
stroke: '#000000',
strokeThickness: 3,
dropShadow: {
color: '#000000',
blur: 5,
distance: 4,
angle: Math.PI / 4,
alpha: 0.5,
},
});
const label = new Text({
text: 'Score: 1234',
style,
});
```
## Fill and Stroke
Using fills and strokes are identical to that of the `Graphics` class. You can find more details about them in the [Graphics Fills](../graphics/graphics-fill.md) section.
```ts
// Using a number
const fill = 0xff0000;
// Using a hex string
const fill = '#ff0000';
// Using an array
const fill = [255, 0, 0];
// Using a Color object
const color = new Color();
const obj4 = color;
// Using a gradient
const fill = new FillGradient({
type: 'linear',
colorStops: [
{ offset: 0, color: 'yellow' },
{ offset: 1, color: 'green' },
],
});
// Using a pattern
const txt = await Assets.load('https://pixijs.com/assets/bg_scene_rotate.jpg');
const fill = new FillPattern(txt, 'repeat');
// Use the fill in a TextStyle
const style = new TextStyle({
fontSize: 48,
fill: fill,
stroke: {
fill,
width: 4,
},
});
```
## Drop Shadow
In v8 `dropShadow` and its properties are now objects. To update a drop shadow, you can set the properties directly on the `dropShadow` object.
```ts
const style = new TextStyle({
dropShadow: {
color: '#000000',
alpha: 0.5,
angle: Math.PI / 4,
blur: 5,
distance: 4,
},
});
style.dropShadow.color = '#ff0000'; // Change shadow color
```
---
## **API Reference**
- [TextStyle](https://pixijs.download/release/docs/text.TextStyle.html)
- [Text](https://pixijs.download/release/docs/scene.Text.html)
- [BitmapText](https://pixijs.download/release/docs/scene.BitmapText.html)
- [HTMLText](https://pixijs.download/release/docs/scene.HTMLText.html)
- [FillStyle](https://pixijs.download/release/docs/scene.FillStyle.html)
- [StrokeStyle](https://pixijs.download/release/docs/scene.StrokeStyle.html)
---
## Tiling Sprite
# Tiling Sprite
A `TilingSprite` is a high-performance way to render a repeating texture across a rectangular area. Instead of stretching the texture, it repeats (tiles) it to fill the given space, making it ideal for backgrounds, parallax effects, terrain, and UI panels.
```ts
import { TilingSprite, Texture } from 'pixi.js';
const tilingSprite = new TilingSprite({
texture: Texture.from('assets/tile.png'),
width: 400,
height: 300,
});
app.stage.addChild(tilingSprite);
```
## What is a TilingSprite?
- It draws a texture repeatedly across a defined area.
- The texture is not scaled by default unless you adjust `tileScale`.
- The sprite's overall `width` and `height` determine how much area the tiles fill, independent of the texture's native size.
- The pattern's offset, scale, and rotation can be controlled independently of the object's transform.
## Key Properties
| Property | Description |
| ---------------------- | ---------------------------------------------------------------------- |
| `texture` | The texture being repeated |
| `tilePosition` | `ObservablePoint` controlling offset of the tiling pattern |
| `tileScale` | `ObservablePoint` controlling scaling of each tile |
| `tileRotation` | Number controlling the rotation of the tile pattern |
| `width` / `height` | The size of the area to be filled by tiles |
| `anchor` | Adjusts origin point of the TilingSprite |
| `applyAnchorToTexture` | If `true`, the anchor affects the starting point of the tiling pattern |
| `clampMargin` | Margin adjustment to avoid edge artifacts (default: `0.5`) |
### Width & Height vs Scale
Unlike `Sprite`, setting `width` and `height` in a `TilingSprite` directly changes the visible tiling area. It **does not affect the scale** of the tiles.
```ts
// Makes the tiling area bigger
tilingSprite.width = 800;
tilingSprite.height = 600;
// Keeps tiles the same size, just tiles more of them
```
To scale the tile pattern itself, use `tileScale`:
```ts
// Makes each tile appear larger
tilingSprite.tileScale.set(2, 2);
```
### Anchor and applyAnchorToTexture
- `anchor` sets the pivot/origin point for positioning the TilingSprite.
- If `applyAnchorToTexture` is `true`, the anchor also affects where the tile pattern begins.
- By default, the tile pattern starts at (0, 0) in local space regardless of anchor.
---
## API Reference
- [TilingSprite](https://pixijs.download/release/docs/scene.TilingSprite.html)
- [Texture](https://pixijs.download/release/docs/rendering.Texture.html)
---
## Documentation for LLMs
# Documentation for LLMs
PixiJS supports the [`llms.txt`](https://llmstxt.org/) convention for making documentation accessible to large language models (LLMs) and the applications that utilize them.
## Available Files
We provide several documentation files at different compression levels to accommodate various context window sizes:
- [`/llms.txt`](https://pixijs.com/llms.txt) - An index of available documentation files
- [`/llms-full.txt`](https://pixijs.com/llms-full.txt) - Complete PixiJS API documentation including all classes, methods, and examples
- [`/llms-medium.txt`](https://pixijs.com/llms-medium.txt) - Compressed documentation optimized for medium context windows
These files are automatically generated and updated daily from our TypeScript definition files and documentation sources.
# Full API Reference
```typescript
// Generated by dts-bundle-generator v9.5.1
/**
* Minimal `EventEmitter` interface that is molded against the Node.js
* `EventEmitter` interface.
*/
export declare class EventEmitter {
static prefixed: string | boolean;
/**
* Return an array listing the events for which the emitter has registered
* listeners.
*/
eventNames(): Array>;
/**
* Return the listeners registered for a given event.
*/
listeners>(event: T): Array>;
/**
* Return the number of listeners listening to a given event.
*/
listenerCount(event: EventEmitter.EventNames): number;
/**
* Calls each of the listeners registered for a given event.
*/
emit>(event: T, ...args: EventEmitter.EventArgs): boolean;
/**
* Add a listener for a given event.
*/
on>(event: T, fn: EventEmitter.EventListener, context?: Context): this;
addListener>(event: T, fn: EventEmitter.EventListener, context?: Context): this;
/**
* Add a one-time listener for a given event.
*/
once>(event: T, fn: EventEmitter.EventListener, context?: Context): this;
/**
* Remove the listeners of a given event.
*/
removeListener>(event: T, fn?: EventEmitter.EventListener, context?: Context, once?: boolean): this;
off>(event: T, fn?: EventEmitter.EventListener, context?: Context, once?: boolean): this;
/**
* Remove all listeners, or those of the specified event.
*/
removeAllListeners(event?: EventEmitter.EventNames): this;
}
export declare namespace EventEmitter {
export interface ListenerFn {
(...args: Args): void;
}
export interface EventEmitterStatic {
new (): EventEmitter;
}
/**
* `object` should be in either of the following forms:
* ```
* interface EventTypes {
* 'event-with-parameters': any[]
* 'event-with-example-handler': (...args: any[]) => void
* }
* ```
*/
export type ValidEventTypes = string | symbol | object;
export type EventNames = T extends string | symbol ? T : keyof T;
export type ArgumentMap = {
[K in keyof T]: T[K] extends (...args: any[]) => void ? Parameters : T[K] extends any[] ? T[K] : any[];
};
export type EventListener> = T extends string | symbol ? (...args: any[]) => void : (...args: ArgumentMap>[Extract]) => void;
export type EventArgs> = Parameters>;
export const EventEmitter: EventEmitterStatic;
}
declare type RgbColor = {
r: number;
g: number;
b: number;
};
declare type HslColor = {
h: number;
s: number;
l: number;
};
declare type HsvColor = {
h: number;
s: number;
v: number;
};
declare type WithAlpha = O & {
a: number;
};
declare type RgbaColor = WithAlpha;
declare type HslaColor = WithAlpha;
declare type HsvaColor = WithAlpha;
/**
* Array of RGBA color components, where each component is a number between 0 and 1.
* The array must contain exactly 4 numbers in the order: red, green, blue, alpha.
* @example
* ```ts
* // Full white (opaque)
* const white: RgbaArray = [1, 1, 1, 1];
*
* // Semi-transparent red
* const transparentRed: RgbaArray = [1, 0, 0, 0.5];
* ```
* @remarks
* - All components must be between 0 and 1
* - Array must contain exactly 4 values
* - Order is [red, green, blue, alpha]
*/
export type RgbaArray = [
number,
number,
number,
number
];
/**
* Valid color formats supported by PixiJS. These types extend from [colord](https://www.npmjs.com/package/colord)
* with additional PixiJS-specific formats.
*
* Common Formats:
* ```ts
* // CSS Color Names
* new Color('red');
* new Color('blue');
* new Color('green');
*
* // Hex Values
* new Color(0xff0000); // RGB integer
* new Color('#ff0000'); // 6-digit hex
* new Color('#f00'); // 3-digit hex
* new Color('#ff0000ff'); // 8-digit hex (with alpha)
* new Color('#f00f'); // 4-digit hex (with alpha)
*
* // RGB/RGBA Objects
* new Color({ r: 255, g: 0, b: 0 });
* new Color({ r: 255, g: 0, b: 0, a: 0.5 });
*
* // RGB/RGBA Strings
* new Color('rgb(255, 0, 0)');
* new Color('rgba(255, 0, 0, 0.5)');
* new Color('rgb(100% 0% 0%)');
* new Color('rgba(100% 0% 0% / 50%)');
*
* // Arrays (normalized 0-1)
* new Color([1, 0, 0]); // RGB
* new Color([1, 0, 0, 0.5]); // RGBA
* new Color(new Float32Array([1, 0, 0, 0.5]));
*
* // Arrays (0-255)
* new Color(new Uint8Array([255, 0, 0]));
* new Color(new Uint8ClampedArray([255, 0, 0, 128]));
*
* // HSL/HSLA
* new Color({ h: 0, s: 100, l: 50 });
* new Color({ h: 0, s: 100, l: 50, a: 0.5 });
* new Color('hsl(0, 100%, 50%)');
* new Color('hsla(0deg 100% 50% / 50%)');
*
* // HSV/HSVA
* new Color({ h: 0, s: 100, v: 100 });
* new Color({ h: 0, s: 100, v: 100, a: 0.5 });
* ```
* @remarks
* - All color values are normalized internally to 0-1 range
* - Alpha is always between 0-1
* - Invalid colors will throw an error
* - Original format is preserved when possible
* @since 7.2.0
*/
export type ColorSource = string | number | number[] | Float32Array | Uint8Array | Uint8ClampedArray | HslColor | HslaColor | HsvColor | HsvaColor | RgbColor | RgbaColor | Color | number;
/**
* Color utility class for managing colors in various formats. Provides a unified way to work
* with colors across your PixiJS application.
*
* Features:
* - Accepts multiple color formats (hex, RGB, HSL, etc.)
* - Automatic format conversion
* - Color manipulation methods
* - Component access (r,g,b,a)
* - Chainable operations
* @example
* ```js
* import { Color } from 'pixi.js';
*
* new Color('red').toArray(); // [1, 0, 0, 1]
* new Color(0xff0000).toArray(); // [1, 0, 0, 1]
* new Color('ff0000').toArray(); // [1, 0, 0, 1]
* new Color('#f00').toArray(); // [1, 0, 0, 1]
* new Color('0xff0000ff').toArray(); // [1, 0, 0, 1]
* new Color('#f00f').toArray(); // [1, 0, 0, 1]
* new Color({ r: 255, g: 0, b: 0, a: 0.5 }).toArray(); // [1, 0, 0, 0.5]
* new Color('rgb(255, 0, 0, 0.5)').toArray(); // [1, 0, 0, 0.5]
* new Color([1, 1, 1]).toArray(); // [1, 1, 1, 1]
* new Color([1, 0, 0, 0.5]).toArray(); // [1, 0, 0, 0.5]
* new Color(new Float32Array([1, 0, 0, 0.5])).toArray(); // [1, 0, 0, 0.5]
* new Color(new Uint8Array([255, 0, 0, 255])).toArray(); // [1, 0, 0, 1]
* new Color(new Uint8ClampedArray([255, 0, 0, 255])).toArray(); // [1, 0, 0, 1]
* new Color({ h: 0, s: 100, l: 50, a: 0.5 }).toArray(); // [1, 0, 0, 0.5]
* new Color('hsl(0, 100%, 50%, 50%)').toArray(); // [1, 0, 0, 0.5]
* new Color({ h: 0, s: 100, v: 100, a: 0.5 }).toArray(); // [1, 0, 0, 0.5]
*
* // Convert between formats
* const color = new Color('red');
* color.toHex(); // "#ff0000"
* color.toRgbString(); // "rgb(255,0,0,1)"
* color.toNumber(); // 0xff0000
*
* // Access components
* color.red; // 1
* color.green; // 0
* color.blue; // 0
* color.alpha; // 1
*
* // Chain operations
* color
* .setAlpha(0.5)
* .multiply([0.5, 0.5, 0.5])
* .premultiply(0.8);
* ```
* @remarks
* The Color class automatically normalizes all color values internally:
* - RGB components are stored as floats between 0-1
* - Alpha is always between 0-1
* - Color operations clamp values to valid ranges
* - Original input format is preserved when possible
* @since 7.2.0
*/
export declare class Color {
/**
* Static shared Color instance used for utility operations. This is a singleton color object
* that can be reused to avoid creating unnecessary Color instances.
* > [!IMPORTANT] You should be careful when using this shared instance, as it is mutable and can be
* > changed by any code that uses it.
* >
* > It is best used for one-off color operations or temporary transformations.
* > For persistent colors, create your own Color instance instead.
* @example
* ```ts
* import { Color } from 'pixi.js';
*
* // Use shared instance for one-off color operations
* Color.shared.setValue(0xff0000);
* const redHex = Color.shared.toHex(); // "#ff0000"
* const redRgb = Color.shared.toRgbArray(); // [1, 0, 0]
*
* // Temporary color transformations
* const colorNumber = Color.shared
* .setValue('#ff0000') // Set to red
* .setAlpha(0.5) // Make semi-transparent
* .premultiply(0.8) // Apply premultiplication
* .toNumber(); // Convert to number
*
* // Chain multiple operations
* const result = Color.shared
* .setValue(someColor)
* .multiply(tintColor)
* .toPremultiplied(alpha);
* ```
* @remarks
* - This is a shared instance - be careful about multiple code paths using it simultaneously
* - Use for temporary color operations to avoid allocating new Color instances
* - The value is preserved between operations, so reset if needed
* - For persistent colors, create your own Color instance instead
*/
static readonly shared: Color;
/**
* @param {ColorSource} value - Optional value to use, if not provided, white is used.
*/
constructor(value?: ColorSource);
/**
* Get the red component of the color, normalized between 0 and 1.
* @example
* ```ts
* const color = new Color('red');
* console.log(color.red); // 1
*
* const green = new Color('#00ff00');
* console.log(green.red); // 0
* ```
*/
get red(): number;
/**
* Get the green component of the color, normalized between 0 and 1.
* @example
* ```ts
* const color = new Color('lime');
* console.log(color.green); // 1
*
* const red = new Color('#ff0000');
* console.log(red.green); // 0
* ```
*/
get green(): number;
/**
* Get the blue component of the color, normalized between 0 and 1.
* @example
* ```ts
* const color = new Color('blue');
* console.log(color.blue); // 1
*
* const yellow = new Color('#ffff00');
* console.log(yellow.blue); // 0
* ```
*/
get blue(): number;
/**
* Get the alpha component of the color, normalized between 0 and 1.
* @example
* ```ts
* const color = new Color('red');
* console.log(color.alpha); // 1 (fully opaque)
*
* const transparent = new Color('rgba(255, 0, 0, 0.5)');
* console.log(transparent.alpha); // 0.5 (semi-transparent)
* ```
*/
get alpha(): number;
/**
* Sets the color value and returns the instance for chaining.
*
* This is a chainable version of setting the `value` property.
* @param value - The color to set. Accepts various formats:
* - Hex strings/numbers (e.g., '#ff0000', 0xff0000)
* - RGB/RGBA values (arrays, objects)
* - CSS color names
* - HSL/HSLA values
* - HSV/HSVA values
* @returns The Color instance for chaining
* @example
* ```ts
* // Basic usage
* const color = new Color();
* color.setValue('#ff0000')
* .setAlpha(0.5)
* .premultiply(0.8);
*
* // Different formats
* color.setValue(0xff0000); // Hex number
* color.setValue('#ff0000'); // Hex string
* color.setValue([1, 0, 0]); // RGB array
* color.setValue([1, 0, 0, 0.5]); // RGBA array
* color.setValue({ r: 1, g: 0, b: 0 }); // RGB object
*
* // Copy from another color
* const red = new Color('red');
* color.setValue(red);
* ```
* @throws {Error} If the color value is invalid or null
*/
setValue(value: ColorSource): this;
/**
* The current color source. This property allows getting and setting the color value
* while preserving the original format where possible.
* @remarks
* When setting:
* - Setting to a `Color` instance copies its source and components
* - Setting to other valid sources normalizes and stores the value
* - Setting to `null` throws an Error
* - The color remains unchanged if normalization fails
*
* When getting:
* - Returns `null` if color was modified by {@link Color.multiply} or {@link Color.premultiply}
* - Otherwise returns the original color source
* @example
* ```ts
* // Setting different color formats
* const color = new Color();
*
* color.value = 0xff0000; // Hex number
* color.value = '#ff0000'; // Hex string
* color.value = [1, 0, 0]; // RGB array
* color.value = [1, 0, 0, 0.5]; // RGBA array
* color.value = { r: 1, g: 0, b: 0 }; // RGB object
*
* // Copying from another color
* const red = new Color('red');
* color.value = red; // Copies red's components
*
* // Getting the value
* console.log(color.value); // Returns original format
*
* // After modifications
* color.multiply([0.5, 0.5, 0.5]);
* console.log(color.value); // Returns null
* ```
* @throws {Error} When attempting to set `null`
*/
set value(value: ColorSource | null);
get value(): Exclude | null;
/**
* Convert to a RGBA color object with normalized components (0-1).
* @example
* ```ts
* import { Color } from 'pixi.js';
*
* // Convert colors to RGBA objects
* new Color('white').toRgba(); // returns { r: 1, g: 1, b: 1, a: 1 }
* new Color('#ff0000').toRgba(); // returns { r: 1, g: 0, b: 0, a: 1 }
*
* // With transparency
* new Color('rgba(255,0,0,0.5)').toRgba(); // returns { r: 1, g: 0, b: 0, a: 0.5 }
* ```
* @returns An RGBA object with normalized components
*/
toRgba(): RgbaColor;
/**
* Convert to a RGB color object with normalized components (0-1).
*
* Alpha component is omitted in the output.
* @example
* ```ts
* import { Color } from 'pixi.js';
*
* // Convert colors to RGB objects
* new Color('white').toRgb(); // returns { r: 1, g: 1, b: 1 }
* new Color('#ff0000').toRgb(); // returns { r: 1, g: 0, b: 0 }
*
* // Alpha is ignored
* new Color('rgba(255,0,0,0.5)').toRgb(); // returns { r: 1, g: 0, b: 0 }
* ```
* @returns An RGB object with normalized components
*/
toRgb(): RgbColor;
/**
* Convert to a CSS-style rgba string representation.
*
* RGB components are scaled to 0-255 range, alpha remains 0-1.
* @example
* ```ts
* import { Color } from 'pixi.js';
*
* // Convert colors to RGBA strings
* new Color('white').toRgbaString(); // returns "rgba(255,255,255,1)"
* new Color('#ff0000').toRgbaString(); // returns "rgba(255,0,0,1)"
*
* // With transparency
* new Color([1, 0, 0, 0.5]).toRgbaString(); // returns "rgba(255,0,0,0.5)"
* ```
* @returns A CSS-compatible rgba string
*/
toRgbaString(): string;
/**
* Convert to an [R, G, B] array of clamped uint8 values (0 to 255).
* @param {number[]|Uint8Array|Uint8ClampedArray} [out] - Optional output array. If not provided,
* a cached array will be used and returned.
* @returns Array containing RGB components as integers between 0-255
* @example
* ```ts
* // Basic usage
* new Color('white').toUint8RgbArray(); // returns [255, 255, 255]
* new Color('#ff0000').toUint8RgbArray(); // returns [255, 0, 0]
*
* // Using custom output array
* const rgb = new Uint8Array(3);
* new Color('blue').toUint8RgbArray(rgb); // rgb is now [0, 0, 255]
*
* // Using different array types
* new Color('red').toUint8RgbArray(new Uint8ClampedArray(3)); // [255, 0, 0]
* new Color('red').toUint8RgbArray([]); // [255, 0, 0]
* ```
* @remarks
* - Output values are always clamped between 0-255
* - Alpha component is not included in output
* - Reuses internal cache array if no output array provided
*/
toUint8RgbArray(out?: T): T;
/**
* Convert to an [R, G, B, A] array of normalized floats (numbers from 0.0 to 1.0).
* @param {number[]|Float32Array} [out] - Optional output array. If not provided,
* a cached array will be used and returned.
* @returns Array containing RGBA components as floats between 0-1
* @example
* ```ts
* // Basic usage
* new Color('white').toArray(); // returns [1, 1, 1, 1]
* new Color('red').toArray(); // returns [1, 0, 0, 1]
*
* // With alpha
* new Color('rgba(255,0,0,0.5)').toArray(); // returns [1, 0, 0, 0.5]
*
* // Using custom output array
* const rgba = new Float32Array(4);
* new Color('blue').toArray(rgba); // rgba is now [0, 0, 1, 1]
* ```
* @remarks
* - Output values are normalized between 0-1
* - Includes alpha component as the fourth value
* - Reuses internal cache array if no output array provided
*/
toArray(out?: T): T;
/**
* Convert to an [R, G, B] array of normalized floats (numbers from 0.0 to 1.0).
* @param {number[]|Float32Array} [out] - Optional output array. If not provided,
* a cached array will be used and returned.
* @returns Array containing RGB components as floats between 0-1
* @example
* ```ts
* // Basic usage
* new Color('white').toRgbArray(); // returns [1, 1, 1]
* new Color('red').toRgbArray(); // returns [1, 0, 0]
*
* // Using custom output array
* const rgb = new Float32Array(3);
* new Color('blue').toRgbArray(rgb); // rgb is now [0, 0, 1]
* ```
* @remarks
* - Output values are normalized between 0-1
* - Alpha component is omitted from output
* - Reuses internal cache array if no output array provided
*/
toRgbArray(out?: T): T;
/**
* Convert to a hexadecimal number.
* @returns The color as a 24-bit RGB integer
* @example
* ```ts
* // Basic usage
* new Color('white').toNumber(); // returns 0xffffff
* new Color('red').toNumber(); // returns 0xff0000
*
* // Store as hex
* const color = new Color('blue');
* const hex = color.toNumber(); // 0x0000ff
* ```
*/
toNumber(): number;
/**
* Convert to a BGR number.
*
* Useful for platforms that expect colors in BGR format.
* @returns The color as a 24-bit BGR integer
* @example
* ```ts
* // Convert RGB to BGR
* new Color(0xffcc99).toBgrNumber(); // returns 0x99ccff
*
* // Common use case: platform-specific color format
* const color = new Color('orange');
* const bgrColor = color.toBgrNumber(); // Color with swapped R/B channels
* ```
* @remarks
* This swaps the red and blue channels compared to the normal RGB format:
* - RGB 0xRRGGBB becomes BGR 0xBBGGRR
*/
toBgrNumber(): number;
/**
* Convert to a hexadecimal number in little endian format (e.g., BBGGRR).
*
* Useful for platforms that expect colors in little endian byte order.
* @example
* ```ts
* import { Color } from 'pixi.js';
*
* // Convert RGB color to little endian format
* new Color(0xffcc99).toLittleEndianNumber(); // returns 0x99ccff
*
* // Common use cases:
* const color = new Color('orange');
* const leColor = color.toLittleEndianNumber(); // Swaps byte order for LE systems
*
* // Multiple conversions
* const colors = {
* normal: 0xffcc99,
* littleEndian: new Color(0xffcc99).toLittleEndianNumber(), // 0x99ccff
* backToNormal: new Color(0x99ccff).toLittleEndianNumber() // 0xffcc99
* };
* ```
* @remarks
* - Swaps R and B channels in the color value
* - RGB 0xRRGGBB becomes 0xBBGGRR
* - Useful for systems that use little endian byte order
* - Can be used to convert back and forth between formats
* @returns The color as a number in little endian format (BBGGRR)
*/
toLittleEndianNumber(): number;
/**
* Multiply with another color.
*
* This action is destructive and modifies the original color.
* @param {ColorSource} value - The color to multiply by. Accepts any valid color format:
* - Hex strings/numbers (e.g., '#ff0000', 0xff0000)
* - RGB/RGBA arrays ([1, 0, 0], [1, 0, 0, 1])
* - Color objects ({ r: 1, g: 0, b: 0 })
* - CSS color names ('red', 'blue')
* @returns this - The Color instance for chaining
* @example
* ```ts
* // Basic multiplication
* const color = new Color('#ff0000');
* color.multiply(0x808080); // 50% darker red
*
* // With transparency
* color.multiply([1, 1, 1, 0.5]); // 50% transparent
*
* // Chain operations
* color
* .multiply('#808080')
* .multiply({ r: 1, g: 1, b: 1, a: 0.5 });
* ```
* @remarks
* - Multiplies each RGB component and alpha separately
* - Values are clamped between 0-1
* - Original color format is lost (value becomes null)
* - Operation cannot be undone
*/
multiply(value: ColorSource): this;
/**
* Converts color to a premultiplied alpha format.
*
* This action is destructive and modifies the original color.
* @param alpha - The alpha value to multiply by (0-1)
* @param {boolean} [applyToRGB=true] - Whether to premultiply RGB channels
* @returns {Color} The Color instance for chaining
* @example
* ```ts
* // Basic premultiplication
* const color = new Color('red');
* color.premultiply(0.5); // 50% transparent red with premultiplied RGB
*
* // Alpha only (RGB unchanged)
* color.premultiply(0.5, false); // 50% transparent, original RGB
*
* // Chain with other operations
* color
* .multiply(0x808080)
* .premultiply(0.5)
* .toNumber();
* ```
* @remarks
* - RGB channels are multiplied by alpha when applyToRGB is true
* - Alpha is always set to the provided value
* - Values are clamped between 0-1
* - Original color format is lost (value becomes null)
* - Operation cannot be undone
*/
premultiply(alpha: number, applyToRGB?: boolean): this;
/**
* Returns the color as a 32-bit premultiplied alpha integer.
*
* Format: 0xAARRGGBB
* @param {number} alpha - The alpha value to multiply by (0-1)
* @param {boolean} [applyToRGB=true] - Whether to premultiply RGB channels
* @returns {number} The premultiplied color as a 32-bit integer
* @example
* ```ts
* // Convert to premultiplied format
* const color = new Color('red');
*
* // Full opacity (0xFFRRGGBB)
* color.toPremultiplied(1.0); // 0xFFFF0000
*
* // 50% transparency with premultiplied RGB
* color.toPremultiplied(0.5); // 0x7F7F0000
*
* // 50% transparency without RGB premultiplication
* color.toPremultiplied(0.5, false); // 0x7FFF0000
* ```
* @remarks
* - Returns full opacity (0xFF000000) when alpha is 1.0
* - Returns 0 when alpha is 0.0 and applyToRGB is true
* - RGB values are rounded during premultiplication
*/
toPremultiplied(alpha: number, applyToRGB?: boolean): number;
/**
* Convert to a hexadecimal string (6 characters).
* @returns A CSS-compatible hex color string (e.g., "#ff0000")
* @example
* ```ts
* import { Color } from 'pixi.js';
*
* // Basic colors
* new Color('red').toHex(); // returns "#ff0000"
* new Color('white').toHex(); // returns "#ffffff"
* new Color('black').toHex(); // returns "#000000"
*
* // From different formats
* new Color(0xff0000).toHex(); // returns "#ff0000"
* new Color([1, 0, 0]).toHex(); // returns "#ff0000"
* new Color({ r: 1, g: 0, b: 0 }).toHex(); // returns "#ff0000"
* ```
* @remarks
* - Always returns a 6-character hex string
* - Includes leading "#" character
* - Alpha channel is ignored
* - Values are rounded to nearest hex value
*/
toHex(): string;
/**
* Convert to a hexadecimal string with alpha (8 characters).
* @returns A CSS-compatible hex color string with alpha (e.g., "#ff0000ff")
* @example
* ```ts
* import { Color } from 'pixi.js';
*
* // Fully opaque colors
* new Color('red').toHexa(); // returns "#ff0000ff"
* new Color('white').toHexa(); // returns "#ffffffff"
*
* // With transparency
* new Color('rgba(255, 0, 0, 0.5)').toHexa(); // returns "#ff00007f"
* new Color([1, 0, 0, 0]).toHexa(); // returns "#ff000000"
* ```
* @remarks
* - Returns an 8-character hex string
* - Includes leading "#" character
* - Alpha is encoded in last two characters
* - Values are rounded to nearest hex value
*/
toHexa(): string;
/**
* Set alpha (transparency) value while preserving color components.
*
* Provides a chainable interface for setting alpha.
* @param alpha - Alpha value between 0 (fully transparent) and 1 (fully opaque)
* @returns The Color instance for chaining
* @example
* ```ts
* // Basic alpha setting
* const color = new Color('red');
* color.setAlpha(0.5); // 50% transparent red
*
* // Chain with other operations
* color
* .setValue('#ff0000')
* .setAlpha(0.8) // 80% opaque
* .premultiply(0.5); // Further modify alpha
*
* // Reset to fully opaque
* color.setAlpha(1);
* ```
* @remarks
* - Alpha value is clamped between 0-1
* - Can be chained with other color operations
*/
setAlpha(alpha: number): this;
/**
* Check if a value can be interpreted as a valid color format.
* Supports all color formats that can be used with the Color class.
* @param value - Value to check
* @returns True if the value can be used as a color
* @example
* ```ts
* import { Color } from 'pixi.js';
*
* // CSS colors and hex values
* Color.isColorLike('red'); // true
* Color.isColorLike('#ff0000'); // true
* Color.isColorLike(0xff0000); // true
*
* // Arrays (RGB/RGBA)
* Color.isColorLike([1, 0, 0]); // true
* Color.isColorLike([1, 0, 0, 0.5]); // true
*
* // TypedArrays
* Color.isColorLike(new Float32Array([1, 0, 0])); // true
* Color.isColorLike(new Uint8Array([255, 0, 0])); // true
* Color.isColorLike(new Uint8ClampedArray([255, 0, 0])); // true
*
* // Object formats
* Color.isColorLike({ r: 1, g: 0, b: 0 }); // true (RGB)
* Color.isColorLike({ r: 1, g: 0, b: 0, a: 0.5 }); // true (RGBA)
* Color.isColorLike({ h: 0, s: 100, l: 50 }); // true (HSL)
* Color.isColorLike({ h: 0, s: 100, l: 50, a: 0.5 }); // true (HSLA)
* Color.isColorLike({ h: 0, s: 100, v: 100 }); // true (HSV)
* Color.isColorLike({ h: 0, s: 100, v: 100, a: 0.5 });// true (HSVA)
*
* // Color instances
* Color.isColorLike(new Color('red')); // true
*
* // Invalid values
* Color.isColorLike(null); // false
* Color.isColorLike(undefined); // false
* Color.isColorLike({}); // false
* Color.isColorLike([]); // false
* Color.isColorLike('not-a-color'); // false
* ```
* @remarks
* Checks for the following formats:
* - Numbers (0x000000 to 0xffffff)
* - CSS color strings
* - RGB/RGBA arrays and objects
* - HSL/HSLA objects
* - HSV/HSVA objects
* - TypedArrays (Float32Array, Uint8Array, Uint8ClampedArray)
* - Color instances
*/
static isColorLike(value: unknown): value is ColorSource;
}
/**
* Common interface for points. Both Point and ObservablePoint implement it.
* Provides a standard way to represent 2D coordinates.
*
* Many PixiJS methods accept PointData for transformations,
* making it easy to work with different point types interchangeably.
* @example
* ```ts
* // Create an object implementing PointData
* const point: PointData = { x: 100, y: 200 };
*
* // Use with matrix transformations
* const matrix = new Matrix();
* matrix.translate(50, 50).apply(point);
*
* // Mix with other point types
* const observablePoint = new ObservablePoint(() => {}, null, 0, 0);
* const regularPoint = new Point(0, 0);
* // All are PointData compatible
* ```
* @remarks
* - Basic x,y coordinate interface
* - Used by Point and ObservablePoint
*/
export interface PointData {
/** X coordinate */
x: number;
/** Y coordinate */
y: number;
}
/**
* Common interface for points with manipulation methods.
*
* Extends PointData to add operations for copying, comparison and setting values.
* @example
* ```ts
* // Basic point manipulation
* const point: PointLike = new Point(10, 20);
* point.set(30, 40);
*
* // Copy between points
* const other = new Point();
* point.copyTo(other);
*
* // Compare points
* const same = point.equals(other); // true
* ```
*/
export interface PointLike extends PointData {
/**
* Copies x and y from the given point
* @param {PointData} p - The point to copy from
* @returns {this} Returns itself.
* @example
* ```ts
* const point1: PointLike = new Point(10, 20);
* const point2: PointLike = new Point(30, 40);
* point1.copyFrom(point2);
* console.log(point1.x, point1.y); // 30, 40
* ```
*/
copyFrom: (p: PointData) => this;
/**
* Copies x and y into the given point
* @param {PointLike} p - The point to copy.
* @returns {PointLike} Given point with values updated
* @example
* ```ts
* const point1: PointLike = new Point(10, 20);
* const point2: PointLike = new Point(0, 0);
* point1.copyTo(point2);
* console.log(point2.x, point2.y); // 10, 20
* ```
*/
copyTo: (p: T) => T;
/**
* Returns true if the given point is equal to this point
* @param {PointData} p - The point to check
* @returns {boolean} Whether the given point equal to this point
* @example
* ```ts
* const point1: PointLike = new Point(10, 20);
* const point2: PointLike = new Point(10, 20);
* const point3: PointLike = new Point(30, 40);
* console.log(point1.equals(point2)); // true
* console.log(point1.equals(point3)); // false
* ```
*/
equals: (p: PointData) => boolean;
/**
* Sets the point to a new x and y position.
* If y is omitted, both x and y will be set to x.
* @param {number} [x=0] - position of the point on the x axis
* @param {number} [y=x] - position of the point on the y axis
* @example
* ```ts
* const point: PointLike = new Point(10, 20);
* point.set(30, 40);
* console.log(point.x, point.y); // 30, 40
* point.set(50); // Sets both x and y to 50
* console.log(point.x, point.y); // 50, 50
* ```
*/
set: (x?: number, y?: number) => void;
}
export interface Point extends PixiMixins.Point {
}
/**
* The Point object represents a location in a two-dimensional coordinate system, where `x` represents
* the position on the horizontal axis and `y` represents the position on the vertical axis.
*
* Many Pixi functions accept the `PointData` type as an alternative to `Point`,
* which only requires `x` and `y` properties.
* @example
* ```ts
* // Basic point creation
* const point = new Point(100, 200);
*
* // Using with transformations
* const matrix = new Matrix();
* matrix.translate(50, 50).apply(point);
*
* // Point arithmetic
* const start = new Point(0, 0);
* const end = new Point(100, 100);
* const middle = new Point(
* (start.x + end.x) / 2,
* (start.y + end.y) / 2
* );
* ```
*/
export declare class Point implements PointLike {
/**
* Position of the point on the x axis
* @example
* ```ts
* // Set x position
* const point = new Point();
* point.x = 100;
*
* // Use in calculations
* const width = rightPoint.x - leftPoint.x;
* ```
*/
x: number;
/**
* Position of the point on the y axis
* @example
* ```ts
* // Set y position
* const point = new Point();
* point.y = 200;
*
* // Use in calculations
* const height = bottomPoint.y - topPoint.y;
* ```
*/
y: number;
/**
* Creates a new `Point`
* @param {number} [x=0] - position of the point on the x axis
* @param {number} [y=0] - position of the point on the y axis
*/
constructor(x?: number, y?: number);
/**
* Creates a clone of this point, which is a new instance with the same `x` and `y` values.
* @example
* ```ts
* // Basic point cloning
* const original = new Point(100, 200);
* const copy = original.clone();
*
* // Clone and modify
* const modified = original.clone();
* modified.set(300, 400);
*
* // Verify independence
* console.log(original); // Point(100, 200)
* console.log(modified); // Point(300, 400)
* ```
* @remarks
* - Creates new Point instance
* - Deep copies x and y values
* - Independent from original
* - Useful for preserving values
* @returns A clone of this point
*/
clone(): Point;
/**
* Copies x and y from the given point into this point.
* @example
* ```ts
* // Basic copying
* const source = new Point(100, 200);
* const target = new Point();
* target.copyFrom(source);
*
* // Copy and chain operations
* const point = new Point()
* .copyFrom(source)
* .set(x + 50, y + 50);
*
* // Copy from any PointData
* const data = { x: 10, y: 20 };
* point.copyFrom(data);
* ```
* @param p - The point to copy from
* @returns The point instance itself
*/
copyFrom(p: PointData): this;
/**
* Copies this point's x and y into the given point.
* @example
* ```ts
* // Basic copying
* const source = new Point(100, 200);
* const target = new Point();
* source.copyTo(target);
* ```
* @param p - The point to copy to. Can be any type that is or extends `PointLike`
* @returns The point (`p`) with values updated
*/
copyTo(p: T): T;
/**
* Checks if another point is equal to this point.
*
* Compares x and y values using strict equality.
* @example
* ```ts
* // Basic equality check
* const p1 = new Point(100, 200);
* const p2 = new Point(100, 200);
* console.log(p1.equals(p2)); // true
*
* // Compare with PointData
* const data = { x: 100, y: 200 };
* console.log(p1.equals(data)); // true
*
* // Check different points
* const p3 = new Point(200, 300);
* console.log(p1.equals(p3)); // false
* ```
* @param p - The point to check
* @returns `true` if both `x` and `y` are equal
*/
equals(p: PointData): boolean;
/**
* Sets the point to a new x and y position.
*
* If y is omitted, both x and y will be set to x.
* @example
* ```ts
* // Basic position setting
* const point = new Point();
* point.set(100, 200);
*
* // Set both x and y to same value
* point.set(50); // x=50, y=50
*
* // Chain with other operations
* point
* .set(10, 20)
* .copyTo(otherPoint);
* ```
* @param x - Position on the x axis
* @param y - Position on the y axis, defaults to x
* @returns The point instance itself
*/
set(x?: number, y?: number): this;
toString(): string;
/**
* A static Point object with `x` and `y` values of `0`.
*
* This shared instance is reset to zero values when accessed.
*
* > [!IMPORTANT] This point is shared and temporary. Do not store references to it.
* @example
* ```ts
* // Use for temporary calculations
* const tempPoint = Point.shared;
* tempPoint.set(100, 200);
* matrix.apply(tempPoint);
*
* // Will be reset to (0,0) on next access
* const fresh = Point.shared; // x=0, y=0
* ```
* @returns A fresh zeroed point for temporary use
*/
static get shared(): Point;
}
/**
* A fast matrix for 2D transformations.
* Represents a 3x3 transformation matrix:
*
* ```js
* | a c tx |
* | b d ty |
* | 0 0 1 |
* ```
* @example
* ```ts
* // Create identity matrix
* const matrix = new Matrix();
*
* // Create matrix with custom values
* const transform = new Matrix(2, 0, 0, 2, 100, 100); // Scale 2x, translate 100,100
*
* // Transform a point
* const point = { x: 10, y: 20 };
* const transformed = transform.apply(point);
*
* // Chain transformations
* matrix
* .translate(100, 50)
* .rotate(Math.PI / 4)
* .scale(2, 2);
* ```
* @remarks
* - Used for transform hierarchies
* - Supports scale, rotation, position
* - Can be concatenated with append/prepend
* - Efficient for batched transformations
*/
export declare class Matrix {
/**
* Scale on the x axis.
* @default 1
*/
a: number;
/**
* Shear on the y axis.
* @default 0
*/
b: number;
/**
* Shear on the x axis.
* @default 0
*/
c: number;
/**
* Scale on the y axis.
* @default 1
*/
d: number;
/**
* Translation on the x axis.
* @default 0
*/
tx: number;
/**
* Translation on the y axis.
* @default 0
*/
ty: number;
/**
* Array representation of the matrix.
* Only populated when `toArray()` is called.
* @default null
*/
array: Float32Array | null;
/**
* @param a - x scale
* @param b - y skew
* @param c - x skew
* @param d - y scale
* @param tx - x translation
* @param ty - y translation
*/
constructor(a?: number, b?: number, c?: number, d?: number, tx?: number, ty?: number);
/**
* Creates a Matrix object based on the given array.
* Populates matrix components from a flat array in column-major order.
*
* > [!NOTE] Array mapping order:
* > ```
* > array[0] = a (x scale)
* > array[1] = b (y skew)
* > array[2] = tx (x translation)
* > array[3] = c (x skew)
* > array[4] = d (y scale)
* > array[5] = ty (y translation)
* > ```
* @example
* ```ts
* // Create matrix from array
* const matrix = new Matrix();
* matrix.fromArray([
* 2, 0, 100, // a, b, tx
* 0, 2, 100 // c, d, ty
* ]);
*
* // Create matrix from typed array
* const float32Array = new Float32Array([
* 1, 0, 0, // Scale x1, no skew
* 0, 1, 0 // No skew, scale x1
* ]);
* matrix.fromArray(float32Array);
* ```
* @param array - The array to populate the matrix from
*/
fromArray(array: number[]): void;
/**
* Sets the matrix properties directly.
* All matrix components can be set in one call.
* @example
* ```ts
* // Set to identity matrix
* matrix.set(1, 0, 0, 1, 0, 0);
*
* // Set to scale matrix
* matrix.set(2, 0, 0, 2, 0, 0); // Scale 2x
*
* // Set to translation matrix
* matrix.set(1, 0, 0, 1, 100, 50); // Move 100,50
* ```
* @param a - Scale on x axis
* @param b - Shear on y axis
* @param c - Shear on x axis
* @param d - Scale on y axis
* @param tx - Translation on x axis
* @param ty - Translation on y axis
* @returns This matrix. Good for chaining method calls.
*/
set(a: number, b: number, c: number, d: number, tx: number, ty: number): this;
/**
* Creates an array from the current Matrix object.
*
* > [!NOTE] The array format is:
* > ```
* > Non-transposed:
* > [a, c, tx,
* > b, d, ty,
* > 0, 0, 1]
* >
* > Transposed:
* > [a, b, 0,
* > c, d, 0,
* > tx,ty,1]
* > ```
* @example
* ```ts
* // Basic array conversion
* const matrix = new Matrix(2, 0, 0, 2, 100, 100);
* const array = matrix.toArray();
*
* // Using existing array
* const float32Array = new Float32Array(9);
* matrix.toArray(false, float32Array);
*
* // Get transposed array
* const transposed = matrix.toArray(true);
* ```
* @param transpose - Whether to transpose the matrix
* @param out - Optional Float32Array to store the result
* @returns The array containing the matrix values
*/
toArray(transpose?: boolean, out?: Float32Array): Float32Array;
/**
* Get a new position with the current transformation applied.
*
* Can be used to go from a child's coordinate space to the world coordinate space. (e.g. rendering)
* @example
* ```ts
* // Basic point transformation
* const matrix = new Matrix().translate(100, 50).rotate(Math.PI / 4);
* const point = new Point(10, 20);
* const transformed = matrix.apply(point);
*
* // Reuse existing point
* const output = new Point();
* matrix.apply(point, output);
* ```
* @param pos - The origin point to transform
* @param newPos - Optional point to store the result
* @returns The transformed point
*/
apply
(pos: PointData, newPos?: P): P;
/**
* Get a new position with the inverse of the current transformation applied.
*
* Can be used to go from the world coordinate space to a child's coordinate space. (e.g. input)
* @example
* ```ts
* // Basic inverse transformation
* const matrix = new Matrix().translate(100, 50).rotate(Math.PI / 4);
* const worldPoint = new Point(150, 100);
* const localPoint = matrix.applyInverse(worldPoint);
*
* // Reuse existing point
* const output = new Point();
* matrix.applyInverse(worldPoint, output);
*
* // Convert mouse position to local space
* const mousePoint = new Point(mouseX, mouseY);
* const localMouse = matrix.applyInverse(mousePoint);
* ```
* @param pos - The origin point to inverse-transform
* @param newPos - Optional point to store the result
* @returns The inverse-transformed point
*/
applyInverse
(pos: PointData, newPos?: P): P;
/**
* Translates the matrix on the x and y axes.
* Adds to the position values while preserving scale, rotation and skew.
* @example
* ```ts
* // Basic translation
* const matrix = new Matrix();
* matrix.translate(100, 50); // Move right 100, down 50
*
* // Chain with other transformations
* matrix
* .scale(2, 2)
* .translate(100, 0)
* .rotate(Math.PI / 4);
* ```
* @param x - How much to translate on the x axis
* @param y - How much to translate on the y axis
* @returns This matrix. Good for chaining method calls.
*/
translate(x: number, y: number): this;
/**
* Applies a scale transformation to the matrix.
* Multiplies the scale values with existing matrix components.
* @example
* ```ts
* // Basic scaling
* const matrix = new Matrix();
* matrix.scale(2, 3); // Scale 2x horizontally, 3x vertically
*
* // Chain with other transformations
* matrix
* .translate(100, 100)
* .scale(2, 2) // Scales after translation
* .rotate(Math.PI / 4);
* ```
* @param x - The amount to scale horizontally
* @param y - The amount to scale vertically
* @returns This matrix. Good for chaining method calls.
*/
scale(x: number, y: number): this;
/**
* Applies a rotation transformation to the matrix.
*
* Rotates around the origin (0,0) by the given angle in radians.
* @example
* ```ts
* // Basic rotation
* const matrix = new Matrix();
* matrix.rotate(Math.PI / 4); // Rotate 45 degrees
*
* // Chain with other transformations
* matrix
* .translate(100, 100) // Move to rotation center
* .rotate(Math.PI) // Rotate 180 degrees
* .scale(2, 2); // Scale after rotation
*
* // Common angles
* matrix.rotate(Math.PI / 2); // 90 degrees
* matrix.rotate(Math.PI); // 180 degrees
* matrix.rotate(Math.PI * 2); // 360 degrees
* ```
* @remarks
* - Rotates around origin point (0,0)
* - Affects position if translation was set
* - Uses counter-clockwise rotation
* - Order of operations matters when chaining
* @param angle - The angle in radians
* @returns This matrix. Good for chaining method calls.
*/
rotate(angle: number): this;
/**
* Appends the given Matrix to this Matrix.
* Combines two matrices by multiplying them together: this = this * matrix
* @example
* ```ts
* // Basic matrix combination
* const matrix = new Matrix();
* const other = new Matrix().translate(100, 0).rotate(Math.PI / 4);
* matrix.append(other);
* ```
* @remarks
* - Order matters: A.append(B) !== B.append(A)
* - Modifies current matrix
* - Preserves transformation order
* - Commonly used for combining transforms
* @param matrix - The matrix to append
* @returns This matrix. Good for chaining method calls.
*/
append(matrix: Matrix): this;
/**
* Appends two matrices and sets the result to this matrix.
* Performs matrix multiplication: this = A * B
* @example
* ```ts
* // Basic matrix multiplication
* const result = new Matrix();
* const matrixA = new Matrix().scale(2, 2);
* const matrixB = new Matrix().rotate(Math.PI / 4);
* result.appendFrom(matrixA, matrixB);
* ```
* @remarks
* - Order matters: A * B !== B * A
* - Creates a new transformation from two others
* - More efficient than append() for multiple operations
* - Does not modify input matrices
* @param a - The first matrix to multiply
* @param b - The second matrix to multiply
* @returns This matrix. Good for chaining method calls.
*/
appendFrom(a: Matrix, b: Matrix): this;
/**
* Sets the matrix based on all the available properties.
* Combines position, scale, rotation, skew and pivot in a single operation.
* @example
* ```ts
* // Basic transform setup
* const matrix = new Matrix();
* matrix.setTransform(
* 100, 100, // position
* 0, 0, // pivot
* 2, 2, // scale
* Math.PI / 4, // rotation (45 degrees)
* 0, 0 // skew
* );
* ```
* @remarks
* - Updates all matrix components at once
* - More efficient than separate transform calls
* - Uses radians for rotation and skew
* - Pivot affects rotation center
* @param x - Position on the x axis
* @param y - Position on the y axis
* @param pivotX - Pivot on the x axis
* @param pivotY - Pivot on the y axis
* @param scaleX - Scale on the x axis
* @param scaleY - Scale on the y axis
* @param rotation - Rotation in radians
* @param skewX - Skew on the x axis
* @param skewY - Skew on the y axis
* @returns This matrix. Good for chaining method calls.
*/
setTransform(x: number, y: number, pivotX: number, pivotY: number, scaleX: number, scaleY: number, rotation: number, skewX: number, skewY: number): this;
/**
* Prepends the given Matrix to this Matrix.
* Combines two matrices by multiplying them together: this = matrix * this
* @example
* ```ts
* // Basic matrix prepend
* const matrix = new Matrix().scale(2, 2);
* const other = new Matrix().translate(100, 0);
* matrix.prepend(other); // Translation happens before scaling
* ```
* @remarks
* - Order matters: A.prepend(B) !== B.prepend(A)
* - Modifies current matrix
* - Reverses transformation order compared to append()
* @param matrix - The matrix to prepend
* @returns This matrix. Good for chaining method calls.
*/
prepend(matrix: Matrix): this;
/**
* Decomposes the matrix into its individual transform components.
* Extracts position, scale, rotation and skew values from the matrix.
* @example
* ```ts
* // Basic decomposition
* const matrix = new Matrix()
* .translate(100, 100)
* .rotate(Math.PI / 4)
* .scale(2, 2);
*
* const transform = {
* position: new Point(),
* scale: new Point(),
* pivot: new Point(),
* skew: new Point(),
* rotation: 0
* };
*
* matrix.decompose(transform);
* console.log(transform.position); // Point(100, 100)
* console.log(transform.rotation); // ~0.785 (PI/4)
* console.log(transform.scale); // Point(2, 2)
* ```
* @remarks
* - Handles combined transformations
* - Accounts for pivot points
* - Chooses between rotation/skew based on transform type
* - Uses radians for rotation and skew
* @param transform - The transform object to store the decomposed values
* @returns The transform with the newly applied properties
*/
decompose(transform: TransformableObject): TransformableObject;
/**
* Inverts this matrix.
* Creates the matrix that when multiplied with this matrix results in an identity matrix.
* @example
* ```ts
* // Basic matrix inversion
* const matrix = new Matrix()
* .translate(100, 50)
* .scale(2, 2);
*
* matrix.invert(); // Now transforms in opposite direction
*
* // Verify inversion
* const point = new Point(50, 50);
* const transformed = matrix.apply(point);
* const original = matrix.invert().apply(transformed);
* // original ≈ point
* ```
* @remarks
* - Modifies the current matrix
* - Useful for reversing transformations
* - Cannot invert matrices with zero determinant
* @returns This matrix. Good for chaining method calls.
*/
invert(): this;
/**
* Checks if this matrix is an identity matrix.
*
* An identity matrix has no transformations applied (default state).
* @example
* ```ts
* // Check if matrix is identity
* const matrix = new Matrix();
* console.log(matrix.isIdentity()); // true
*
* // Check after transformations
* matrix.translate(100, 0);
* console.log(matrix.isIdentity()); // false
*
* // Reset and verify
* matrix.identity();
* console.log(matrix.isIdentity()); // true
* ```
* @remarks
* - Verifies a = 1, d = 1 (no scale)
* - Verifies b = 0, c = 0 (no skew)
* - Verifies tx = 0, ty = 0 (no translation)
* @returns True if matrix has no transformations
*/
isIdentity(): boolean;
/**
* Resets this Matrix to an identity (default) matrix.
* Sets all components to their default values: scale=1, no skew, no translation.
* @example
* ```ts
* // Reset transformed matrix
* const matrix = new Matrix()
* .scale(2, 2)
* .rotate(Math.PI / 4);
* matrix.identity(); // Back to default state
*
* // Chain after reset
* matrix
* .identity()
* .translate(100, 100)
* .scale(2, 2);
*
* // Compare with identity constant
* const isDefault = matrix.equals(Matrix.IDENTITY);
* ```
* @remarks
* - Sets a=1, d=1 (default scale)
* - Sets b=0, c=0 (no skew)
* - Sets tx=0, ty=0 (no translation)
* @returns This matrix. Good for chaining method calls.
*/
identity(): this;
/**
* Creates a new Matrix object with the same values as this one.
* @returns A copy of this matrix. Good for chaining method calls.
*/
clone(): Matrix;
/**
* Creates a new Matrix object with the same values as this one.
* @param matrix
* @example
* ```ts
* // Basic matrix cloning
* const matrix = new Matrix()
* .translate(100, 100)
* .rotate(Math.PI / 4);
* const copy = matrix.clone();
*
* // Clone and modify
* const modified = matrix.clone()
* .scale(2, 2);
*
* // Compare matrices
* console.log(matrix.equals(copy)); // true
* console.log(matrix.equals(modified)); // false
* ```
* @returns A copy of this matrix. Good for chaining method calls.
*/
copyTo(matrix: Matrix): Matrix;
/**
* Changes the values of the matrix to be the same as the ones in given matrix.
* @example
* ```ts
* // Basic matrix copying
* const source = new Matrix()
* .translate(100, 100)
* .rotate(Math.PI / 4);
* const target = new Matrix();
* target.copyFrom(source);
* ```
* @param matrix - The matrix to copy from
* @returns This matrix. Good for chaining method calls.
*/
copyFrom(matrix: Matrix): this;
/**
* Checks if this matrix equals another matrix.
* Compares all components for exact equality.
* @example
* ```ts
* // Basic equality check
* const m1 = new Matrix();
* const m2 = new Matrix();
* console.log(m1.equals(m2)); // true
*
* // Compare transformed matrices
* const transform = new Matrix()
* .translate(100, 100)
* const clone = new Matrix()
* .scale(2, 2);
* console.log(transform.equals(clone)); // false
* ```
* @param matrix - The matrix to compare to
* @returns True if matrices are identical
*/
equals(matrix: Matrix): boolean;
toString(): string;
/**
* A default (identity) matrix with no transformations applied.
*
* > [!IMPORTANT] This is a shared read-only object. Create a new Matrix if you need to modify it.
* @example
* ```ts
* // Get identity matrix reference
* const identity = Matrix.IDENTITY;
* console.log(identity.isIdentity()); // true
*
* // Compare with identity
* const matrix = new Matrix();
* console.log(matrix.equals(Matrix.IDENTITY)); // true
*
* // Create new matrix instead of modifying IDENTITY
* const transform = new Matrix()
* .copyFrom(Matrix.IDENTITY)
* .translate(100, 100);
* ```
* @returns A read-only identity matrix
*/
static get IDENTITY(): Readonly;
/**
* A static Matrix that can be used to avoid creating new objects.
* Will always ensure the matrix is reset to identity when requested.
*
* > [!IMPORTANT] This matrix is shared and temporary. Do not store references to it.
* @example
* ```ts
* // Use for temporary calculations
* const tempMatrix = Matrix.shared;
* tempMatrix.translate(100, 100).rotate(Math.PI / 4);
* const point = tempMatrix.apply({ x: 10, y: 20 });
*
* // Will be reset to identity on next access
* const fresh = Matrix.shared; // Back to identity
* ```
* @remarks
* - Always returns identity matrix
* - Safe to modify temporarily
* - Not safe to store references
* - Useful for one-off calculations
* @returns A fresh identity matrix for temporary use
*/
static get shared(): Matrix;
}
export interface ObservablePoint extends PixiMixins.ObservablePoint {
}
/**
* Observer used to listen for observable point changes.
* Provides callback mechanism for point value updates.
* @example
* ```ts
* // Basic observer implementation
* const observer: Observer = {
* _onUpdate: (point) => {
* console.log(`Point updated to (${point.x}, ${point.y})`);
* }
* };
*
* // Create observable point with observer
* const point = new ObservablePoint(observer, 100, 100);
*
* // Observer will be notified on changes
* point.x = 200; // Logs: Point updated to (200, 100)
* ```
* @remarks
* - Used internally by ObservablePoint
* - Triggered on x/y changes
* - Can track multiple points
* - Useful for change detection
* @typeParam T - The type of point being observed
*/
export interface Observer {
/**
* Callback to call when the point has updated.
* Triggered whenever x or y coordinates change.
* @param point - The point that was updated
*/
_onUpdate: (point?: T) => void;
}
/**
* The ObservablePoint object represents a location in a two-dimensional coordinate system.
* Triggers a callback when its position changes.
*
* The x and y properties represent the position on the horizontal and vertical axes, respectively.
* @example
* ```ts
* // Basic observable point usage
* const point = new ObservablePoint(
* { _onUpdate: (p) => console.log(`Updated to (${p.x}, ${p.y})`) },
* 100, 100
* );
*
* // Update triggers callback
* point.x = 200; // Logs: Updated to (200, 100)
* point.y = 300; // Logs: Updated to (200, 300)
*
* // Set both coordinates
* point.set(50, 50); // Logs: Updated to (50, 50)
* ```
*/
export declare class ObservablePoint implements PointLike {
/**
* Creates a new `ObservablePoint`
* @param observer - Observer to pass to listen for change events.
* @param {number} [x=0] - position of the point on the x axis
* @param {number} [y=0] - position of the point on the y axis
*/
constructor(observer: Observer, x?: number, y?: number);
/**
* Creates a clone of this point.
* @example
* ```ts
* // Basic cloning
* const point = new ObservablePoint(observer, 100, 200);
* const copy = point.clone();
*
* // Clone with new observer
* const newObserver = {
* _onUpdate: (p) => console.log(`Clone updated: (${p.x}, ${p.y})`)
* };
* const watched = point.clone(newObserver);
*
* // Verify independence
* watched.set(300, 400); // Only triggers new observer
* ```
* @param observer - Optional observer to pass to the new observable point
* @returns A copy of this observable point
*/
clone(observer?: Observer): ObservablePoint;
/**
* Sets the point to a new x and y position.
*
* If y is omitted, both x and y will be set to x.
* @example
* ```ts
* // Basic position setting
* const point = new ObservablePoint(observer);
* point.set(100, 200);
*
* // Set both x and y to same value
* point.set(50); // x=50, y=50
* ```
* @param x - Position on the x axis
* @param y - Position on the y axis, defaults to x
* @returns The point instance itself
*/
set(x?: number, y?: number): this;
/**
* Copies x and y from the given point into this point.
* @example
* ```ts
* // Basic copying
* const source = new ObservablePoint(observer, 100, 200);
* const target = new ObservablePoint();
* target.copyFrom(source);
*
* // Copy and chain operations
* const point = new ObservablePoint()
* .copyFrom(source)
* .set(x + 50, y + 50);
*
* // Copy from any PointData
* const data = { x: 10, y: 20 };
* point.copyFrom(data);
* ```
* @param p - The point to copy from
* @returns The point instance itself
*/
copyFrom(p: PointData): this;
/**
* Copies this point's x and y into the given point.
* @example
* ```ts
* // Basic copying
* const source = new ObservablePoint(100, 200);
* const target = new ObservablePoint();
* source.copyTo(target);
* ```
* @param p - The point to copy to. Can be any type that is or extends `PointLike`
* @returns The point (`p`) with values updated
*/
copyTo(p: T): T;
/**
* Checks if another point is equal to this point.
*
* Compares x and y values using strict equality.
* @example
* ```ts
* // Basic equality check
* const p1 = new ObservablePoint(100, 200);
* const p2 = new ObservablePoint(100, 200);
* console.log(p1.equals(p2)); // true
*
* // Compare with PointData
* const data = { x: 100, y: 200 };
* console.log(p1.equals(data)); // true
*
* // Check different points
* const p3 = new ObservablePoint(200, 300);
* console.log(p1.equals(p3)); // false
* ```
* @param p - The point to check
* @returns `true` if both `x` and `y` are equal
*/
equals(p: PointData): boolean;
toString(): string;
/**
* Position of the observable point on the x axis.
* Triggers observer callback when value changes.
* @example
* ```ts
* // Basic x position
* const point = new ObservablePoint(observer);
* point.x = 100; // Triggers observer
*
* // Use in calculations
* const width = rightPoint.x - leftPoint.x;
* ```
* @default 0
*/
get x(): number;
set x(value: number);
/**
* Position of the observable point on the y axis.
* Triggers observer callback when value changes.
* @example
* ```ts
* // Basic y position
* const point = new ObservablePoint(observer);
* point.y = 200; // Triggers observer
*
* // Use in calculations
* const height = bottomPoint.y - topPoint.y;
* ```
* @default 0
*/
get y(): number;
set y(value: number);
}
declare function earcut(vertices: ArrayLike, holes?: ArrayLike, dimensions?: number): number[];
/**
* A simple axis-aligned bounding box (AABB) data structure used to define rectangular boundaries.
* Provides a clearer alternative to array-based bounds representation [minX, minY, maxX, maxY].
* @example
* ```ts
* // Create bounds data
* const bounds: BoundsData = {
* minX: 0,
* minY: 0,
* maxX: 100,
* maxY: 100
* };
*
* // Calculate dimensions
* const width = bounds.maxX - bounds.minX;
* const height = bounds.maxY - bounds.minY;
*
* // Check if point is inside
* const isInside = (x: number, y: number) =>
* x >= bounds.minX && x <= bounds.maxX &&
* y >= bounds.minY && y <= bounds.maxY;
* ```
*/
export interface BoundsData {
/** The minimum X coordinate of the bounds */
minX: number;
/** The minimum Y coordinate of the bounds */
minY: number;
/** The maximum X coordinate of the bounds */
maxX: number;
/** The maximum Y coordinate of the bounds */
maxY: number;
}
/**
* A representation of an axis-aligned bounding box (AABB) used for efficient collision detection and culling.
* Stores minimum and maximum coordinates to define a rectangular boundary.
* @example
* ```ts
* // Create bounds
* const bounds = new Bounds();
*
* // Add a rectangular frame
* bounds.addFrame(0, 0, 100, 100);
* console.log(bounds.width, bounds.height); // 100, 100
*
* // Transform bounds
* const matrix = new Matrix()
* .translate(50, 50)
* .rotate(Math.PI / 4);
* bounds.applyMatrix(matrix);
*
* // Check point intersection
* if (bounds.containsPoint(75, 75)) {
* console.log('Point is inside bounds!');
* }
* ```
*/
export declare class Bounds {
/**
* The minimum X coordinate of the bounds.
* Represents the leftmost edge of the bounding box.
* @example
* ```ts
* const bounds = new Bounds();
* // Set left edge
* bounds.minX = 100;
* ```
* @default Infinity
*/
minX: number;
/**
* The minimum Y coordinate of the bounds.
* Represents the topmost edge of the bounding box.
* @example
* ```ts
* const bounds = new Bounds();
* // Set top edge
* bounds.minY = 100;
* ```
* @default Infinity
*/
minY: number;
/**
* The maximum X coordinate of the bounds.
* Represents the rightmost edge of the bounding box.
* @example
* ```ts
* const bounds = new Bounds();
* // Set right edge
* bounds.maxX = 200;
* // Get width
* const width = bounds.maxX - bounds.minX;
* ```
* @default -Infinity
*/
maxX: number;
/**
* The maximum Y coordinate of the bounds.
* Represents the bottommost edge of the bounding box.
* @example
* ```ts
* const bounds = new Bounds();
* // Set bottom edge
* bounds.maxY = 200;
* // Get height
* const height = bounds.maxY - bounds.minY;
* ```
* @default -Infinity
*/
maxY: number;
/**
* Creates a new Bounds object.
* @param minX - The minimum X coordinate of the bounds.
* @param minY - The minimum Y coordinate of the bounds.
* @param maxX - The maximum X coordinate of the bounds.
* @param maxY - The maximum Y coordinate of the bounds.
*/
constructor(minX?: number, minY?: number, maxX?: number, maxY?: number);
/**
* Checks if bounds are empty, meaning either width or height is zero or negative.
* Empty bounds occur when min values exceed max values on either axis.
* @example
* ```ts
* const bounds = new Bounds();
*
* // Check if newly created bounds are empty
* console.log(bounds.isEmpty()); // true, default bounds are empty
*
* // Add frame and check again
* bounds.addFrame(0, 0, 100, 100);
* console.log(bounds.isEmpty()); // false, bounds now have area
*
* // Clear bounds
* bounds.clear();
* console.log(bounds.isEmpty()); // true, bounds are empty again
* ```
* @returns True if bounds are empty (have no area)
*/
isEmpty(): boolean;
/**
* The bounding rectangle representation of these bounds.
* Lazily creates and updates a Rectangle instance based on the current bounds.
* @example
* ```ts
* const bounds = new Bounds(0, 0, 100, 100);
*
* // Get rectangle representation
* const rect = bounds.rectangle;
* console.log(rect.x, rect.y, rect.width, rect.height);
*
* // Use for hit testing
* if (bounds.rectangle.contains(mouseX, mouseY)) {
* console.log('Mouse is inside bounds!');
* }
* ```
*/
get rectangle(): Rectangle;
/**
* Clears the bounds and resets all coordinates to their default values.
* Resets the transformation matrix back to identity.
* @example
* ```ts
* const bounds = new Bounds(0, 0, 100, 100);
* console.log(bounds.isEmpty()); // false
* // Clear the bounds
* bounds.clear();
* console.log(bounds.isEmpty()); // true
* ```
* @returns This bounds object for chaining
*/
clear(): this;
/**
* Sets the bounds directly using coordinate values.
* Provides a way to set all bounds values at once.
* @example
* ```ts
* const bounds = new Bounds();
* bounds.set(0, 0, 100, 100);
* ```
* @param x0 - Left X coordinate of frame
* @param y0 - Top Y coordinate of frame
* @param x1 - Right X coordinate of frame
* @param y1 - Bottom Y coordinate of frame
*/
set(x0: number, y0: number, x1: number, y1: number): void;
/**
* Adds a rectangular frame to the bounds, optionally transformed by a matrix.
* Updates the bounds to encompass the new frame coordinates.
* @example
* ```ts
* const bounds = new Bounds();
* bounds.addFrame(0, 0, 100, 100);
*
* // Add transformed frame
* const matrix = new Matrix()
* .translate(50, 50)
* .rotate(Math.PI / 4);
* bounds.addFrame(0, 0, 100, 100, matrix);
* ```
* @param x0 - Left X coordinate of frame
* @param y0 - Top Y coordinate of frame
* @param x1 - Right X coordinate of frame
* @param y1 - Bottom Y coordinate of frame
* @param matrix - Optional transformation matrix
*/
addFrame(x0: number, y0: number, x1: number, y1: number, matrix?: Matrix): void;
/**
* Adds a rectangle to the bounds, optionally transformed by a matrix.
* Updates the bounds to encompass the given rectangle.
* @example
* ```ts
* const bounds = new Bounds();
* // Add simple rectangle
* const rect = new Rectangle(0, 0, 100, 100);
* bounds.addRect(rect);
*
* // Add transformed rectangle
* const matrix = new Matrix()
* .translate(50, 50)
* .rotate(Math.PI / 4);
* bounds.addRect(rect, matrix);
* ```
* @param rect - The rectangle to be added
* @param matrix - Optional transformation matrix
*/
addRect(rect: Rectangle, matrix?: Matrix): void;
/**
* Adds another bounds object to this one, optionally transformed by a matrix.
* Expands the bounds to include the given bounds' area.
* @example
* ```ts
* const bounds = new Bounds();
*
* // Add child bounds
* const childBounds = sprite.getBounds();
* bounds.addBounds(childBounds);
*
* // Add transformed bounds
* const matrix = new Matrix()
* .scale(2, 2);
* bounds.addBounds(childBounds, matrix);
* ```
* @param bounds - The bounds to be added
* @param matrix - Optional transformation matrix
*/
addBounds(bounds: BoundsData, matrix?: Matrix): void;
/**
* Adds other Bounds as a mask, creating an intersection of the two bounds.
* Only keeps the overlapping region between current bounds and mask bounds.
* @example
* ```ts
* const bounds = new Bounds(0, 0, 100, 100);
* // Create mask bounds
* const mask = new Bounds();
* mask.addFrame(50, 50, 150, 150);
* // Apply mask - results in bounds of (50,50,100,100)
* bounds.addBoundsMask(mask);
* ```
* @param mask - The Bounds to use as a mask
*/
addBoundsMask(mask: Bounds): void;
/**
* Applies a transformation matrix to the bounds, updating its coordinates.
* Transforms all corners of the bounds using the given matrix.
* @example
* ```ts
* const bounds = new Bounds(0, 0, 100, 100);
* // Apply translation
* const translateMatrix = new Matrix()
* .translate(50, 50);
* bounds.applyMatrix(translateMatrix);
* ```
* @param matrix - The matrix to apply to the bounds
*/
applyMatrix(matrix: Matrix): void;
/**
* Resizes the bounds object to fit within the given rectangle.
* Clips the bounds if they extend beyond the rectangle's edges.
* @example
* ```ts
* const bounds = new Bounds(0, 0, 200, 200);
* // Fit within viewport
* const viewport = new Rectangle(50, 50, 100, 100);
* bounds.fit(viewport);
* // bounds are now (50, 50, 150, 150)
* ```
* @param rect - The rectangle to fit within
* @returns This bounds object for chaining
*/
fit(rect: Rectangle): this;
/**
* Resizes the bounds object to include the given bounds.
* Similar to fit() but works with raw coordinate values instead of a Rectangle.
* @example
* ```ts
* const bounds = new Bounds(0, 0, 200, 200);
* // Fit to specific coordinates
* bounds.fitBounds(50, 150, 50, 150);
* // bounds are now (50, 50, 150, 150)
* ```
* @param left - The left value of the bounds
* @param right - The right value of the bounds
* @param top - The top value of the bounds
* @param bottom - The bottom value of the bounds
* @returns This bounds object for chaining
*/
fitBounds(left: number, right: number, top: number, bottom: number): this;
/**
* Pads bounds object, making it grow in all directions.
* If paddingY is omitted, both paddingX and paddingY will be set to paddingX.
* @example
* ```ts
* const bounds = new Bounds(0, 0, 100, 100);
*
* // Add equal padding
* bounds.pad(10);
* // bounds are now (-10, -10, 110, 110)
*
* // Add different padding for x and y
* bounds.pad(20, 10);
* // bounds are now (-30, -20, 130, 120)
* ```
* @param paddingX - The horizontal padding amount
* @param paddingY - The vertical padding amount
* @returns This bounds object for chaining
*/
pad(paddingX: number, paddingY?: number): this;
/**
* Ceils the bounds by rounding up max values and rounding down min values.
* Useful for pixel-perfect calculations and avoiding fractional pixels.
* @example
* ```ts
* const bounds = new Bounds();
* bounds.set(10.2, 10.9, 50.1, 50.8);
*
* // Round to whole pixels
* bounds.ceil();
* // bounds are now (10, 10, 51, 51)
* ```
* @returns This bounds object for chaining
*/
ceil(): this;
/**
* Creates a new Bounds instance with the same values.
* @example
* ```ts
* const bounds = new Bounds(0, 0, 100, 100);
*
* // Create a copy
* const copy = bounds.clone();
*
* // Original and copy are independent
* bounds.pad(10);
* console.log(copy.width === bounds.width); // false
* ```
* @returns A new Bounds instance with the same values
*/
clone(): Bounds;
/**
* Scales the bounds by the given values, adjusting all edges proportionally.
* @example
* ```ts
* const bounds = new Bounds(0, 0, 100, 100);
*
* // Scale uniformly
* bounds.scale(2);
* // bounds are now (0, 0, 200, 200)
*
* // Scale non-uniformly
* bounds.scale(0.5, 2);
* // bounds are now (0, 0, 100, 400)
* ```
* @param x - The X value to scale by
* @param y - The Y value to scale by (defaults to x)
* @returns This bounds object for chaining
*/
scale(x: number, y?: number): this;
/**
* The x position of the bounds in local space.
* Setting this value will move the bounds while maintaining its width.
* @example
* ```ts
* const bounds = new Bounds(0, 0, 100, 100);
* // Get x position
* console.log(bounds.x); // 0
*
* // Move bounds horizontally
* bounds.x = 50;
* console.log(bounds.minX, bounds.maxX); // 50, 150
*
* // Width stays the same
* console.log(bounds.width); // Still 100
* ```
*/
get x(): number;
set x(value: number);
/**
* The y position of the bounds in local space.
* Setting this value will move the bounds while maintaining its height.
* @example
* ```ts
* const bounds = new Bounds(0, 0, 100, 100);
* // Get y position
* console.log(bounds.y); // 0
*
* // Move bounds vertically
* bounds.y = 50;
* console.log(bounds.minY, bounds.maxY); // 50, 150
*
* // Height stays the same
* console.log(bounds.height); // Still 100
* ```
*/
get y(): number;
set y(value: number);
/**
* The width value of the bounds.
* Represents the distance between minX and maxX coordinates.
* @example
* ```ts
* const bounds = new Bounds(0, 0, 100, 100);
* // Get width
* console.log(bounds.width); // 100
* // Resize width
* bounds.width = 200;
* console.log(bounds.maxX - bounds.minX); // 200
* ```
*/
get width(): number;
set width(value: number);
/**
* The height value of the bounds.
* Represents the distance between minY and maxY coordinates.
* @example
* ```ts
* const bounds = new Bounds(0, 0, 100, 100);
* // Get height
* console.log(bounds.height); // 100
* // Resize height
* bounds.height = 150;
* console.log(bounds.maxY - bounds.minY); // 150
* ```
*/
get height(): number;
set height(value: number);
/**
* The left edge coordinate of the bounds.
* Alias for minX.
* @example
* ```ts
* const bounds = new Bounds(50, 0, 150, 100);
* console.log(bounds.left); // 50
* console.log(bounds.left === bounds.minX); // true
* ```
*/
get left(): number;
/**
* The right edge coordinate of the bounds.
* Alias for maxX.
* @example
* ```ts
* const bounds = new Bounds(0, 0, 100, 100);
* console.log(bounds.right); // 100
* console.log(bounds.right === bounds.maxX); // true
* ```
*/
get right(): number;
/**
* The top edge coordinate of the bounds.
* Alias for minY.
* @example
* ```ts
* const bounds = new Bounds(0, 25, 100, 125);
* console.log(bounds.top); // 25
* console.log(bounds.top === bounds.minY); // true
* ```
*/
get top(): number;
/**
* The bottom edge coordinate of the bounds.
* Alias for maxY.
* @example
* ```ts
* const bounds = new Bounds(0, 0, 100, 200);
* console.log(bounds.bottom); // 200
* console.log(bounds.bottom === bounds.maxY); // true
* ```
*/
get bottom(): number;
/**
* Whether the bounds has positive width and height.
* Checks if both dimensions are greater than zero.
* @example
* ```ts
* const bounds = new Bounds(0, 0, 100, 100);
* // Check if bounds are positive
* console.log(bounds.isPositive); // true
*
* // Negative bounds
* bounds.maxX = bounds.minX;
* console.log(bounds.isPositive); // false, width is 0
* ```
*/
get isPositive(): boolean;
/**
* Whether the bounds has valid coordinates.
* Checks if the bounds has been initialized with real values.
* @example
* ```ts
* const bounds = new Bounds();
* console.log(bounds.isValid); // false, default state
*
* // Set valid bounds
* bounds.addFrame(0, 0, 100, 100);
* console.log(bounds.isValid); // true
* ```
*/
get isValid(): boolean;
/**
* Adds vertices from a Float32Array to the bounds, optionally transformed by a matrix.
* Used for efficiently updating bounds from raw vertex data.
* @example
* ```ts
* const bounds = new Bounds();
*
* // Add vertices from geometry
* const vertices = new Float32Array([
* 0, 0, // Vertex 1
* 100, 0, // Vertex 2
* 100, 100 // Vertex 3
* ]);
* bounds.addVertexData(vertices, 0, 6);
*
* // Add transformed vertices
* const matrix = new Matrix()
* .translate(50, 50)
* .rotate(Math.PI / 4);
* bounds.addVertexData(vertices, 0, 6, matrix);
*
* // Add subset of vertices
* bounds.addVertexData(vertices, 2, 4); // Only second vertex
* ```
* @param vertexData - The array of vertices to add
* @param beginOffset - Starting index in the vertex array
* @param endOffset - Ending index in the vertex array (excluded)
* @param matrix - Optional transformation matrix
*/
addVertexData(vertexData: Float32Array, beginOffset: number, endOffset: number, matrix?: Matrix): void;
/**
* Checks if a point is contained within the bounds.
* Returns true if the point's coordinates fall within the bounds' area.
* @example
* ```ts
* const bounds = new Bounds(0, 0, 100, 100);
* // Basic point check
* console.log(bounds.containsPoint(50, 50)); // true
* console.log(bounds.containsPoint(150, 150)); // false
*
* // Check edges
* console.log(bounds.containsPoint(0, 0)); // true, includes edges
* console.log(bounds.containsPoint(100, 100)); // true, includes edges
* ```
* @param x - x coordinate to check
* @param y - y coordinate to check
* @returns True if the point is inside the bounds
*/
containsPoint(x: number, y: number): boolean;
/**
* Returns a string representation of the bounds.
* Useful for debugging and logging bounds information.
* @example
* ```ts
* const bounds = new Bounds(0, 0, 100, 100);
* console.log(bounds.toString()); // "[pixi.js:Bounds minX=0 minY=0 maxX=100 maxY=100 width=100 height=100]"
* ```
* @returns A string describing the bounds
*/
toString(): string;
/**
* Copies the bounds from another bounds object.
* Useful for reusing bounds objects and avoiding allocations.
* @example
* ```ts
* const sourceBounds = new Bounds(0, 0, 100, 100);
* // Copy bounds
* const targetBounds = new Bounds();
* targetBounds.copyFrom(sourceBounds);
* ```
* @param bounds - The bounds to copy from
* @returns This bounds object for chaining
*/
copyFrom(bounds: Bounds): this;
}
/**
* Two Pi.
* @type {number}
*/
export declare const PI_2: number;
/**
* Conversion factor for converting radians to degrees.
* @type {number} RAD_TO_DEG
*/
export declare const RAD_TO_DEG: number;
/**
* Conversion factor for converting degrees to radians.
* @type {number}
*/
export declare const DEG_TO_RAD: number;
export interface Rectangle extends PixiMixins.Rectangle {
}
/**
* The `Rectangle` object represents a rectangular area defined by its position and dimensions.
* Used for hit testing, bounds calculation, and general geometric operations.
* @example
* ```ts
* // Basic rectangle creation
* const rect = new Rectangle(100, 100, 200, 150);
*
* // Use as container bounds
* container.hitArea = new Rectangle(0, 0, 100, 100);
*
* // Check point containment
* const isInside = rect.contains(mouseX, mouseY);
*
* // Manipulate dimensions
* rect.width *= 2;
* rect.height += 50;
* ```
* @remarks
* - Position defined by top-left corner (x,y)
* - Dimensions defined by width and height
* - Supports point and rectangle containment
* - Common in UI and layout calculations
*/
export declare class Rectangle implements ShapePrimitive {
/**
* The type of the object, mainly used to avoid `instanceof` checks
* @example
* ```ts
* // Check shape type
* const shape = new Rectangle(0, 0, 100, 100);
* console.log(shape.type); // 'rectangle'
*
* // Use in type guards
* if (shape.type === 'rectangle') {
* console.log(shape.width, shape.height);
* }
* ```
* @default 'rectangle'
*/
readonly type: SHAPE_PRIMITIVE;
/**
* The X coordinate of the upper-left corner of the rectangle
* @example
* ```ts
* // Basic x position
* const rect = new Rectangle();
* rect.x = 100;
* ```
* @default 0
*/
x: number;
/**
* The Y coordinate of the upper-left corner of the rectangle
* @example
* ```ts
* // Basic y position
* const rect = new Rectangle();
* rect.y = 100;
* ```
* @default 0
*/
y: number;
/**
* The overall width of this rectangle
* @example
* ```ts
* // Basic width setting
* const rect = new Rectangle();
* rect.width = 200;
* ```
* @default 0
*/
width: number;
/**
* The overall height of this rectangle
* @example
* ```ts
* // Basic height setting
* const rect = new Rectangle();
* rect.height = 150;
* ```
* @default 0
*/
height: number;
/**
* @param x - The X coordinate of the upper-left corner of the rectangle
* @param y - The Y coordinate of the upper-left corner of the rectangle
* @param width - The overall width of the rectangle
* @param height - The overall height of the rectangle
*/
constructor(x?: string | number, y?: string | number, width?: string | number, height?: string | number);
/**
* Returns the left edge (x-coordinate) of the rectangle.
* @example
* ```ts
* // Get left edge position
* const rect = new Rectangle(100, 100, 200, 150);
* console.log(rect.left); // 100
*
* // Use in alignment calculations
* sprite.x = rect.left + padding;
*
* // Compare positions
* if (point.x > rect.left) {
* console.log('Point is right of rectangle');
* }
* ```
* @returns The x-coordinate of the left edge
*/
get left(): number;
/**
* Returns the right edge (x + width) of the rectangle.
* @example
* ```ts
* // Get right edge position
* const rect = new Rectangle(100, 100, 200, 150);
* console.log(rect.right); // 300
*
* // Align to right edge
* sprite.x = rect.right - sprite.width;
*
* // Check boundaries
* if (point.x < rect.right) {
* console.log('Point is inside right bound');
* }
* ```
* @returns The x-coordinate of the right edge
*/
get right(): number;
/**
* Returns the top edge (y-coordinate) of the rectangle.
* @example
* ```ts
* // Get top edge position
* const rect = new Rectangle(100, 100, 200, 150);
* console.log(rect.top); // 100
*
* // Position above rectangle
* sprite.y = rect.top - sprite.height;
*
* // Check vertical position
* if (point.y > rect.top) {
* console.log('Point is below top edge');
* }
* ```
* @returns The y-coordinate of the top edge
*/
get top(): number;
/**
* Returns the bottom edge (y + height) of the rectangle.
* @example
* ```ts
* // Get bottom edge position
* const rect = new Rectangle(100, 100, 200, 150);
* console.log(rect.bottom); // 250
*
* // Stack below rectangle
* sprite.y = rect.bottom + margin;
*
* // Check vertical bounds
* if (point.y < rect.bottom) {
* console.log('Point is above bottom edge');
* }
* ```
* @returns The y-coordinate of the bottom edge
*/
get bottom(): number;
/**
* Determines whether the Rectangle is empty (has no area).
* @example
* ```ts
* // Check zero dimensions
* const rect = new Rectangle(100, 100, 0, 50);
* console.log(rect.isEmpty()); // true
* ```
* @returns True if the rectangle has no area
*/
isEmpty(): boolean;
/**
* A constant empty rectangle. This is a new object every time the property is accessed.
* @example
* ```ts
* // Get fresh empty rectangle
* const empty = Rectangle.EMPTY;
* console.log(empty.isEmpty()); // true
* ```
* @returns A new empty rectangle instance
*/
static get EMPTY(): Rectangle;
/**
* Creates a clone of this Rectangle
* @example
* ```ts
* // Basic cloning
* const original = new Rectangle(100, 100, 200, 150);
* const copy = original.clone();
*
* // Clone and modify
* const modified = original.clone();
* modified.width *= 2;
* modified.height += 50;
*
* // Verify independence
* console.log(original.width); // 200
* console.log(modified.width); // 400
* ```
* @returns A copy of the rectangle
*/
clone(): Rectangle;
/**
* Converts a Bounds object to a Rectangle object.
* @example
* ```ts
* // Convert bounds to rectangle
* const bounds = container.getBounds();
* const rect = new Rectangle().copyFromBounds(bounds);
* ```
* @param bounds - The bounds to copy and convert to a rectangle
* @returns Returns itself
*/
copyFromBounds(bounds: Bounds): this;
/**
* Copies another rectangle to this one.
* @example
* ```ts
* // Basic copying
* const source = new Rectangle(100, 100, 200, 150);
* const target = new Rectangle();
* target.copyFrom(source);
*
* // Chain with other operations
* const rect = new Rectangle()
* .copyFrom(source)
* .pad(10);
* ```
* @param rectangle - The rectangle to copy from
* @returns Returns itself
*/
copyFrom(rectangle: Rectangle): Rectangle;
/**
* Copies this rectangle to another one.
* @example
* ```ts
* // Basic copying
* const source = new Rectangle(100, 100, 200, 150);
* const target = new Rectangle();
* source.copyTo(target);
*
* // Chain with other operations
* const result = source
* .copyTo(new Rectangle())
* .getBounds();
* ```
* @param rectangle - The rectangle to copy to
* @returns Returns given parameter
*/
copyTo(rectangle: Rectangle): Rectangle;
/**
* Checks whether the x and y coordinates given are contained within this Rectangle
* @example
* ```ts
* // Basic containment check
* const rect = new Rectangle(100, 100, 200, 150);
* const isInside = rect.contains(150, 125); // true
* // Check edge cases
* console.log(rect.contains(100, 100)); // true (on edge)
* console.log(rect.contains(300, 250)); // false (outside)
* ```
* @param x - The X coordinate of the point to test
* @param y - The Y coordinate of the point to test
* @returns Whether the x/y coordinates are within this Rectangle
*/
contains(x: number, y: number): boolean;
/**
* Checks whether the x and y coordinates given are contained within this rectangle including the stroke.
* @example
* ```ts
* // Basic stroke check
* const rect = new Rectangle(100, 100, 200, 150);
* const isOnStroke = rect.strokeContains(150, 100, 4); // 4px line width
*
* // Check with different alignments
* const innerStroke = rect.strokeContains(150, 100, 4, 0); // Inside
* const centerStroke = rect.strokeContains(150, 100, 4, 0.5); // Centered
* const outerStroke = rect.strokeContains(150, 100, 4, 1); // Outside
* ```
* @param x - The X coordinate of the point to test
* @param y - The Y coordinate of the point to test
* @param strokeWidth - The width of the line to check
* @param alignment - The alignment of the stroke (0 = inner, 0.5 = centered, 1 = outer)
* @returns Whether the x/y coordinates are within this rectangle's stroke
*/
strokeContains(x: number, y: number, strokeWidth: number, alignment?: number): boolean;
/**
* Determines whether the `other` Rectangle transformed by `transform` intersects with `this` Rectangle object.
* Returns true only if the area of the intersection is >0, this means that Rectangles
* sharing a side are not overlapping. Another side effect is that an arealess rectangle
* (width or height equal to zero) can't intersect any other rectangle.
* @param {Rectangle} other - The Rectangle to intersect with `this`.
* @param {Matrix} transform - The transformation matrix of `other`.
* @returns {boolean} A value of `true` if the transformed `other` Rectangle intersects with `this`; otherwise `false`.
*/
/**
* Determines whether the `other` Rectangle transformed by `transform` intersects with `this` Rectangle object.
*
* Returns true only if the area of the intersection is greater than 0.
* This means that rectangles sharing only a side are not considered intersecting.
* @example
* ```ts
* // Basic intersection check
* const rect1 = new Rectangle(0, 0, 100, 100);
* const rect2 = new Rectangle(50, 50, 100, 100);
* console.log(rect1.intersects(rect2)); // true
*
* // With transformation matrix
* const matrix = new Matrix();
* matrix.rotate(Math.PI / 4); // 45 degrees
* console.log(rect1.intersects(rect2, matrix)); // Checks with rotation
*
* // Edge cases
* const zeroWidth = new Rectangle(0, 0, 0, 100);
* console.log(rect1.intersects(zeroWidth)); // false (no area)
* ```
* @remarks
* - Returns true only if intersection area is > 0
* - Rectangles sharing only a side are not intersecting
* - Zero-area rectangles cannot intersect anything
* - Supports optional transformation matrix
* @param other - The Rectangle to intersect with `this`
* @param transform - Optional transformation matrix of `other`
* @returns True if the transformed `other` Rectangle intersects with `this`
*/
intersects(other: Rectangle, transform?: Matrix): boolean;
/**
* Pads the rectangle making it grow in all directions.
*
* If paddingY is omitted, both paddingX and paddingY will be set to paddingX.
* @example
* ```ts
* // Basic padding
* const rect = new Rectangle(100, 100, 200, 150);
* rect.pad(10); // Adds 10px padding on all sides
*
* // Different horizontal and vertical padding
* const uiRect = new Rectangle(0, 0, 100, 50);
* uiRect.pad(20, 10); // 20px horizontal, 10px vertical
* ```
* @remarks
* - Adjusts x/y by subtracting padding
* - Increases width/height by padding * 2
* - Common in UI layout calculations
* - Chainable with other methods
* @param paddingX - The horizontal padding amount
* @param paddingY - The vertical padding amount
* @returns Returns itself
*/
pad(paddingX?: number, paddingY?: number): this;
/**
* Fits this rectangle around the passed one.
* @example
* ```ts
* // Basic fitting
* const container = new Rectangle(0, 0, 100, 100);
* const content = new Rectangle(25, 25, 200, 200);
* content.fit(container); // Clips to container bounds
* ```
* @param rectangle - The rectangle to fit around
* @returns Returns itself
*/
fit(rectangle: Rectangle): this;
/**
* Enlarges rectangle so that its corners lie on a grid defined by resolution.
* @example
* ```ts
* // Basic grid alignment
* const rect = new Rectangle(10.2, 10.6, 100.8, 100.4);
* rect.ceil(); // Aligns to whole pixels
*
* // Custom resolution grid
* const uiRect = new Rectangle(5.3, 5.7, 50.2, 50.8);
* uiRect.ceil(0.5); // Aligns to half pixels
*
* // Use with precision value
* const preciseRect = new Rectangle(20.001, 20.999, 100.001, 100.999);
* preciseRect.ceil(1, 0.01); // Handles small decimal variations
* ```
* @param resolution - The grid size to align to (1 = whole pixels)
* @param eps - Small number to prevent floating point errors
* @returns Returns itself
*/
ceil(resolution?: number, eps?: number): this;
/**
* Enlarges this rectangle to include the passed rectangle.
* @example
* ```ts
* // Basic enlargement
* const rect = new Rectangle(50, 50, 100, 100);
* const other = new Rectangle(0, 0, 200, 75);
* rect.enlarge(other);
* // rect is now: x=0, y=0, width=200, height=150
*
* // Use for bounding box calculation
* const bounds = new Rectangle();
* objects.forEach((obj) => {
* bounds.enlarge(obj.getBounds());
* });
* ```
* @param rectangle - The rectangle to include
* @returns Returns itself
*/
enlarge(rectangle: Rectangle): this;
/**
* Returns the framing rectangle of the rectangle as a Rectangle object
* @example
* ```ts
* // Basic bounds retrieval
* const rect = new Rectangle(100, 100, 200, 150);
* const bounds = rect.getBounds();
*
* // Reuse existing rectangle
* const out = new Rectangle();
* rect.getBounds(out);
* ```
* @param out - Optional rectangle to store the result
* @returns The framing rectangle
*/
getBounds(out?: Rectangle): Rectangle;
/**
* Determines whether another Rectangle is fully contained within this Rectangle.
*
* Rectangles that occupy the same space are considered to be containing each other.
*
* Rectangles without area (width or height equal to zero) can't contain anything,
* not even other arealess rectangles.
* @example
* ```ts
* // Check if one rectangle contains another
* const container = new Rectangle(0, 0, 100, 100);
* const inner = new Rectangle(25, 25, 50, 50);
*
* console.log(container.containsRect(inner)); // true
*
* // Check overlapping rectangles
* const partial = new Rectangle(75, 75, 50, 50);
* console.log(container.containsRect(partial)); // false
*
* // Zero-area rectangles
* const empty = new Rectangle(0, 0, 0, 100);
* console.log(container.containsRect(empty)); // false
* ```
* @param other - The Rectangle to check for containment
* @returns True if other is fully contained within this Rectangle
*/
containsRect(other: Rectangle): boolean;
/**
* Sets the position and dimensions of the rectangle.
* @example
* ```ts
* // Basic usage
* const rect = new Rectangle();
* rect.set(100, 100, 200, 150);
*
* // Chain with other operations
* const bounds = new Rectangle()
* .set(0, 0, 100, 100)
* .pad(10);
* ```
* @param x - The X coordinate of the upper-left corner of the rectangle
* @param y - The Y coordinate of the upper-left corner of the rectangle
* @param width - The overall width of the rectangle
* @param height - The overall height of the rectangle
* @returns Returns itself for method chaining
*/
set(x: number, y: number, width: number, height: number): this;
toString(): string;
}
/**
* Base options for destroying display objects.
* Controls how deep the destruction process should go through the display tree.
* @example
* ```ts
* // Basic destruction - only this container
* container.destroy({ children: false });
*
* // Deep destruction - container and all children
* container.destroy({ children: true });
*
* // Cleanup pattern
* function cleanupScene(scene: Container) {
* // Remove from parent first
* scene.parent?.removeChild(scene);
* // Then destroy with all children
* scene.destroy({ children: true });
* }
* ```
*/
export interface BaseDestroyOptions {
/**
* Whether to destroy children recursively.
* When true, runs destroy() on all children in the display tree.
* @default false
* @example
* ```js
* container.destroy({ children: true });
* ```
*/
children?: boolean;
}
/**
* Options when destroying textures through `.destroy()` calls.
* Controls how thoroughly textures and their sources are cleaned up.
* @example
* ```ts
* // Basic texture cleanup
* sprite.destroy({
* texture: true
* });
*
* // Complete texture cleanup
* sprite.destroy({
* texture: true,
* textureSource: true
* });
* ```
*/
export interface TextureDestroyOptions {
/**
* Whether to destroy the texture for the display object.
* @default false
* @example
* ```js
* texturedObject.destroy({ texture: true });
* ```
*/
texture?: boolean;
/**
* Whether to destroy the underlying texture source.
* Use carefully with shared texture sources.
* @default false
* @example
* ```js
* texturedObject.destroy({ textureSource: true });
* ```
*/
textureSource?: boolean;
}
/**
* Options when destroying a graphics context.
* Controls the cleanup of graphics-specific resources.
* @example
* ```ts
* // Basic context cleanup
* graphics.destroy({
* context: true
* });
*
* // Full graphics cleanup
* graphics.destroy({
* context: true,
* texture: true,
* textureSource: true
* });
* ```
*/
export interface ContextDestroyOptions {
/**
* Whether to destroy the graphics context associated with the graphics object.
* @default false
* @example
* ```js
* graphics.destroy({ context: true });
* ```
*/
context?: boolean;
}
/**
* Options when destroying a text object. Controls whether associated text styles
* should be cleaned up along with the text object itself.
* ```ts
* // Basic text cleanup
* text.destroy({ style: false }); // Keep style for reuse
* text.destroy({ style: true }); // Destroy style as well
* ```
*/
export interface TextDestroyOptions {
/**
* Whether to destroy the text style object along with the text.
* Use carefully with shared styles.
* @default false
*/
style?: boolean;
}
/**
* Options for destroying a container and its resources.
* Combines all destroy options into a single configuration object.
* @example
* ```ts
* // Destroy the container and all its children, including textures and styles
* container.destroy({
* children: true,
* texture: true,
* textureSource: true,
* context: true,
* style: true
* });
* ```
*/
export type DestroyOptions = TypeOrBool;
/**
* Global registration system for all PixiJS extensions. Provides a centralized way to add, remove,
* and manage functionality across the engine.
*
* Features:
* - Register custom extensions and plugins
* - Handle multiple extension types
* - Priority-based ordering
* @example
* ```ts
* import { extensions, ExtensionType } from 'pixi.js';
*
* // Register a simple object extension
* extensions.add({
* extension: {
* type: ExtensionType.LoadParser,
* name: 'my-loader',
* priority: 100, // Optional priority for ordering
* },
* // add load parser functions
* });
*
* // Register a class-based extension
* class MyRendererPlugin {
* static extension = {
* type: [ExtensionType.WebGLSystem, ExtensionType.WebGPUSystem],
* name: 'myRendererPlugin'
* };
*
* // add renderer plugin methods
* }
* extensions.add(MyRendererPlugin);
*
* // Remove extensions
* extensions.remove(MyRendererPlugin);
* ```
* @remarks
* - Extensions must have a type from {@link ExtensionType}
* - Can be registered before or after their handlers
* - Supports priority-based ordering
* - Automatically normalizes extension formats
*/
export declare const extensions: {
/**
* Remove extensions from PixiJS.
* @param extensions - Extensions to be removed. Can be:
* - Extension class with static `extension` property
* - Extension format object with `type` and `ref`
* - Multiple extensions as separate arguments
* @returns {extensions} this for chaining
* @example
* ```ts
* // Remove a single extension
* extensions.remove(MyRendererPlugin);
*
* // Remove multiple extensions
* extensions.remove(
* MyRendererPlugin,
* MySystemPlugin
* );
* ```
*/
remove(...extensions: Array): any;
/**
* Register new extensions with PixiJS. Extensions can be registered in multiple formats:
* - As a class with a static `extension` property
* - As an extension format object
* - As multiple extensions passed as separate arguments
* @param extensions - Extensions to add to PixiJS. Each can be:
* - A class with static `extension` property
* - An extension format object with `type` and `ref`
* - Multiple extensions as separate arguments
* @returns This extensions instance for chaining
* @example
* ```ts
* // Register a simple extension
* extensions.add(MyRendererPlugin);
*
* // Register multiple extensions
* extensions.add(
* MyRendererPlugin,
* MySystemPlugin,
* });
* ```
*/
add(...extensions: Array): any;
/**
* Mixin the source object(s) properties into the target class's prototype.
* Copies all property descriptors from source objects to the target's prototype.
* @param Target - The target class to mix properties into
* @param sources - One or more source objects containing properties to mix in
* @example
* ```ts
* // Create a mixin with shared properties
* const moveable = {
* x: 0,
* y: 0,
* move(x: number, y: number) {
* this.x += x;
* this.y += y;
* }
* };
*
* // Create a mixin with computed properties
* const scalable = {
* scale: 1,
* get scaled() {
* return this.scale > 1;
* }
* };
*
* // Apply mixins to a class
* extensions.mixin(Sprite, moveable, scalable);
*
* // Use mixed-in properties
* const sprite = new Sprite();
* sprite.move(10, 20);
* console.log(sprite.x, sprite.y); // 10, 20
* ```
* @remarks
* - Copies all properties including getters/setters
* - Does not modify source objects
* - Preserves property descriptors
*/
mixin(Target: any, ...sources: Parameters[0][]): void;
};
/**
* The wrap modes that are supported by pixi.
*
* The wrap mode affects the default wrapping mode of future operations.
* - `clamp-to-edge` is the default mode, which clamps the texture coordinates to the edge of the texture.
* - `repeat` allows the texture to repeat in both u and v directions.
* - `mirror-repeat` allows the texture to repeat in both u and v directions, but mirrors the texture on every other repeat.
*/
export type WRAP_MODE = "clamp-to-edge" | "repeat" | "mirror-repeat";
/**
* The scale modes that are supported by pixi.
*
* The scale mode affects the default scaling mode of future operations.
* It can be re-assigned to either LINEAR or NEAREST, depending upon suitability.
*
* - `nearest` is a pixelating scaling mode, which does not interpolate pixels.
* - `linear` is a smooth scaling mode, which interpolates pixels for smoother results.
*/
export type SCALE_MODE = "nearest" | "linear";
/**
* The options that can be passed to a new Texture
*/
export interface TextureOptions {
/** the underlying texture data that this texture will use */
source?: TextureSourceType;
/** optional label, for debugging */
label?: string;
/** The rectangle frame of the texture to show */
frame?: Rectangle;
/** The area of original texture */
orig?: Rectangle;
/** Trimmed rectangle of original texture */
trim?: Rectangle;
/** Default anchor point used for sprite placement / rotation */
defaultAnchor?: {
x: number;
y: number;
};
/** Default borders used for 9-slice scaling {@link NineSlicePlane}*/
defaultBorders?: TextureBorders;
/** indicates how the texture was rotated by texture packer. See {@link groupD8} */
rotate?: number;
/**
* Set to true if you plan on modifying this texture's frame, UVs, or swapping its source at runtime.
* This is false by default as it improves performance. Generally, it's recommended to create new
* textures and swap those rather than modifying an existing texture's properties unless you are
* working with a dynamic frames.
* Not setting this to true when modifying the texture can lead to visual artifacts.
*
* If this is false and you modify the texture, you can manually update the sprite's texture by calling
* `sprite.onViewUpdate()`.
*/
dynamic?: boolean;
}
/**
* A texture stores the information that represents an image or part of an image.
*
* A texture must have a loaded resource passed to it to work. It does not contain any
* loading mechanisms.
*
* The Assets class can be used to load a texture from a file. This is the recommended
* way as it will handle the loading and caching for you.
*
* ```js
*
* const texture = await Assets.load('assets/image.png');
*
* // once Assets has loaded the image it will be available via the from method
* const sameTexture = Texture.from('assets/image.png');
* // another way to access the texture once loaded
* const sameAgainTexture = Asset.get('assets/image.png');
*
* const sprite1 = new Sprite(texture);
*
* ```
*
* It cannot be added to the display list directly; instead use it as the texture for a Sprite.
* If no frame is provided for a texture, then the whole image is used.
*
* You can directly create a texture from an image and then reuse it multiple times like this :
*
* ```js
* import { Sprite, Texture } from 'pixi.js';
*
* const texture = await Assets.load('assets/image.png');
* const sprite1 = new Sprite(texture);
* const sprite2 = new Sprite(texture);
* ```
*
* If you didn't pass the texture frame to constructor, it enables `noFrame` mode:
* it subscribes on baseTexture events, it automatically resizes at the same time as baseTexture.
*/
export declare class Texture extends EventEmitter<{
update: Texture;
destroy: Texture;
}> implements BindableTexture {
/**
* Helper function that creates a returns Texture based on the source you provide.
* The source should be loaded and ready to go. If not its best to grab the asset using Assets.
* @param id - String or Source to create texture from
* @param skipCache - Skip adding the texture to the cache
* @returns The texture based on the Id provided
*/
static from: (id: TextureSourceLike, skipCache?: boolean) => Texture;
/** label used for debugging */
label?: string;
/** unique id for this texture */
readonly uid: number;
/**
* Has the texture been destroyed?
*/
destroyed: boolean;
/**
* Indicates whether the texture is rotated inside the atlas
* set to 2 to compensate for texture packer rotation
* set to 6 to compensate for spine packer rotation
* can be used to rotate or mirror sprites
* See {@link groupD8} for explanation
*/
readonly rotate: number;
/** A uvs object based on the given frame and the texture source */
readonly uvs: UVs;
/**
* Anchor point that is used as default if sprite is created with this texture.
* Changing the `defaultAnchor` at a later point of time will not update Sprite's anchor point.
* @default {0,0}
*/
readonly defaultAnchor?: {
x: number;
y: number;
};
/**
* Default width of the non-scalable border that is used if 9-slice plane is created with this texture.
* @since 7.2.0
*/
readonly defaultBorders?: TextureBorders;
/**
* This is the area of the BaseTexture image to actually copy to the Canvas / WebGL when rendering,
* irrespective of the actual frame size or placement (which can be influenced by trimmed texture atlases)
*/
readonly frame: Rectangle;
/** This is the area of original texture, before it was put in atlas. */
readonly orig: Rectangle;
/**
* This is the trimmed area of original texture, before it was put in atlas
* Please call `updateUvs()` after you change coordinates of `trim` manually.
*/
readonly trim: Rectangle;
/**
* Does this Texture have any frame data assigned to it?
*
* This mode is enabled automatically if no frame was passed inside constructor.
*
* In this mode texture is subscribed to baseTexture events, and fires `update` on any change.
*
* Beware, after loading or resize of baseTexture event can fired two times!
* If you want more control, subscribe on baseTexture itself.
* @example
* texture.on('update', () => {});
*/
noFrame: boolean;
/**
* Set to true if you plan on modifying the uvs of this texture.
* When this is the case, sprites and other objects using the texture will
* make sure to listen for changes to the uvs and update their vertices accordingly.
*/
dynamic: boolean;
/** is it a texture? yes! used for type checking */
readonly isTexture = true;
/**
* @param {TextureOptions} options - Options for the texture
*/
constructor({ source, label, frame, orig, trim, defaultAnchor, defaultBorders, rotate, dynamic }?: TextureOptions);
set source(value: TextureSourceType);
/** the underlying source of the texture (equivalent of baseTexture in v7) */
get source(): TextureSourceType;
/** returns a TextureMatrix instance for this texture. By default, that object is not created because its heavy. */
get textureMatrix(): TextureMatrix;
/** The width of the Texture in pixels. */
get width(): number;
/** The height of the Texture in pixels. */
get height(): number;
/** Call this function when you have modified the frame of this texture. */
updateUvs(): void;
/**
* Destroys this texture
* @param destroySource - Destroy the source when the texture is destroyed.
*/
destroy(destroySource?: boolean): void;
/**
* Call this if you have modified the `texture outside` of the constructor.
*
* If you have modified this texture's source, you must separately call `texture.source.update()` to see those changes.
*/
update(): void;
/** @deprecated since 8.0.0 */
get baseTexture(): TextureSource;
/** an Empty Texture used internally by the engine */
static EMPTY: Texture;
/** a White texture used internally by the engine */
static WHITE: Texture;
}
/**
* System that manages the generation of textures from display objects in the renderer.
* This system is responsible for creating reusable textures from containers, sprites, and other display objects.
* Available through `renderer.textureGenerator`.
* @example
* ```ts
* import { Application, Sprite, Graphics } from 'pixi.js';
*
* const app = new Application();
* await app.init();
*
* // Create a complex display object
* const container = new Container();
*
* const graphics = new Graphics()
* .circle(0, 0, 50)
* .fill('red');
*
* const sprite = new Sprite(texture);
* sprite.x = 100;
*
* container.addChild(graphics, sprite);
*
* // Generate a texture from the container
* const generatedTexture = app.renderer.textureGenerator.generateTexture({
* target: container,
* resolution: 2,
* antialias: true
* });
*
* // Use the generated texture
* const newSprite = new Sprite(generatedTexture);
* app.stage.addChild(newSprite);
*
* // Clean up when done
* generatedTexture.destroy(true);
* ```
*
* Features:
* - Convert any display object to a texture
* - Support for custom regions and resolutions
* - Anti-aliasing support
* - Background color configuration
* - Texture source options customization
*
* Common Use Cases:
* - Creating texture atlases dynamically
* - Caching complex container content
* - Generating thumbnails
* - Creating reusable textures from rendered content
*
* Performance Considerations:
* - Generating textures is relatively expensive
* - Cache results when possible
* - Be mindful of resolution and size
* - Clean up unused textures
*/
export declare class GenerateTextureSystem implements System {
constructor(renderer: Renderer);
/**
* Creates a texture from a display object that can be used for creating sprites and other textures.
* This is particularly useful for optimizing performance when a complex container needs to be reused.
* @param options - Generate texture options or a container to convert to texture
* @returns A new RenderTexture containing the rendered display object
* @example
* ```ts
* // Basic usage with a container
* const container = new Container();
* container.addChild(
* new Graphics()
* .circle(0, 0, 50)
* .fill('red')
* );
*
* const texture = renderer.textureGenerator.generateTexture(container);
*
* // Advanced usage with options
* const texture = renderer.textureGenerator.generateTexture({
* target: container,
* frame: new Rectangle(0, 0, 100, 100), // Specific region
* resolution: 2, // High DPI
* clearColor: '#ff0000', // Red background
* antialias: true // Smooth edges
* });
*
* // Create a sprite from the generated texture
* const sprite = new Sprite(texture);
*
* // Clean up when done
* texture.destroy(true);
* ```
*/
generateTexture(options: GenerateTextureOptions | Container): RenderTexture;
destroy(): void;
}
/**
* Various blend modes supported by Pixi
*/
export type BLEND_MODES = "inherit" | "normal" | "add" | "multiply" | "screen" | "darken" | "lighten" | "erase" | "color-dodge" | "color-burn" | "linear-burn" | "linear-dodge" | "linear-light" | "hard-light" | "soft-light" | "pin-light" | "difference" | "exclusion" | "overlay" | "saturation" | "color" | "luminosity" | "normal-npm" | "add-npm" | "screen-npm" | "none" | "subtract" | "divide" | "vivid-light" | "hard-mix" | "negation" | "min" | "max";
interface ShaderBase {
/** The WebGL program used by the WebGL renderer. */
glProgram?: GlProgram;
/** The WebGPU program used by the WebGPU renderer. */
gpuProgram?: GpuProgram;
/**
* A number that uses two bits on whether the shader is compatible with the WebGL renderer and/or the WebGPU renderer.
* 0b00 - not compatible with either
* 0b01 - compatible with WebGL
* 0b10 - compatible with WebGPU
* This is automatically set based on if a {@link GlProgram} or {@link GpuProgram} is provided.
*/
compatibleRenderers?: number;
}
interface ShaderWithResourcesDescriptor {
/**
* A key value of uniform resources used by the shader.
* Under the hood pixi will look at the provided shaders and figure out where
* the resources are mapped. Its up to you to make sure the resource key
* matches the uniform name in the webGPU program. WebGL is a little more forgiving!
*/
resources?: Record;
}
type GlShaderFromWith = {
gpu?: GpuProgramOptions;
gl: GlProgramOptions;
};
type GpuShaderFromWith = {
gpu: GpuProgramOptions;
gl?: GlProgramOptions;
};
/**
* Defines a size with a width and a height.
*/
export interface Size {
/** The width. */
width: number;
/** The height. */
height: number;
}
interface LocalBoundsCacheData {
data: number[];
index: number;
didChange: boolean;
localBounds: Bounds;
}
/**
* Options for configuring a Sprite instance. Defines the texture, anchor point, and rendering behavior.
* @example
* ```ts
* // Create a basic sprite with texture
* const sprite = new Sprite({
* texture: Texture.from('sprite.png')
* });
*
* // Create a centered sprite with rounded position
* const centeredSprite = new Sprite({
* texture: Texture.from('centered.png'),
* anchor: 0.5, // Center point
* roundPixels: true, // Crisp rendering
* x: 100, // Position from ViewContainerOptions
* y: 100
* });
*
* // Create a sprite with specific anchor points
* const anchoredSprite = new Sprite({
* texture: Texture.from('corner.png'),
* anchor: {
* x: 1, // Right-aligned
* y: 0 // Top-aligned
* }
* });
* ```
*/
export interface SpriteOptions extends PixiMixins.SpriteOptions, ViewContainerOptions {
/**
* The texture to use for the sprite. If not provided, uses Texture.EMPTY
* @default Texture.EMPTY
* @example
* ```ts
* // Create a sprite with a texture
* const sprite = new Sprite({
* texture: Texture.from('path/to/image.png')
* });
* // Update the texture later
* sprite.texture = Texture.from('path/to/another-image.png');
* ```
*/
texture?: Texture;
/**
* The anchor point of the sprite (0-1 range).
* Controls the origin point for rotation, scaling, and positioning.
* Can be a number for uniform anchor or a PointData for separate x/y values.
* @default 0
* @example
* ```ts
* // Centered anchor
* anchor: 0.5
* // Separate x/y anchor
* anchor: { x: 0.5, y: 0.5 }
* // Right-aligned anchor
* anchor: { x: 1, y: 0 }
* ```
*/
anchor?: PointData | number;
/**
* Whether or not to round the x/y position to whole pixels.
* Useful for crisp pixel art style rendering.
* @default false
* @example
* ```ts
* const sprite = new Sprite({
* texture: Texture.from('sprite.png'),
* roundPixels: true // Ensures crisp rendering
* });
* ```
*/
roundPixels?: boolean;
}
export interface Sprite extends PixiMixins.Sprite, ViewContainer {
}
/**
* The Sprite object is one of the most important objects in PixiJS. It is a
* drawing item that can be added to a scene and rendered to the screen.
* Sprites can display images, handle input events, and be transformed in various ways.
* @example
* ```ts
* // Create a sprite directly from an image path
* const sprite = Sprite.from('assets/image.png');
* sprite.position.set(100, 100);
* app.stage.addChild(sprite);
*
* // Create from a spritesheet (more efficient)
* const sheet = await Assets.load('assets/spritesheet.json');
* const sprite = new Sprite(sheet.textures['image.png']);
*
* // Create with specific options
* const configuredSprite = new Sprite({
* texture: Texture.from('sprite.png'),
* anchor: 0.5, // Center anchor point
* position: { x: 100, y: 100 },
* scale: { x: 2, y: 2 }, // Double size
* rotation: Math.PI / 4 // 45 degrees
* });
*
* // Animate sprite properties
* app.ticker.add(() => {
* sprite.rotation += 0.1; // Rotate
* sprite.scale.x = Math.sin(performance.now() / 1000) + 1; // Pulse scale
* });
* ```
*/
export declare class Sprite extends ViewContainer {
/**
* Creates a new sprite based on a source texture, image, video, or canvas element.
* This is a convenience method that automatically creates and manages textures.
* @example
* ```ts
* // Create from path or URL
* const sprite = Sprite.from('assets/image.png');
*
* // Create from existing texture
* const sprite = Sprite.from(texture);
*
* // Create from canvas
* const canvas = document.createElement('canvas');
* const sprite = Sprite.from(canvas, true); // Skip caching new texture
* ```
* @param source - The source to create the sprite from. Can be a path to an image, a texture,
* or any valid texture source (canvas, video, etc.)
* @param skipCache - Whether to skip adding to the texture cache when creating a new texture
* @returns A new sprite based on the source
*/
static from(source: Texture | TextureSourceLike, skipCache?: boolean): Sprite;
/**
* @param options - The options for creating the sprite.
*/
constructor(options?: SpriteOptions | Texture);
set texture(value: Texture);
/**
* The texture that is displayed by the sprite. When changed, automatically updates
* the sprite dimensions and manages texture event listeners.
* @example
* ```ts
* // Create sprite with texture
* const sprite = new Sprite({
* texture: Texture.from('sprite.png')
* });
*
* // Update texture
* sprite.texture = Texture.from('newSprite.png');
*
* // Use texture from spritesheet
* const sheet = await Assets.load('spritesheet.json');
* sprite.texture = sheet.textures['frame1.png'];
*
* // Reset to empty texture
* sprite.texture = Texture.EMPTY;
* ```
*/
get texture(): Texture;
/**
* The bounds of the sprite, taking into account the texture's trim area.
* @example
* ```ts
* const texture = new Texture({
* source: new TextureSource({ width: 300, height: 300 }),
* frame: new Rectangle(196, 66, 58, 56),
* trim: new Rectangle(4, 4, 58, 56),
* orig: new Rectangle(0, 0, 64, 64),
* rotate: 2,
* });
* const sprite = new Sprite(texture);
* const visualBounds = sprite.visualBounds;
* // console.log(visualBounds); // { minX: -4, maxX: 62, minY: -4, maxY: 60 }
*/
get visualBounds(): BoundsData;
/**
* Destroys this sprite renderable and optionally its texture.
* @param options - Options parameter. A boolean will act as if all options
* have been set to that value
* @example
* sprite.destroy();
* sprite.destroy(true);
* sprite.destroy({ texture: true, textureSource: true });
*/
destroy(options?: DestroyOptions): void;
/**
* The anchor sets the origin point of the sprite. The default value is taken from the {@link Texture}
* and passed to the constructor.
*
* - The default is `(0,0)`, this means the sprite's origin is the top left.
* - Setting the anchor to `(0.5,0.5)` means the sprite's origin is centered.
* - Setting the anchor to `(1,1)` would mean the sprite's origin point will be the bottom right corner.
*
* If you pass only single parameter, it will set both x and y to the same value as shown in the example below.
* @example
* ```ts
* // Center the anchor point
* sprite.anchor = 0.5; // Sets both x and y to 0.5
* sprite.position.set(400, 300); // Sprite will be centered at this position
*
* // Set specific x/y anchor points
* sprite.anchor = {
* x: 1, // Right edge
* y: 0 // Top edge
* };
*
* // Using individual coordinates
* sprite.anchor.set(0.5, 1); // Center-bottom
*
* // For rotation around center
* sprite.anchor.set(0.5);
* sprite.rotation = Math.PI / 4; // 45 degrees around center
*
* // For scaling from center
* sprite.anchor.set(0.5);
* sprite.scale.set(2); // Scales from center point
* ```
*/
get anchor(): ObservablePoint;
set anchor(value: PointData | number);
/**
* The width of the sprite, setting this will actually modify the scale to achieve the value set.
* @example
* ```ts
* // Set width directly
* sprite.width = 200;
* console.log(sprite.scale.x); // Scale adjusted to match width
*
* // Set width while preserving aspect ratio
* const ratio = sprite.height / sprite.width;
* sprite.width = 300;
* sprite.height = 300 * ratio;
*
* // For better performance when setting both width and height
* sprite.setSize(300, 400); // Avoids recalculating bounds twice
*
* // Reset to original texture size
* sprite.width = sprite.texture.orig.width;
* ```
*/
get width(): number;
set width(value: number);
/**
* The height of the sprite, setting this will actually modify the scale to achieve the value set.
* @example
* ```ts
* // Set height directly
* sprite.height = 150;
* console.log(sprite.scale.y); // Scale adjusted to match height
*
* // Set height while preserving aspect ratio
* const ratio = sprite.width / sprite.height;
* sprite.height = 200;
* sprite.width = 200 * ratio;
*
* // For better performance when setting both width and height
* sprite.setSize(300, 400); // Avoids recalculating bounds twice
*
* // Reset to original texture size
* sprite.height = sprite.texture.orig.height;
* ```
*/
get height(): number;
set height(value: number);
/**
* Retrieves the size of the Sprite as a [Size]{@link Size} object based on the texture dimensions and scale.
* This is faster than getting width and height separately as it only calculates the bounds once.
* @example
* ```ts
* // Basic size retrieval
* const sprite = new Sprite(Texture.from('sprite.png'));
* const size = sprite.getSize();
* console.log(`Size: ${size.width}x${size.height}`);
*
* // Reuse existing size object
* const reuseSize = { width: 0, height: 0 };
* sprite.getSize(reuseSize);
* ```
* @param out - Optional object to store the size in, to avoid allocating a new object
* @returns The size of the Sprite
*/
getSize(out?: Size): Size;
/**
* Sets the size of the Sprite to the specified width and height.
* This is faster than setting width and height separately as it only recalculates bounds once.
* @example
* ```ts
* // Basic size setting
* const sprite = new Sprite(Texture.from('sprite.png'));
* sprite.setSize(100, 200); // Width: 100, Height: 200
*
* // Set uniform size
* sprite.setSize(100); // Sets both width and height to 100
*
* // Set size with object
* sprite.setSize({
* width: 200,
* height: 300
* });
*
* // Reset to texture size
* sprite.setSize(
* sprite.texture.orig.width,
* sprite.texture.orig.height
* );
* ```
* @param value - This can be either a number or a {@link Size} object
* @param height - The height to set. Defaults to the value of `width` if not provided
*/
setSize(value: number | Optional, height?: number): void;
}
type OPTIONAL_SPACE = " " | "";
type FLOPS = T extends {
value: infer V;
} ? V : never;
interface System$1 {
extension: {
name: string;
};
defaultOptions?: any;
new (...args: any): any;
}
type SystemsWithExtensionList = System$1[];
type InstanceType$1 any> = T extends new (...args: any) => infer R ? R : any;
type NameType = T[number]["extension"]["name"];
type NotUnknown = T extends unknown ? keyof T extends never ? never : T : T;
type KnownProperties = {
[K in keyof T as NotUnknown extends never ? never : K]: T[K];
};
type FlattenOptions = T extends {
[K: string]: infer U;
} ? U : never;
type OptionsUnion = FlattenOptions>;
type DefaultOptionsTypes = {
[K in NameType]: Extract["defaultOptions"];
};
type SeparateOptions = KnownProperties>;
type UnionToIntersection = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
type MaskMode = "pushMaskBegin" | "pushMaskEnd" | "popMaskBegin" | "popMaskEnd";
declare class AlphaMaskEffect extends FilterEffect implements PoolItem {
constructor();
get sprite(): Sprite;
set sprite(value: Sprite);
get inverse(): boolean;
set inverse(value: boolean);
init: () => void;
}
interface MaskConversionTest {
test: (item: any) => boolean;
maskClass: new (item: any) => Effect & PoolItem;
}
type MaskMode$1 = "pushMaskBegin" | "pushMaskEnd" | "popMaskBegin" | "popMaskEnd";
interface EnsurePrecisionOptions {
requestedVertexPrecision: PRECISION;
requestedFragmentPrecision: PRECISION;
maxSupportedVertexPrecision: PRECISION;
maxSupportedFragmentPrecision: PRECISION;
}
interface AdvancedBlendInstruction extends Instruction {
renderPipeId: "blendMode";
blendMode: BLEND_MODES;
activeBlend: Renderable[];
}
declare const imageTypes: {
png: string;
jpg: string;
webp: string;
};
type Formats = keyof typeof imageTypes;
/**
* System for exporting content from a renderer. It provides methods to extract content as images,
* canvases, or raw pixel data. Available through `renderer.extract`.
* @example
* ```ts
* import { Application, Graphics } from 'pixi.js';
*
* // Create a new application
* const app = new Application();
* await app.init();
*
* // Draw something to extract
* const graphics = new Graphics()
* .circle(0, 0, 50)
* .fill(0xFF0000);
*
* // Basic extraction examples
* const image = await app.renderer.extract.image(graphics); // As HTMLImageElement
* const canvas = app.renderer.extract.canvas(graphics); // As Canvas
* const pixels = app.renderer.extract.pixels(graphics); // As pixel data
* const base64 = await app.renderer.extract.base64(graphics); // As base64 string
*
* // Advanced extraction with options
* const customImage = await app.renderer.extract.image({
* target: graphics,
* format: 'png',
* resolution: 2,
* frame: new Rectangle(0, 0, 100, 100),
* clearColor: '#00000000'
* });
*
* // Download content
* app.renderer.extract.download({
* target: graphics,
* filename: 'my-image.png'
* });
*
* // Debug visualization
* app.renderer.extract.log(graphics);
* ```
*
* Features:
* - Extract as various formats (PNG, JPEG, WebP)
* - Control output quality and resolution
* - Extract specific regions
* - Download extracted content
* - Debug visualization
*
* Common Use Cases:
* - Creating thumbnails
* - Saving game screenshots
* - Processing visual content
* - Debugging renders
* - Creating textures from rendered content
*
* Performance Considerations:
* - Extraction operations are relatively expensive
* - Consider caching results for frequently used content
* - Be mindful of resolution and format choices
* - Large extractions may impact performance
*/
export declare class ExtractSystem implements System {
/**
* Default options for image extraction.
* @example
* ```ts
* // Customize default options
* ExtractSystem.defaultImageOptions.format = 'webp';
* ExtractSystem.defaultImageOptions.quality = 0.8;
*
* // Use defaults
* const image = await renderer.extract.image(sprite);
* ```
*/
static defaultImageOptions: ImageOptions;
/** @param renderer - The renderer this System works for. */
constructor(renderer: Renderer);
/**
* Creates an HTMLImageElement from a display object or texture.
* @param options - Options for creating the image, or the target to extract
* @returns Promise that resolves with the generated HTMLImageElement
* @example
* ```ts
* // Basic usage with a sprite
* const sprite = new Sprite(texture);
* const image = await renderer.extract.image(sprite);
* document.body.appendChild(image);
*
* // Advanced usage with options
* const image = await renderer.extract.image({
* target: container,
* format: 'webp',
* quality: 0.8,
* frame: new Rectangle(0, 0, 100, 100),
* resolution: 2,
* clearColor: '#ff0000',
* antialias: true
* });
*
* // Extract directly from a texture
* const texture = Texture.from('myTexture.png');
* const image = await renderer.extract.image(texture);
* ```
*/
image(options: ExtractImageOptions | Container | Texture): Promise;
/**
* Converts the target into a base64 encoded string.
*
* This method works by first creating
* a canvas using `Extract.canvas` and then converting it to a base64 string.
* @param options - The options for creating the base64 string, or the target to extract
* @returns Promise that resolves with the base64 encoded string
* @example
* ```ts
* // Basic usage with a sprite
* const sprite = new Sprite(texture);
* const base64 = await renderer.extract.base64(sprite);
* console.log(base64); // data:image/png;base64,...
*
* // Advanced usage with options
* const base64 = await renderer.extract.base64({
* target: container,
* format: 'webp',
* quality: 0.8,
* frame: new Rectangle(0, 0, 100, 100),
* resolution: 2
* });
* ```
* @throws Will throw an error if the platform doesn't support any of:
* - ICanvas.toDataURL
* - ICanvas.toBlob
* - ICanvas.convertToBlob
*/
base64(options: ExtractImageOptions | Container | Texture): Promise;
/**
* Creates a Canvas element, renders the target to it and returns it.
* This method is useful for creating static images or when you need direct canvas access.
* @param options - The options for creating the canvas, or the target to extract
* @returns A Canvas element with the texture rendered on
* @example
* ```ts
* // Basic canvas extraction from a sprite
* const sprite = new Sprite(texture);
* const canvas = renderer.extract.canvas(sprite);
* document.body.appendChild(canvas);
*
* // Extract with custom region
* const canvas = renderer.extract.canvas({
* target: container,
* frame: new Rectangle(0, 0, 100, 100)
* });
*
* // Extract with high resolution
* const canvas = renderer.extract.canvas({
* target: sprite,
* resolution: 2,
* clearColor: '#ff0000'
* });
*
* // Extract directly from a texture
* const texture = Texture.from('myTexture.png');
* const canvas = renderer.extract.canvas(texture);
*
* // Extract with anti-aliasing
* const canvas = renderer.extract.canvas({
* target: graphics,
* antialias: true
* });
* ```
*/
canvas(options: ExtractOptions | Container | Texture): ICanvas;
/**
* Returns a one-dimensional array containing the pixel data of the entire texture in RGBA order,
* with integer values between 0 and 255 (inclusive).
* > [!NOE] The returned array is a flat Uint8Array where every 4 values represent RGBA
* @param options - The options for extracting the image, or the target to extract
* @returns One-dimensional Uint8Array containing the pixel data in RGBA format
* @example
* ```ts
* // Basic pixel extraction
* const sprite = new Sprite(texture);
* const pixels = renderer.extract.pixels(sprite);
* console.log(pixels[0], pixels[1], pixels[2], pixels[3]); // R,G,B,A values
*
* // Extract with custom region
* const pixels = renderer.extract.pixels({
* target: sprite,
* frame: new Rectangle(0, 0, 100, 100)
* });
*
* // Extract with high resolution
* const pixels = renderer.extract.pixels({
* target: sprite,
* resolution: 2
* });
* ```
*/
pixels(options: ExtractOptions | Container | Texture): GetPixelsOutput;
/**
* Creates a texture from a display object or existing texture.
*
* This is useful for creating
* reusable textures from rendered content or making copies of existing textures.
* > [!NOTE] The returned texture should be destroyed when no longer needed
* @param options - The options for creating the texture, or the target to extract
* @returns A new texture containing the extracted content
* @example
* ```ts
* // Basic texture extraction from a sprite
* const sprite = new Sprite(texture);
* const extractedTexture = renderer.extract.texture(sprite);
*
* // Extract with custom region
* const regionTexture = renderer.extract.texture({
* target: container,
* frame: new Rectangle(0, 0, 100, 100)
* });
*
* // Extract with high resolution
* const hiResTexture = renderer.extract.texture({
* target: sprite,
* resolution: 2,
* clearColor: '#ff0000'
* });
*
* // Create a new sprite from extracted texture
* const newSprite = new Sprite(
* renderer.extract.texture({
* target: graphics,
* antialias: true
* })
* );
*
* // Clean up when done
* extractedTexture.destroy(true);
* ```
*/
texture(options: ExtractOptions | Container | Texture): Texture;
/**
* Extracts and downloads content from the renderer as an image file.
* This is a convenient way to save screenshots or export rendered content.
* > [!NOTE] The download will use PNG format regardless of the filename extension
* @param options - The options for downloading and extracting the image, or the target to extract
* @example
* ```ts
* // Basic download with default filename
* const sprite = new Sprite(texture);
* renderer.extract.download(sprite); // Downloads as 'image.png'
*
* // Download with custom filename
* renderer.extract.download({
* target: sprite,
* filename: 'screenshot.png'
* });
*
* // Download with custom region
* renderer.extract.download({
* target: container,
* filename: 'region.png',
* frame: new Rectangle(0, 0, 100, 100)
* });
*
* // Download with high resolution and background
* renderer.extract.download({
* target: stage,
* filename: 'hd-screenshot.png',
* resolution: 2,
* clearColor: '#ff0000'
* });
*
* // Download with anti-aliasing
* renderer.extract.download({
* target: graphics,
* filename: 'smooth.png',
* antialias: true
* });
* ```
*/
download(options: ExtractDownloadOptions | Container | Texture): void;
destroy(): void;
}
interface UniformParserDefinition {
type: UNIFORM_TYPES;
test(data: UniformData): boolean;
ubo?: string;
uboWgsl?: string;
uboStd40?: string;
uniform?: string;
}
declare const DefaultWebGPUSystems: (typeof BackgroundSystem | typeof GenerateTextureSystem | typeof GlobalUniformSystem | typeof HelloSystem | typeof ViewSystem | typeof RenderGroupSystem | typeof TextureGCSystem | typeof ExtractSystem | typeof RendererInitHook | typeof RenderableGCSystem | typeof SchedulerSystem | typeof GpuUboSystem | typeof GpuEncoderSystem | typeof GpuDeviceSystem | typeof GpuLimitsSystem | typeof GpuBufferSystem | typeof GpuTextureSystem | typeof GpuRenderTargetSystem | typeof GpuShaderSystem | typeof GpuStateSystem | typeof PipelineSystem | typeof GpuColorMaskSystem | typeof GpuStencilSystem | typeof BindGroupSystem)[];
declare const DefaultWebGPUPipes: (typeof BlendModePipe | typeof BatcherPipe | typeof SpritePipe | typeof RenderGroupPipe | typeof AlphaMaskPipe | typeof StencilMaskPipe | typeof ColorMaskPipe | typeof CustomRenderPipe | typeof GpuUniformBatchPipe)[];
/**
* The default WebGPU systems. These are the systems that are added by default to the WebGPURenderer.
*/
export type WebGPUSystems = ExtractSystemTypes & PixiMixins.RendererSystems & PixiMixins.WebGPUSystems;
/**
* Options for WebGPURenderer.
*/
export interface WebGPUOptions extends SharedRendererOptions, ExtractRendererOptions, PixiMixins.WebGPUOptions {
}
export interface WebGPURenderer extends AbstractRenderer, WebGPUSystems {
}
/**
* The WebGPU PixiJS Renderer. This renderer allows you to use the next-generation graphics API, WebGPU.
* ```ts
* // Create a new renderer
* const renderer = new WebGPURenderer();
* await renderer.init();
*
* // Add the renderer to the stage
* document.body.appendChild(renderer.canvas);
*
* // Create a new stage
* const stage = new Container();
*
* // Render the stage
* renderer.render(stage);
* ```
*
* You can use {@link autoDetectRenderer} to create a renderer that will automatically detect the best
* renderer for the environment.
* ```ts
* import { autoDetectRenderer } from 'pixi.js';
* // Create a new renderer
* const renderer = await autoDetectRenderer();
* ```
*
* The renderer is composed of systems that manage specific tasks. The following systems are added by default
* whenever you create a WebGPU renderer:
*
* | WebGPU Core Systems | Systems that are specific to the WebGL renderer |
* | ---------------------------------------- | ----------------------------------------------------------------------------- |
* | {@link GpuUboSystem} | This manages WebGPU uniform buffer objects feature for shaders |
* | {@link GpuEncoderSystem} | This manages the WebGPU command encoder |
* | {@link GpuDeviceSystem} | This manages the WebGPU Device and its extensions |
* | {@link GpuBufferSystem} | This manages buffers and their GPU resources, keeps everything in sync |
* | {@link GpuTextureSystem} | This manages textures and their GPU resources, keeps everything in sync |
* | {@link GpuRenderTargetSystem} | This manages what we render too. For example the screen, or another texture |
* | {@link GpuShaderSystem} | This manages shaders, programs that run on the GPU to output lovely pixels |
* | {@link GpuStateSystem} | This manages the state of the WebGPU Pipelines. eg the various flags that can be set blend modes / depthTesting etc |
* | {@link PipelineSystem} | This manages the WebGPU pipelines, used for rendering |
* | {@link GpuColorMaskSystem} | This manages the color mask. Used for color masking |
* | {@link GpuStencilSystem} | This manages the stencil buffer. Used primarily for masking |
* | {@link BindGroupSystem} | This manages the WebGPU bind groups. this is how data is bound to a shader when rendering |
*
* The breadth of the API surface provided by the renderer is contained within these systems.
* @property {GpuUboSystem} ubo - UboSystem instance.
* @property {GpuEncoderSystem} encoder - EncoderSystem instance.
* @property {GpuDeviceSystem} device - DeviceSystem instance.
* @property {GpuBufferSystem} buffer - BufferSystem instance.
* @property {GpuTextureSystem} texture - TextureSystem instance.
* @property {GpuRenderTargetSystem} renderTarget - RenderTargetSystem instance.
* @property {GpuShaderSystem} shader - ShaderSystem instance.
* @property {GpuStateSystem} state - StateSystem instance.
* @property {PipelineSystem} pipeline - PipelineSystem instance.
* @property {GpuColorMaskSystem} colorMask - ColorMaskSystem instance.
* @property {GpuStencilSystem} stencil - StencilSystem instance.
* @property {BindGroupSystem} bindGroup - BindGroupSystem instance.
*/
export declare class WebGPURenderer extends AbstractRenderer implements WebGPUSystems {
/** The WebGPU Device. */
gpu: GPU$1;
constructor();
}
/**
* Automatically determines the most appropriate renderer for the current environment.
*
* The function will prioritize the WebGL renderer as it is the most tested safe API to use.
* In the near future as WebGPU becomes more stable and ubiquitous, it will be prioritized over WebGL.
*
* The selected renderer's code is then dynamically imported to optimize
* performance and minimize the initial bundle size.
*
* To maximize the benefits of dynamic imports, it's recommended to use a modern bundler
* that supports code splitting. This will place the renderer code in a separate chunk,
* which is loaded only when needed.
* @example
*
* // create a renderer
* const renderer = await autoDetectRenderer({
* width: 800,
* height: 600,
* antialias: true,
* });
*
* // custom for each renderer
* const renderer = await autoDetectRenderer({
* width: 800,
* height: 600,
* webgpu:{
* antialias: true,
* backgroundColor: 'red'
* },
* webgl:{
* antialias: true,
* backgroundColor: 'green'
* }
* });
* @param options - A partial configuration object based on the `AutoDetectOptions` type.
* @returns A Promise that resolves to an instance of the selected renderer.
*/
export declare function autoDetectRenderer(options: Partial): Promise;
/**
* Application options supplied to the {@link Application#init} method.
* These options configure how your PixiJS application behaves.
* @example
* ```js
* import { Application } from 'pixi.js';
*
* const app = new Application();
*
* // Initialize with common options
* await app.init({
* // Rendering options
* width: 800, // Canvas width
* height: 600, // Canvas height
* backgroundColor: 0x1099bb, // Background color
* antialias: true, // Enable antialiasing
* resolution: window.devicePixelRatio, // Screen resolution
*
* // Performance options
* autoStart: true, // Auto-starts the render loop
* sharedTicker: true, // Use shared ticker for better performance
*
* // Automatic resize options
* resizeTo: window, // Auto-resize to window
* autoDensity: true, // Adjust for device pixel ratio
*
* // Advanced options
* preference: 'webgl', // Renderer preference ('webgl' or 'webgpu')
* powerPreference: 'high-performance' // GPU power preference
* });
* ```
*/
export interface ApplicationOptions extends AutoDetectOptions, PixiMixins.ApplicationOptions {
}
export interface Application extends PixiMixins.Application {
}
/**
* Convenience class to create a new PixiJS application.
*
* The Application class is the main entry point for creating a PixiJS application. It handles the setup of all core
* components needed to start rendering and managing your game or interactive experience.
*
* Key features:
* - Automatically creates and manages the renderer
* - Provides a stage (root container) for your display objects
* - Handles canvas creation and management
* - Supports plugins for extending functionality
* - {@link ResizePlugin} for automatic resizing
* - {@link TickerPlugin} for managing frame updates
* - {@link CullerPlugin} for culling off-screen objects
* @example
* ```js
* import { Assets, Application, Sprite } from 'pixi.js';
*
* // Create a new application
* const app = new Application();
*
* // Initialize with options
* await app.init({
* width: 800, // Canvas width
* height: 600, // Canvas height
* backgroundColor: 0x1099bb, // Background color
* antialias: true, // Enable antialiasing
* resolution: 1, // Resolution / device pixel ratio
* preference: 'webgl', // or 'webgpu' // Renderer preference
* });
*
* // Add the canvas to your webpage
* document.body.appendChild(app.canvas);
*
* // Start adding content to your application
* const texture - await Assets.load('your-image.png');
* const sprite = new Sprite(texture);
* app.stage.addChild(sprite);
* ```
* > [!IMPORTANT] From PixiJS v8.0.0, the application must be initialized using the async `init()` method
* > rather than passing options to the constructor.
*/
export declare class Application {
/**
* The root display container for your application.
* All visual elements should be added to this container or its children.
* @example
* ```js
* // Create a sprite and add it to the stage
* const sprite = Sprite.from('image.png');
* app.stage.addChild(sprite);
*
* // Create a container for grouping objects
* const container = new Container();
* app.stage.addChild(container);
* ```
*/
stage: Container;
/**
* The renderer instance that handles all drawing operations.
*
* Unless specified, it will automatically create a WebGL renderer if available.
* If WebGPU is available and the `preference` is set to `webgpu`, it will create a WebGPU renderer.
* @example
* ```js
* // Create a new application
* const app = new Application();
* await app.init({
* width: 800,
* height: 600,
* preference: 'webgl', // or 'webgpu'
* });
*
* // Access renderer properties
* console.log(app.renderer.width, app.renderer.height);
* ```
*/
renderer: R;
/** Create new Application instance */
constructor();
/** @deprecated since 8.0.0 */
constructor(options?: Partial);
/**
* Initializes the PixiJS application with the specified options.
*
* This method must be called after creating a new Application instance.
* @param options - Configuration options for the application and renderer
* @returns A promise that resolves when initialization is complete
* @example
* ```js
* const app = new Application();
*
* // Initialize with custom options
* await app.init({
* width: 800,
* height: 600,
* backgroundColor: 0x1099bb,
* preference: 'webgl', // or 'webgpu'
* });
* ```
*/
init(options?: Partial): Promise;
/**
* Renders the current stage to the screen.
*
* When using the default setup with {@link TickerPlugin} (enabled by default), you typically don't need to call
* this method directly as rendering is handled automatically.
*
* Only use this method if you've disabled the {@link TickerPlugin} or need custom
* render timing control.
* @example
* ```js
* // Example 1: Default setup (TickerPlugin handles rendering)
* const app = new Application();
* await app.init();
* // No need to call render() - TickerPlugin handles it
*
* // Example 2: Custom rendering loop (if TickerPlugin is disabled)
* const app = new Application();
* await app.init({ autoStart: false }); // Disable automatic rendering
*
* function animate() {
* app.render();
* requestAnimationFrame(animate);
* }
* animate();
* ```
*/
render(): void;
/**
* Reference to the renderer's canvas element. This is the HTML element
* that displays your application's graphics.
* @type {HTMLCanvasElement}
* @example
* ```js
* // Create a new application
* const app = new Application();
* // Initialize the application
* await app.init({...});
* // Add canvas to the page
* document.body.appendChild(app.canvas);
*
* // Access the canvas directly
* console.log(app.canvas); // HTMLCanvasElement
* ```
*/
get canvas(): R["canvas"];
/**
* Reference to the renderer's canvas element.
* @type {HTMLCanvasElement}
* @deprecated since 8.0.0
*/
get view(): R["canvas"];
/**
* Reference to the renderer's screen rectangle. This represents the visible area of your application.
*
* It's commonly used for:
* - Setting filter areas for full-screen effects
* - Defining hit areas for screen-wide interaction
* - Determining the visible bounds of your application
* @example
* ```js
* // Use as filter area for a full-screen effect
* const blurFilter = new BlurFilter();
* sprite.filterArea = app.screen;
*
* // Use as hit area for screen-wide interaction
* const screenSprite = new Sprite();
* screenSprite.hitArea = app.screen;
*
* // Get screen dimensions
* console.log(app.screen.width, app.screen.height);
* ```
*/
get screen(): Rectangle;
/**
* Destroys the application and all of its resources.
*
* This method should be called when you want to completely
* clean up the application and free all associated memory.
* @param rendererDestroyOptions - Options for destroying the renderer:
* - `false` or `undefined`: Preserves the canvas element (default)
* - `true`: Removes the canvas element
* - `{ removeView: boolean }`: Object with removeView property to control canvas removal
* @param options - Options for destroying the application:
* - `false` or `undefined`: Basic cleanup (default)
* - `true`: Complete cleanup including children
* - Detailed options object:
* - `children`: Remove children
* - `texture`: Destroy textures
* - `textureSource`: Destroy texture sources
* - `context`: Destroy WebGL context
* @example
* ```js
* // Basic cleanup
* app.destroy();
*
* // Remove canvas and do complete cleanup
* app.destroy(true, true);
*
* // Remove canvas with explicit options
* app.destroy({ removeView: true }, true);
*
* // Detailed cleanup with specific options
* app.destroy(
* { removeView: true },
* {
* children: true,
* texture: true,
* textureSource: true,
* context: true
* }
* );
* ```
* > [!WARNING] After calling destroy, the application instance should no longer be used.
* > All properties will be null and further operations will throw errors.
*/
destroy(rendererDestroyOptions?: RendererDestroyOptions, options?: DestroyOptions): void;
}
declare global {
var __PIXI_APP_INIT__: undefined | ((arg: Application | Renderer, version: string) => void);
var __PIXI_RENDERER_INIT__: undefined | ((arg: Application | Renderer, version: string) => void);
}
/**
* The options for rendering a view.
*/
export interface RenderOptions extends ClearOptions {
/** The container to render. */
container: Container;
/** the transform to apply to the container. */
transform?: Matrix;
}
/**
* Options for destroying the renderer.
* This can be a boolean or an object.
*/
export type RendererDestroyOptions = TypeOrBool;
declare const defaultRunners: readonly [
"init",
"destroy",
"contextChange",
"resolutionChange",
"resetState",
"renderEnd",
"renderStart",
"render",
"update",
"postrender",
"prerender"
];
type DefaultRunners = typeof defaultRunners[number];
type Runners = {
[key in DefaultRunners]: SystemRunner;
} & {
[K: ({} & string) | ({} & symbol)]: SystemRunner;
};
declare const DefaultWebGLSystems: (typeof BackgroundSystem | typeof GenerateTextureSystem | typeof GlobalUniformSystem | typeof HelloSystem | typeof ViewSystem | typeof RenderGroupSystem | typeof TextureGCSystem | typeof ExtractSystem | typeof RendererInitHook | typeof RenderableGCSystem | typeof SchedulerSystem | typeof GlUboSystem | typeof GlBackBufferSystem | typeof GlContextSystem | typeof GlLimitsSystem | typeof GlBufferSystem | typeof GlTextureSystem | typeof GlRenderTargetSystem | typeof GlGeometrySystem | typeof GlUniformGroupSystem | typeof GlShaderSystem | typeof GlEncoderSystem | typeof GlStateSystem | typeof GlStencilSystem | typeof GlColorMaskSystem)[];
declare const DefaultWebGLPipes: (typeof BlendModePipe | typeof BatcherPipe | typeof SpritePipe | typeof RenderGroupPipe | typeof AlphaMaskPipe | typeof StencilMaskPipe | typeof ColorMaskPipe | typeof CustomRenderPipe)[];
/**
* The default WebGL renderer, uses WebGL2 contexts.
*/
export type WebGLSystems = ExtractSystemTypes & PixiMixins.RendererSystems & PixiMixins.WebGLSystems;
/**
* Options for WebGLRenderer.
*/
export interface WebGLOptions extends SharedRendererOptions, ExtractRendererOptions, PixiMixins.WebGLOptions {
}
/**
* The default WebGL renderer, uses WebGL2 contexts.
*/
export interface WebGLRenderer extends AbstractRenderer, WebGLSystems {
}
/**
* The WebGL PixiJS Renderer. This renderer allows you to use the most common graphics API, WebGL (and WebGL2).
*
* ```ts
* // Create a new renderer
* const renderer = new WebGLRenderer();
* await renderer.init();
*
* // Add the renderer to the stage
* document.body.appendChild(renderer.canvas);
*
* // Create a new stage
* const stage = new Container();
*
* // Render the stage
* renderer.render(stage);
* ```
*
* You can use {@link autoDetectRenderer} to create a renderer that will automatically detect the best
* renderer for the environment.
*
*
* ```ts
* // Create a new renderer
* const renderer = await rendering.autoDetectRenderer({
* preference:'webgl',
* });
* ```
*
* The renderer is composed of systems that manage specific tasks. The following systems are added by default
* whenever you create a WebGL renderer:
*
* | WebGL Core Systems | Systems that are specific to the WebGL renderer |
* | ------------------------------------------- | ----------------------------------------------------------------------------- |
* | {@link GlUboSystem} | This manages WebGL2 uniform buffer objects feature for shaders |
* | {@link GlBackBufferSystem} | manages the back buffer, used so that we can pixi can pixels from the screen |
* | {@link GlContextSystem} | This manages the WebGL context and its extensions |
* | {@link GlBufferSystem} | This manages buffers and their GPU resources, keeps everything in sync |
* | {@link GlTextureSystem} | This manages textures and their GPU resources, keeps everything in sync |
* | {@link GlRenderTargetSystem} | This manages what we render too. For example the screen, or another texture |
* | {@link GlGeometrySystem} | This manages geometry, used for drawing meshes via the GPU |
* | {@link GlUniformGroupSystem} | This manages uniform groups. Syncing shader properties with the GPU |
* | {@link GlShaderSystem} | This manages shaders, programs that run on the GPU to output lovely pixels |
* | {@link GlEncoderSystem} | This manages encoders, a WebGPU Paradigm, use it to draw a mesh + shader |
* | {@link GlStateSystem} | This manages the state of the WebGL context. eg the various flags that can be set blend modes / depthTesting etc |
* | {@link GlStencilSystem} | This manages the stencil buffer. Used primarily for masking |
* | {@link GlColorMaskSystem} | This manages the color mask. Used for color masking |
*
* The breadth of the API surface provided by the renderer is contained within these systems.
* @property {GlUboSystem} ubo - UboSystem instance.
* @property {GlBackBufferSystem} backBuffer - BackBufferSystem instance.
* @property {GlContextSystem} context - ContextSystem instance.
* @property {GlBufferSystem} buffer - BufferSystem instance.
* @property {GlTextureSystem} texture - TextureSystem instance.
* @property {GlRenderTargetSystem} renderTarget - RenderTargetSystem instance.
* @property {GlGeometrySystem} geometry - GeometrySystem instance.
* @property {GlUniformGroupSystem} uniformGroup - UniformGroupSystem instance.
* @property {GlShaderSystem} shader - ShaderSystem instance.
* @property {GlEncoderSystem} encoder - EncoderSystem instance.
* @property {GlStateSystem} state - StateSystem instance.
* @property {GlStencilSystem} stencil - StencilSystem instance.
* @property {GlColorMaskSystem} colorMask - ColorMaskSystem instance.
*/
export declare class WebGLRenderer extends AbstractRenderer implements WebGLSystems {
gl: GlRenderingContext;
constructor();
}
/**
* A generic renderer that can be either a WebGL or WebGPU renderer.
*/
export type Renderer = WebGLRenderer | WebGPURenderer;
/**
* Options for the renderer.
*/
export interface RendererOptions extends WebGLOptions, WebGPUOptions {
}
export interface ViewContainer extends PixiMixins.ViewContainer, Container {
_gpuData: Record;
}
/**
* Options for configuring a RenderLayer. A RenderLayer allows control over rendering order
* independent of the scene graph hierarchy.
* @example
* ```ts
* // Basic layer with automatic sorting
* const layer = new RenderLayer({
* sortableChildren: true
* });
*
* // Layer with custom sort function
* const customLayer = new RenderLayer({
* sortableChildren: true,
* sortFunction: (a, b) => {
* // Sort by y position
* return a.position.y - b.position.y;
* }
* });
*
* // Add objects to layer while maintaining scene graph parent
* const sprite = new Sprite(texture);
* container.addChild(sprite); // Add to scene graph
* layer.attach(sprite); // Add to render layer
*
* // Manual sorting when needed
* const manualLayer = new RenderLayer({
* sortableChildren: false
* });
* manualLayer.attach(sprite1, sprite2);
* manualLayer.sortRenderLayerChildren(); // Sort manually
* ```
*/
export interface RenderLayerOptions {
/**
* If true, the layer's children will be sorted by zIndex before rendering.
* If false, you can manually sort the children using sortRenderLayerChildren when needed.
* @default false
* @example
* ```ts
* const layer = new RenderLayer({
* sortableChildren: true // Automatically sorts children by zIndex
* });
* ```
*/
sortableChildren?: boolean;
/**
* Custom sort function to sort layer children. Default sorts by zIndex.
* @param a - First container to compare
* @param b - Second container to compare
* @returns Negative if a should render before b, positive if b should render before a
* @example
* ```ts
* const layer = new RenderLayer({
* sortFunction: (a, b) => {
* // Sort by y position
* return a.position.y - b.position.y;
* }
* });
* ```
* @default (a, b) => a.zIndex - b.zIndex
*/
sortFunction?: (a: Container, b: Container) => number;
}
type ContainerKeys = keyof Container;
type PartialContainerKeys = Exclude;
declare class RenderLayerClass extends Container {
/**
* Default options for RenderLayer instances. These options control the sorting behavior
* of objects within the render layer.
* @example
* ```ts
* // Create a custom render layer with modified default options
* RenderLayer.defaultOptions = {
* sortableChildren: true,
* sortFunction: (a, b) => a.y - b.y // Sort by vertical position
* };
*
* // All new render layers will use these defaults
* const layer1 = new RenderLayer();
* // layer1 will have sortableChildren = true
* ```
* @property {boolean} sortableChildren -
* @property {Function} sortFunction -
*/
static defaultOptions: RenderLayerOptions;
/** Function used to sort layer children if sortableChildren is true */
sortFunction: (a: Container, b: Container) => number;
/**
* The list of objects that this layer is responsible for rendering. Objects in this list maintain
* their original parent in the scene graph but are rendered as part of this layer.
* @example
* ```ts
* const layer = new RenderLayer();
* const sprite = new Sprite(texture);
*
* // Add sprite to scene graph for transforms
* container.addChild(sprite);
*
* // Add to layer for render order control
* layer.attach(sprite);
* console.log(layer.renderLayerChildren.length); // 1
*
* // Access objects in the layer
* layer.renderLayerChildren.forEach(child => {
* console.log('Layer child:', child);
* });
*
* // Check if object is in layer
* const isInLayer = layer.renderLayerChildren.includes(sprite);
*
* // Clear all objects from layer
* layer.detachAll();
* console.log(layer.renderLayerChildren.length); // 0
* ```
*/
renderLayerChildren: Container[];
/**
* Creates a new RenderLayer instance
* @param options - Configuration options for the RenderLayer
* @param {boolean} [options.sortableChildren=false] - If true, layer children will be automatically sorted each render
* @param {Function} [options.sortFunction] - Custom function to sort layer children. Default sorts by zIndex
*/
constructor(options?: RenderLayerOptions);
/**
* Adds one or more Containers to this render layer. The Containers will be rendered as part of this layer
* while maintaining their original parent in the scene graph.
*
* If the Container already belongs to a layer, it will be removed from the old layer before being added to this one.
* @example
* ```ts
* const layer = new RenderLayer();
* const container = new Container();
* const sprite1 = new Sprite(texture1);
* const sprite2 = new Sprite(texture2);
*
* // Add sprites to scene graph for transforms
* container.addChild(sprite1, sprite2);
*
* // Add sprites to layer for render order control
* layer.attach(sprite1, sprite2);
*
* // Add single sprite with type checking
* const typedSprite = layer.attach(new Sprite(texture3));
* typedSprite.tint = 'red';
*
* // Automatically removes from previous layer if needed
* const otherLayer = new RenderLayer();
* otherLayer.attach(sprite1); // Removes from previous layer
* ```
* @param children - The Container(s) to add to this layer. Can be any Container or array of Containers.
* @returns The first child that was added, for method chaining
*/
attach(...children: U): U[0];
/**
* Removes one or more Containers from this render layer. The Containers will maintain their
* original parent in the scene graph but will no longer be rendered as part of this layer.
* @example
* ```ts
* const layer = new RenderLayer();
* const container = new Container();
* const sprite1 = new Sprite(texture1);
* const sprite2 = new Sprite(texture2);
*
* // Add sprites to scene graph and layer
* container.addChild(sprite1, sprite2);
* layer.attach(sprite1, sprite2);
*
* // Remove single sprite from layer
* layer.detach(sprite1);
* // sprite1 is still child of container but not rendered in layer
*
* // Remove multiple sprites at once
* const otherLayer = new RenderLayer();
* otherLayer.attach(sprite3, sprite4);
* otherLayer.detach(sprite3, sprite4);
*
* // Type-safe detachment
* const typedSprite = layer.detach(spriteInLayer);
* typedSprite.texture = newTexture; // TypeScript knows this is a Sprite
* ```
* @param children - The Container(s) to remove from this layer
* @returns The first child that was removed, for method chaining
*/
detach(...children: U): U[0];
/**
* Removes all objects from this render layer. Objects will maintain their
* original parent in the scene graph but will no longer be rendered as part of this layer.
* @example
* ```ts
* const layer = new RenderLayer();
* const container = new Container();
*
* // Add multiple sprites to scene graph and layer
* const sprites = [
* new Sprite(texture1),
* new Sprite(texture2),
* new Sprite(texture3)
* ];
*
* container.addChild(...sprites); // Add to scene graph
* layer.attach(...sprites); // Add to render layer
*
* // Later, remove all sprites from layer at once
* layer.detachAll();
* console.log(layer.renderLayerChildren.length); // 0
* console.log(container.children.length); // 3 (still in scene graph)
* ```
* @returns The RenderLayer instance for method chaining
*/
detachAll(): void;
/**
* Sort the layer's children using the defined sort function. This method allows manual sorting
* of layer children and is automatically called during rendering if sortableChildren is true.
* @example
* ```ts
* const layer = new RenderLayer();
*
* // Add multiple sprites at different depths
* const sprite1 = new Sprite(texture);
* const sprite2 = new Sprite(texture);
* const sprite3 = new Sprite(texture);
*
* sprite1.zIndex = 3;
* sprite2.zIndex = 1;
* sprite3.zIndex = 2;
*
* layer.attach(sprite1, sprite2, sprite3);
*
* // Manual sorting with default zIndex sort
* layer.sortRenderLayerChildren();
* // Order is now: sprite2 (1), sprite3 (2), sprite1 (3)
*
* // Custom sort by y position
* layer.sortFunction = (a, b) => a.y - b.y;
* layer.sortRenderLayerChildren();
*
* // Automatic sorting
* layer.sortableChildren = true; // Will sort each render
* ```
* @returns The RenderLayer instance for method chaining
*/
sortRenderLayerChildren(): void;
}
/**
* The RenderLayer API provides a way to control the rendering order of objects independently
* of their logical parent-child relationships in the scene graph.
* This allows developers to decouple how objects are transformed
* (via their logical parent) from how they are rendered on the screen.
*
* ### Key Concepts
*
* #### RenderLayers Control Rendering Order:
* - RenderLayers define where in the render stack objects are drawn,
* but they do not affect an object's transformations (e.g., position, scale, rotation) or logical hierarchy.
* - RenderLayers can be added anywhere in the scene graph.
*
* #### Logical Parenting Remains Unchanged:
* - Objects still have a logical parent for transformations via addChild.
* - Assigning an object to a layer does not reparent it.
*
* #### Explicit Control:
* - Developers assign objects to layers using renderLayer.add and remove them using renderLayer.remove.
* ---
* ### API Details
*
* #### 1. Creating a RenderLayer
* A RenderLayer is a lightweight object responsible for controlling render order.
* It has no children or transformations of its own
* but can be inserted anywhere in the scene graph to define its render position.
* ```js
* const layer = new RenderLayer();
* app.stage.addChild(layer); // Insert the layer into the scene graph
* ```
*
* #### 2. Adding Objects to a Layer
* Use renderLayer.add to assign an object to a layer.
* This overrides the object's default render order defined by its logical parent.
* ```js
* const rect = new Graphics();
* container.addChild(rect); // Add to logical parent
* layer.attach(rect); // Control render order via the layer
* ```
*
* #### 3. Removing Objects from a Layer
* To stop an object from being rendered in the layer, use remove.
* ```js
* layer.remove(rect); // Stop rendering rect via the layer
* ```
* When an object is removed from its logical parent (removeChild), it is automatically removed from the layer.
*
* #### 4. Re-Adding Objects to Layers
* If an object is re-added to a logical parent, it does not automatically reassign itself to the layer.
* Developers must explicitly reassign it.
* ```js
* container.addChild(rect); // Logical parent
* layer.attach(rect); // Explicitly reassign to the layer
* ```
*
* #### 5. Layer Position in Scene Graph
* A layer's position in the scene graph determines its render priority relative to other layers and objects.
* Layers can be inserted anywhere in the scene graph.
* ```js
* const backgroundLayer = new RenderLayer();
* const uiLayer = new RenderLayer();
*
* app.stage.addChild(backgroundLayer);
* app.stage.addChild(world);
* app.stage.addChild(uiLayer);
* ```
* This is a new API and therefore considered experimental at this stage.
* While the core is pretty robust, there are still a few tricky issues we need to tackle.
* However, even with the known issues below, we believe this API is incredibly useful!
*
* Known issues:
* - Interaction may not work as expected since hit testing does not account for the visual render order created by layers.
* For example, if an object is visually moved to the front via a layer, hit testing will still use its original position.
* - RenderLayers and their children must all belong to the same renderGroup to work correctly
*/
export declare const RenderLayer: new (options?: RenderLayerOptions) => IRenderLayer;
/**
* The type of child that can be added to a {@link Container}.
* This is a generic type that extends the {@link Container} class.
*/
export type ContainerChild = Container;
/**
* Events that can be emitted by a Container. These events provide lifecycle hooks and notifications
* for container state changes.
* @example
* ```ts
* import { Container, Sprite } from 'pixi.js';
*
* // Setup container with event listeners
* const container = new Container();
*
* // Listen for child additions
* container.on('childAdded', (child, container, index) => {
* console.log(`Child added at index ${index}:`, child);
* });
*
* // Listen for child removals
* container.on('childRemoved', (child, container, index) => {
* console.log(`Child removed from index ${index}:`, child);
* });
*
* // Listen for when container is added to parent
* container.on('added', (parent) => {
* console.log('Added to parent:', parent);
* });
*
* // Listen for when container is removed from parent
* container.on('removed', (parent) => {
* console.log('Removed from parent:', parent);
* });
*
* // Listen for container destruction
* container.on('destroyed', (container) => {
* console.log('Container destroyed:', container);
* });
* ```
*/
export interface ContainerEvents extends PixiMixins.ContainerEvents {
/**
* Emitted when this container is added to a new container.
* Useful for setting up parent-specific behaviors.
* @param container - The parent container this was added to
* @example
* ```ts
* const child = new Container();
* child.on('added', (parent) => {
* console.log('Child added to parent:', parent.label);
* });
* parentContainer.addChild(child);
* ```
*/
added: [
container: Container
];
/**
* Emitted when a child is added to this container.
* Useful for tracking container composition changes.
* @param child - The child that was added
* @param container - The container the child was added to (this container)
* @param index - The index at which the child was added
* @example
* ```ts
* const parent = new Container();
* parent.on('childAdded', (child, container, index) => {
* console.log(`New child at index ${index}:`, child);
* });
* ```
*/
childAdded: [
child: C,
container: Container,
index: number
];
/**
* Emitted when this container is removed from its parent.
* Useful for cleanup and state management.
* @param container - The parent container this was removed from
* @example
* ```ts
* const child = new Container();
* child.on('removed', (oldParent) => {
* console.log('Child removed from parent:', oldParent.label);
* });
* ```
*/
removed: [
container: Container
];
/**
* Emitted when a child is removed from this container.
* Useful for cleanup and maintaining container state.
* @param child - The child that was removed
* @param container - The container the child was removed from (this container)
* @param index - The index from which the child was removed
* @example
* ```ts
* const parent = new Container();
* parent.on('childRemoved', (child, container, index) => {
* console.log(`Child removed from index ${index}:`, child);
* });
* ```
*/
childRemoved: [
child: C,
container: Container,
index: number
];
/**
* Emitted when the container is destroyed.
* Useful for final cleanup and resource management.
* @param container - The container that was destroyed
* @example
* ```ts
* const container = new Container();
* container.on('destroyed', (container) => {
* console.log('Container destroyed:', container.label);
* });
* ```
*/
destroyed: [
container: Container
];
}
type AnyEvent = {
[K: ({} & string) | ({} & symbol)]: any;
};
/**
* Options for updating the transform of a container.
*/
export interface UpdateTransformOptions {
x: number;
y: number;
scaleX: number;
scaleY: number;
rotation: number;
skewX: number;
skewY: number;
pivotX: number;
pivotY: number;
}
/**
* Constructor options used for `Container` instances.
* ```js
* const container = new Container({
* position: new Point(100, 200),
* scale: new Point(2, 2),
* rotation: Math.PI / 2,
* });
* ```
*/
export interface ContainerOptions extends PixiMixins.ContainerOptions {
/** @see Container#isRenderGroup */
isRenderGroup?: boolean;
/**
* The blend mode to be applied to the sprite. Controls how pixels are blended when rendering.
*
* Setting to 'normal' will reset to default blending.
* > [!NOTE] More blend modes are available after importing the `pixi.js/advanced-blend-modes` sub-export.
* @example
* ```ts
* // Basic blend modes
* new Container({ blendMode: 'normal' }); // Default blending
* new Container({ blendMode: 'add' }); // Additive blending
* new Container({ blendMode: 'multiply' }); // Multiply colors
* new Container({ blendMode: 'screen' }); // Screen blend
* ```
* @default 'normal'
*/
blendMode?: BLEND_MODES;
/**
* The tint applied to the sprite.
*
* This can be any valid {@link ColorSource}.
* @example
* ```ts
* new Container({ tint: 0xff0000 }); // Red tint
* new Container({ tint: 'blue' }); // Blue tint
* new Container({ tint: '#00ff00' }); // Green tint
* new Container({ tint: 'rgb(0,0,255)' }); // Blue tint
* ```
* @default 0xFFFFFF
*/
tint?: ColorSource;
/**
* The opacity of the object relative to its parent's opacity.
* Value ranges from 0 (fully transparent) to 1 (fully opaque).
* @example
* ```ts
* new Container({ alpha: 0.5 }); // 50% opacity
* new Container({ alpha: 1 }); // Fully opaque
* ```
* @default 1
*/
alpha?: number;
/**
* The angle of the object in degrees.
*
* > [!NOTE] 'rotation' and 'angle' have the same effect on a display object;
* > rotation is in radians, angle is in degrees.
@example
* ```ts
* new Container({ angle: 45 }); // Rotate 45 degrees
* new Container({ angle: 90 }); // Rotate 90 degrees
* ```
*/
angle?: number;
/**
* The array of children of this container. Each child must be a Container or extend from it.
*
* The array is read-only, but its contents can be modified using Container methods.
* @example
* ```ts
* new Container({
* children: [
* new Container(), // First child
* new Container(), // Second child
* ],
* });
* ```
*/
children?: C[];
/**
* The display object container that contains this display object.
* This represents the parent-child relationship in the display tree.
*/
parent?: Container;
/**
* Controls whether this object can be rendered. If false the object will not be drawn,
* but the transform will still be updated. This is different from visible, which skips
* transform updates.
* @example
* ```ts
* new Container({ renderable: false }); // Will not be drawn, but transforms will update
* ```
* @default true
*/
renderable?: boolean;
/**
* The rotation of the object in radians.
*
* > [!NOTE] 'rotation' and 'angle' have the same effect on a display object;
* > rotation is in radians, angle is in degrees.
* @example
* ```ts
* new Container({ rotation: Math.PI / 4 }); // Rotate 45 degrees
* new Container({ rotation: Math.PI / 2 }); // Rotate 90 degrees
* ```
*/
rotation?: number;
/**
* The scale factors of this object along the local coordinate axes.
*
* The default scale is (1, 1).
* @example
* ```ts
* new Container({ scale: new Point(2, 2) }); // Scale by 2x
* new Container({ scale: 0.5 }); // Scale by 0.5x
* new Container({ scale: { x: 1.5, y: 1.5 } }); // Scale by 1.5x
* ```
*/
scale?: PointData | number;
/**
* The center of rotation, scaling, and skewing for this display object in its local space.
* The `position` is the projection of `pivot` in the parent's local space.
*
* By default, the pivot is the origin (0, 0).
* @example
* ```ts
* new Container({ pivot: new Point(100, 200) }); // Set pivot to (100, 200)
* new Container({ pivot: 50 }); // Set pivot to (50, 50)
* new Container({ pivot: { x: 150, y: 150 } }); // Set pivot to (150, 150)
* ```
*/
pivot?: PointData | number;
/**
* The coordinate of the object relative to the local coordinates of the parent.
* @example
* ```ts
* new Container({ position: new Point(100, 200) }); // Set position to (100, 200)
* new Container({ position: { x: 150, y: 150 } }); // Set position to (150, 150)
* ```
*/
position?: PointData;
/**
* The skew factor for the object in radians. Skewing is a transformation that distorts
* the object by rotating it differently at each point, creating a non-uniform shape.
* @example
* ```ts
* new Container({ skew: new Point(0.1, 0.2) }); // Skew by 0.1 radians on x and 0.2 radians on y
* new Container({ skew: { x: 0.1, y: 0.2 } }); // Skew by 0.1 radians on x and 0.2 radians on y
* ```
* @default { x: 0, y: 0 }
*/
skew?: PointData;
/**
* The visibility of the object. If false the object will not be drawn,
* and the transform will not be updated.
* @example
* ```ts
* new Container({ visible: false }); // Will not be drawn and transforms will not update
* new Container({ visible: true }); // Will be drawn and transforms will update
* ```
* @default true
*/
visible?: boolean;
/**
* The position of the container on the x axis relative to the local coordinates of the parent.
*
* An alias to position.x
* @example
* ```ts
* new Container({ x: 100 }); // Set x position to 100
* ```
*/
x?: number;
/**
* The position of the container on the y axis relative to the local coordinates of the parent.
*
* An alias to position.y
* @example
* ```ts
* new Container({ y: 200 }); // Set y position to 200
* ```
*/
y?: number;
/**
* An optional bounds area for this container. Setting this rectangle will stop the renderer
* from recursively measuring the bounds of each children and instead use this single boundArea.
*
* > [!IMPORTANT] This is great for optimisation! If for example you have a
* > 1000 spinning particles and you know they all sit within a specific bounds,
* > then setting it will mean the renderer will not need to measure the
* > 1000 children to find the bounds. Instead it will just use the bounds you set.
* @example
* ```ts
* const container = new Container({
* boundsArea: new Rectangle(0, 0, 500, 500) // Set a fixed bounds area
* });
* ```
*/
boundsArea?: Rectangle;
}
export interface Container extends PixiMixins.Container, EventEmitter & AnyEvent> {
}
/**
* Container is a general-purpose display object that holds children. It also adds built-in support for advanced
* rendering features like masking and filtering.
*
* It is the base class of all display objects that act as a container for other objects, including Graphics
* and Sprite.
*
*
*
* Transforms
*
* The [transform]{@link Container#localTransform} of a display object describes the projection from its
* local coordinate space to its parent's local coordinate space. The following properties are derived
* from the transform:
*
*
*
*
*
Property
*
Description
*
*
*
*
*
[pivot]{@link Container#pivot}
*
* Invariant under rotation, scaling, and skewing. The projection of into the parent's space of the pivot
* is equal to position, regardless of the other three transformations. In other words, It is the center of
* rotation, scaling, and skewing.
*
*
*
*
[position]{@link Container#position}
*
* Translation. This is the position of the [pivot]{@link Container#pivot} in the parent's local
* space. The default value of the pivot is the origin (0,0). If the top-left corner of your display object
* is (0,0) in its local space, then the position will be its top-left corner in the parent's local space.
*
*
*
*
[scale]{@link Container#scale}
*
* Scaling. This will stretch (or compress) the display object's projection. The scale factors are along the
* local coordinate axes. In other words, the display object is scaled before rotated or skewed. The center
* of scaling is the [pivot]{@link Container#pivot}.
*
*
*
*
[rotation]{@link Container#rotation}
*
* Rotation. This will rotate the display object's projection by this angle (in radians).
*
*
*
*
[skew]{@link Container#skew}
*
*
Skewing. This can be used to deform a rectangular display object into a parallelogram.
*
* In PixiJS, skew has a slightly different behaviour than the conventional meaning. It can be
* thought of the net rotation applied to the coordinate axes (separately). For example, if "skew.x" is
* ⍺ and "skew.y" is β, then the line x = 0 will be rotated by ⍺ (y = -x*cot⍺) and the line y = 0 will be
* rotated by β (y = x*tanβ). A line y = x*tanϴ (i.e. a line at angle ϴ to the x-axis in local-space) will
* be rotated by an angle between ⍺ and β.
*
*
* It can be observed that if skew is applied equally to both axes, then it will be equivalent to applying
* a rotation. Indeed, if "skew.x" = -ϴ and "skew.y" = ϴ, it will produce an equivalent of "rotation" = ϴ.
*
*
* Another quite interesting observation is that "skew.x", "skew.y", rotation are commutative operations. Indeed,
* because rotation is essentially a careful combination of the two.
*
*
*
*
*
[angle]{@link Container#angle}
*
Rotation. This is an alias for [rotation]{@link Container#rotation}, but in degrees.
*
*
*
[x]{@link Container#x}
*
Translation. This is an alias for position.x!
*
*
*
[y]{@link Container#y}
*
Translation. This is an alias for position.y!
*
*
*
[width]{@link Container#width}
*
* Implemented in [Container]{@link Container}. Scaling. The width property calculates scale.x by dividing
* the "requested" width by the local bounding box width. It is indirectly an abstraction over scale.x, and there
* is no concept of user-defined width.
*
*
*
*
[height]{@link Container#height}
*
* Implemented in [Container]{@link Container}. Scaling. The height property calculates scale.y by dividing
* the "requested" height by the local bounding box height. It is indirectly an abstraction over scale.y, and there
* is no concept of user-defined height.
*
*
*
*
*
*
*
* Alpha
*
* This alpha sets a display object's **relative opacity** w.r.t its parent. For example, if the alpha of a display
* object is 0.5 and its parent's alpha is 0.5, then it will be rendered with 25% opacity (assuming alpha is not
* applied on any ancestor further up the chain).
*
*
*
* Renderable vs Visible
*
* The `renderable` and `visible` properties can be used to prevent a display object from being rendered to the
* screen. However, there is a subtle difference between the two. When using `renderable`, the transforms of the display
* object (and its children subtree) will continue to be calculated. When using `visible`, the transforms will not
* be calculated.
* ```ts
* import { BlurFilter, Container, Graphics, Sprite } from 'pixi.js';
*
* const container = new Container();
* const sprite = Sprite.from('https://s3-us-west-2.amazonaws.com/s.cdpn.io/693612/IaUrttj.png');
*
* sprite.width = 512;
* sprite.height = 512;
*
* // Adds a sprite as a child to this container. As a result, the sprite will be rendered whenever the container
* // is rendered.
* container.addChild(sprite);
*
* // Blurs whatever is rendered by the container
* container.filters = [new BlurFilter()];
*
* // Only the contents within a circle at the center should be rendered onto the screen.
* container.mask = new Graphics()
* .beginFill(0xffffff)
* .drawCircle(sprite.width / 2, sprite.height / 2, Math.min(sprite.width, sprite.height) / 2)
* .endFill();
* ```
*
*
*
*
* RenderGroup
*
* In PixiJS v8, containers can be set to operate in 'render group mode',
* transforming them into entities akin to a stage in traditional rendering paradigms.
* A render group is a root renderable entity, similar to a container,
* but it's rendered in a separate pass with its own unique set of rendering instructions.
* This approach enhances rendering efficiency and organization, particularly in complex scenes.
*
* You can enable render group mode on any container using container.enableRenderGroup()
* or by initializing a new container with the render group property set to true (new Container({isRenderGroup: true})).
* The method you choose depends on your specific use case and setup requirements.
*
* An important aspect of PixiJS’s rendering process is the automatic treatment of rendered scenes as render groups.
* This conversion streamlines the rendering process, but understanding when and how this happens is crucial
* to fully leverage its benefits.
*
* One of the key advantages of using render groups is the performance efficiency in moving them. Since transformations
* are applied at the GPU level, moving a render group, even one with complex and numerous children,
* doesn't require recalculating the rendering instructions or performing transformations on each child.
* This makes operations like panning a large game world incredibly efficient.
*
* However, it's crucial to note that render groups do not batch together.
* This means that turning every container into a render group could actually slow things down,
* as each render group is processed separately. It's best to use render groups judiciously, at a broader level,
* rather than on a per-child basis.
* This approach ensures you get the performance benefits without overburdening the rendering process.
*
* RenderGroups maintain their own set of rendering instructions,
* ensuring that changes or updates within a render group don't affect the rendering
* instructions of its parent or other render groups.
* This isolation ensures more stable and predictable rendering behavior.
*
* Additionally, renderGroups can be nested, allowing for powerful options in organizing different aspects of your scene.
* This feature is particularly beneficial for separating complex game graphics from UI elements,
* enabling intricate and efficient scene management in complex applications.
*
* This means that Containers have 3 levels of matrix to be mindful of:
*
* 1. localTransform, this is the transform of the container based on its own properties
* 2. groupTransform, this it the transform of the container relative to the renderGroup it belongs too
* 3. worldTransform, this is the transform of the container relative to the Scene being rendered
*
*/
export declare class Container extends EventEmitter & AnyEvent> {
/**
* Mixes all enumerable properties and methods from a source object to Container.
* @param source - The source of properties and methods to mix in.
* @deprecated since 8.8.0
*/
static mixin(source: Dict): void;
/**
* The array of children of this container. Each child must be a Container or extend from it.
*
* The array is read-only, but its contents can be modified using Container methods.
* @example
* ```ts
* // Access children
* const firstChild = container.children[0];
* const lastChild = container.children[container.children.length - 1];
* ```
*/
children: C[];
/**
* The display object container that contains this display object.
* This represents the parent-child relationship in the display tree.
* @example
* ```ts
* // Basic parent access
* const parent = sprite.parent;
*
* // Walk up the tree
* let current = sprite;
* while (current.parent) {
* console.log('Level up:', current.parent.constructor.name);
* current = current.parent;
* }
* ```
*/
parent: Container;
/**
* Current transform of the object based on local factors: position, scale, other stuff.
* This matrix represents the local transformation without any parent influence.
* @example
* ```ts
* // Basic transform access
* const localMatrix = sprite.localTransform;
* console.log(localMatrix.toString());
* ```
*/
localTransform: Matrix;
/**
* Whether this object has been destroyed. If true, the object should no longer be used.
* After an object is destroyed, all of its functionality is disabled and references are removed.
* @example
* ```ts
* // Cleanup with destroy
* sprite.destroy();
* console.log(sprite.destroyed); // true
* ```
* @default false
*/
destroyed: boolean;
/**
* An optional bounds area for this container. Setting this rectangle will stop the renderer
* from recursively measuring the bounds of each children and instead use this single boundArea.
*
* > [!IMPORTANT] This is great for optimisation! If for example you have a
* > 1000 spinning particles and you know they all sit within a specific bounds,
* > then setting it will mean the renderer will not need to measure the
* > 1000 children to find the bounds. Instead it will just use the bounds you set.
* @example
* ```ts
* const container = new Container();
* container.boundsArea = new Rectangle(0, 0, 500, 500);
* ```
*/
boundsArea: Rectangle;
constructor(options?: ContainerOptions);
/**
* Adds one or more children to the container.
* The children will be rendered as part of this container's display list.
* @example
* ```ts
* // Add a single child
* container.addChild(sprite);
*
* // Add multiple children
* container.addChild(background, player, foreground);
*
* // Add with type checking
* const sprite = container.addChild(new Sprite(texture));
* sprite.tint = 'red';
* ```
* @param children - The Container(s) to add to the container
* @returns The first child that was added
*/
addChild(...children: U): U[0];
/**
* Removes one or more children from the container.
* When removing multiple children, events will be triggered for each child in sequence.
* @example
* ```ts
* // Remove a single child
* const removed = container.removeChild(sprite);
*
* // Remove multiple children
* const bg = container.removeChild(background, player, userInterface);
*
* // Remove with type checking
* const sprite = container.removeChild(childSprite);
* sprite.texture = newTexture;
* ```
* @param children - The Container(s) to remove
* @returns The first child that was removed
*/
removeChild(...children: U): U[0];
set isRenderGroup(value: boolean);
/**
* Current transform of the object based on world (parent) factors.
*
* This matrix represents the absolute transformation in the scene graph.
* @example
* ```ts
* // Get world position
* const worldPos = container.worldTransform;
* console.log(`World position: (${worldPos.tx}, ${worldPos.ty})`);
* ```
*/
get worldTransform(): Matrix;
/**
* The position of the container on the x axis relative to the local coordinates of the parent.
*
* An alias to position.x
* @example
* ```ts
* // Basic position
* container.x = 100;
* ```
*/
get x(): number;
set x(value: number);
/**
* The position of the container on the y axis relative to the local coordinates of the parent.
*
* An alias to position.y
* @example
* ```ts
* // Basic position
* container.y = 200;
* ```
*/
get y(): number;
set y(value: number);
/**
* The coordinate of the object relative to the local coordinates of the parent.
* @example
* ```ts
* // Basic position setting
* container.position.set(100, 200);
* container.position.set(100); // Sets both x and y to 100
* // Using point data
* container.position = { x: 50, y: 75 };
* ```
* @since 4.0.0
*/
get position(): ObservablePoint;
set position(value: PointData);
/**
* The rotation of the object in radians.
*
* > [!NOTE] 'rotation' and 'angle' have the same effect on a display object;
* > rotation is in radians, angle is in degrees.
* @example
* ```ts
* // Basic rotation
* container.rotation = Math.PI / 4; // 45 degrees
*
* // Convert from degrees
* const degrees = 45;
* container.rotation = degrees * Math.PI / 180;
*
* // Rotate around center
* container.pivot.set(container.width / 2, container.height / 2);
* container.rotation = Math.PI; // 180 degrees
* ```
*/
get rotation(): number;
set rotation(value: number);
/**
* The angle of the object in degrees.
*
* > [!NOTE] 'rotation' and 'angle' have the same effect on a display object;
* > rotation is in radians, angle is in degrees.
@example
* ```ts
* // Basic angle rotation
* sprite.angle = 45; // 45 degrees
*
* // Rotate around center
* sprite.pivot.set(sprite.width / 2, sprite.height / 2);
* sprite.angle = 180; // Half rotation
*
* // Reset rotation
* sprite.angle = 0;
* ```
*/
get angle(): number;
set angle(value: number);
/**
* The center of rotation, scaling, and skewing for this display object in its local space.
* The `position` is the projection of `pivot` in the parent's local space.
*
* By default, the pivot is the origin (0, 0).
* @example
* ```ts
* // Rotate around center
* container.pivot.set(container.width / 2, container.height / 2);
* container.rotation = Math.PI; // Rotates around center
* ```
* @since 4.0.0
*/
get pivot(): ObservablePoint;
set pivot(value: PointData | number);
/**
* The skew factor for the object in radians. Skewing is a transformation that distorts
* the object by rotating it differently at each point, creating a non-uniform shape.
* @example
* ```ts
* // Basic skewing
* container.skew.set(0.5, 0); // Skew horizontally
* container.skew.set(0, 0.5); // Skew vertically
*
* // Skew with point data
* container.skew = { x: 0.3, y: 0.3 }; // Diagonal skew
*
* // Reset skew
* container.skew.set(0, 0);
*
* // Animate skew
* app.ticker.add(() => {
* // Create wave effect
* container.skew.x = Math.sin(Date.now() / 1000) * 0.3;
* });
*
* // Combine with rotation
* container.rotation = Math.PI / 4; // 45 degrees
* container.skew.set(0.2, 0.2); // Skew the rotated object
* ```
* @since 4.0.0
* @type {ObservablePoint} Point-like object with x/y properties in radians
* @default {x: 0, y: 0}
*/
get skew(): ObservablePoint;
set skew(value: PointData);
/**
* The scale factors of this object along the local coordinate axes.
*
* The default scale is (1, 1).
* @example
* ```ts
* // Basic scaling
* container.scale.set(2, 2); // Scales to double size
* container.scale.set(2); // Scales uniformly to double size
* container.scale = 2; // Scales uniformly to double size
* // Scale to a specific width and height
* container.setSize(200, 100); // Sets width to 200 and height to 100
* ```
* @since 4.0.0
*/
get scale(): ObservablePoint;
set scale(value: PointData | number);
/**
* The width of the Container, setting this will actually modify the scale to achieve the value set.
* > [!NOTE] Changing the width will adjust the scale.x property of the container while maintaining its aspect ratio.
* > [!NOTE] If you want to set both width and height at the same time, use {@link Container#setSize}
* as it is more optimized by not recalculating the local bounds twice.
* @example
* ```ts
* // Basic width setting
* container.width = 100;
* // Optimized width setting
* container.setSize(100, 100);
* ```
*/
get width(): number;
set width(value: number);
/**
* The height of the Container,
* > [!NOTE] Changing the height will adjust the scale.y property of the container while maintaining its aspect ratio.
* > [!NOTE] If you want to set both width and height at the same time, use {@link Container#setSize}
* as it is more optimized by not recalculating the local bounds twice.
* @example
* ```ts
* // Basic height setting
* container.height = 200;
* // Optimized height setting
* container.setSize(100, 200);
* ```
*/
get height(): number;
set height(value: number);
/**
* Retrieves the size of the container as a [Size]{@link Size} object.
*
* This is faster than get the width and height separately.
* @example
* ```ts
* // Basic size retrieval
* const size = container.getSize();
* console.log(`Size: ${size.width}x${size.height}`);
*
* // Reuse existing size object
* const reuseSize = { width: 0, height: 0 };
* container.getSize(reuseSize);
* ```
* @param out - Optional object to store the size in.
* @returns - The size of the container.
*/
getSize(out?: Size): Size;
/**
* Sets the size of the container to the specified width and height.
* This is more efficient than setting width and height separately as it only recalculates bounds once.
* @example
* ```ts
* // Basic size setting
* container.setSize(100, 200);
*
* // Set uniform size
* container.setSize(100); // Sets both width and height to 100
* ```
* @param value - This can be either a number or a [Size]{@link Size} object.
* @param height - The height to set. Defaults to the value of `width` if not provided.
*/
setSize(value: number | Optional, height?: number): void;
/**
* Updates the transform properties of the container.
* Allows partial updates of transform properties for optimized manipulation.
* @example
* ```ts
* // Basic transform update
* container.updateTransform({
* x: 100,
* y: 200,
* rotation: Math.PI / 4
* });
*
* // Scale and rotate around center
* sprite.updateTransform({
* pivotX: sprite.width / 2,
* pivotY: sprite.height / 2,
* scaleX: 2,
* scaleY: 2,
* rotation: Math.PI
* });
*
* // Update position only
* button.updateTransform({
* x: button.x + 10, // Move right
* y: button.y // Keep same y
* });
* ```
* @param opts - Transform options to update
* @param opts.x - The x position
* @param opts.y - The y position
* @param opts.scaleX - The x-axis scale factor
* @param opts.scaleY - The y-axis scale factor
* @param opts.rotation - The rotation in radians
* @param opts.skewX - The x-axis skew factor
* @param opts.skewY - The y-axis skew factor
* @param opts.pivotX - The x-axis pivot point
* @param opts.pivotY - The y-axis pivot point
* @returns This container, for chaining
*/
updateTransform(opts: Partial): this;
/**
* Updates the local transform properties by decomposing the given matrix.
* Extracts position, scale, rotation, and skew from a transformation matrix.
* @example
* ```ts
* // Basic matrix transform
* const matrix = new Matrix()
* .translate(100, 100)
* .rotate(Math.PI / 4)
* .scale(2, 2);
*
* container.setFromMatrix(matrix);
*
* // Copy transform from another container
* const source = new Container();
* source.position.set(100, 100);
* source.rotation = Math.PI / 2;
*
* target.setFromMatrix(source.localTransform);
*
* // Reset transform
* container.setFromMatrix(Matrix.IDENTITY);
* ```
* @param matrix - The matrix to use for updating the transform
*/
setFromMatrix(matrix: Matrix): void;
/** Updates the local transform. */
updateLocalTransform(): void;
set alpha(value: number);
/**
* The opacity of the object relative to its parent's opacity.
* Value ranges from 0 (fully transparent) to 1 (fully opaque).
* @example
* ```ts
* // Basic transparency
* sprite.alpha = 0.5; // 50% opacity
*
* // Inherited opacity
* container.alpha = 0.5;
* const child = new Sprite(texture);
* child.alpha = 0.5;
* container.addChild(child);
* // child's effective opacity is 0.25 (0.5 * 0.5)
* ```
* @default 1
*/
get alpha(): number;
set tint(value: ColorSource);
/**
* The tint applied to the sprite.
*
* This can be any valid {@link ColorSource}.
* @example
* ```ts
* // Basic color tinting
* container.tint = 0xff0000; // Red tint
* container.tint = 'red'; // Same as above
* container.tint = '#00ff00'; // Green
* container.tint = 'rgb(0,0,255)'; // Blue
*
* // Remove tint
* container.tint = 0xffffff; // White = no tint
* container.tint = null; // Also removes tint
* ```
* @default 0xFFFFFF
*/
get tint(): number;
set blendMode(value: BLEND_MODES);
/**
* The blend mode to be applied to the sprite. Controls how pixels are blended when rendering.
*
* Setting to 'normal' will reset to default blending.
* > [!NOTE] More blend modes are available after importing the `pixi.js/advanced-blend-modes` sub-export.
* @example
* ```ts
* // Basic blend modes
* sprite.blendMode = 'add'; // Additive blending
* sprite.blendMode = 'multiply'; // Multiply colors
* sprite.blendMode = 'screen'; // Screen blend
*
* // Reset blend mode
* sprite.blendMode = 'normal'; // Normal blending
* ```
* @default 'normal'
*/
get blendMode(): BLEND_MODES;
/**
* The visibility of the object. If false the object will not be drawn,
* and the transform will not be updated.
* @example
* ```ts
* // Basic visibility toggle
* sprite.visible = false; // Hide sprite
* sprite.visible = true; // Show sprite
* ```
* @default true
*/
get visible(): boolean;
set visible(value: boolean);
/**
* Controls whether this object can be rendered. If false the object will not be drawn,
* but the transform will still be updated. This is different from visible, which skips
* transform updates.
* @example
* ```ts
* // Basic render control
* sprite.renderable = false; // Skip rendering
* sprite.renderable = true; // Enable rendering
* ```
* @default true
*/
get renderable(): boolean;
set renderable(value: boolean);
/**
* Removes all internal references and listeners as well as removes children from the display list.
* Do not use a Container after calling `destroy`.
* @param options - Options parameter. A boolean will act as if all options
* have been set to that value
* @example
* ```ts
* container.destroy();
* container.destroy(true);
* container.destroy({ children: true });
* container.destroy({ children: true, texture: true, textureSource: true });
* ```
*/
destroy(options?: DestroyOptions): void;
}
/**
* The type of the pointer event to listen for.
*/
export type PointerEvents = "auto" | "none" | "visiblePainted" | "visibleFill" | "visibleStroke" | "visible" | "painted" | "fill" | "stroke" | "all" | "inherit";
/**
* When `accessible` is enabled on any display object, these properties will affect its accessibility.
* @example
* const container = new Container();
* container.accessible = true;
* container.accessibleTitle = 'My Container';
* container.accessibleHint = 'This is a container';
* container.tabIndex = 0;
*/
export interface AccessibleOptions {
/**
* Flag for if the object is accessible. If true AccessibilityManager will overlay a
* shadow div with attributes set
* @default false
* @example
* ```js
* const container = new Container();
* container.accessible = true;
* ```
*/
accessible: boolean;
/**
* Sets the title attribute of the shadow div
* If accessibleTitle AND accessibleHint has not been this will default to 'container [tabIndex]'
* @type {string}
* @default null
* @example
* ```js
* const container = new Container();
* container.accessible = true;
* container.accessibleTitle = 'My Container';
* ```
*/
accessibleTitle: string | null;
/**
* Sets the tabIndex of the shadow div. You can use this to set the order of the
* elements when using the tab key to navigate.
* @default 0
* @example
* ```js
* const container = new Container();
* container.accessible = true;
* container.tabIndex = 0;
*
* const sprite = new Sprite(texture);
* sprite.accessible = true;
* sprite.tabIndex = 1;
* ```
*/
tabIndex: number;
/**
* Sets the text content of the shadow
* @default null
* @example
* ```js
* const container = new Container();
* container.accessible = true;
* container.accessibleText = 'This is a container';
* ```
*/
accessibleText: string | null;
/**
* Setting to false will prevent any children inside this container to
* be accessible. Defaults to true.
* @default true
* @example
* ```js
* const container = new Container();
* container.accessible = true;
* container.accessibleChildren = false; // This will prevent any children from being accessible
*
* const sprite = new Sprite(texture);
* sprite.accessible = true; // This will not work since accessibleChildren is false
* ```
*/
accessibleChildren: boolean;
}
/**
* The result of the mobile device detection system.
* Provides detailed information about device type and platform.
* @example
* ```ts
* // Type usage with isMobile
* const deviceInfo: isMobileResult = isMobile;
*
* // Check device categories
* if (deviceInfo.apple.device) {
* console.log('iOS Device Details:', {
* isPhone: deviceInfo.apple.phone,
* isTablet: deviceInfo.apple.tablet,
* isUniversal: deviceInfo.apple.universal
* });
* }
*
* // Platform-specific checks
* const platformInfo = {
* isApple: deviceInfo.apple.device,
* isAndroid: deviceInfo.android.device,
* isAmazon: deviceInfo.amazon.device,
* isWindows: deviceInfo.windows.device
* };
* ```
*/
export type isMobileResult = {
/**
* Apple device detection information.
* Provides detailed iOS device categorization.
* @example
* ```ts
* // iOS device checks
* if (isMobile.apple.device) {
* if (isMobile.apple.tablet) {
* // iPad-specific code
* useTabletLayout();
* } else if (isMobile.apple.phone) {
* // iPhone-specific code
* usePhoneLayout();
* }
* }
* ```
*/
apple: {
/** Whether the device is an iPhone */
phone: boolean;
/** Whether the device is an iPod Touch */
ipod: boolean;
/** Whether the device is an iPad */
tablet: boolean;
/** Whether app is running in iOS universal mode */
universal: boolean;
/** Whether device is any Apple mobile device */
device: boolean;
};
/**
* Amazon device detection information.
* Identifies Amazon Fire tablets and phones.
* @example
* ```ts
* // Amazon Fire tablet detection
* if (isMobile.amazon.tablet) {
* // Fire tablet optimizations
* optimizeForFireTablet();
* }
* ```
*/
amazon: {
/** Whether device is a Fire Phone */
phone: boolean;
/** Whether device is a Fire Tablet */
tablet: boolean;
/** Whether device is any Amazon mobile device */
device: boolean;
};
/**
* Android device detection information.
* Categorizes Android phones and tablets.
* @example
* ```ts
* // Android device handling
* if (isMobile.android.device) {
* // Check specific type
* const deviceType = isMobile.android.tablet ?
* 'tablet' : 'phone';
* console.log(`Android ${deviceType} detected`);
* }
* ```
*/
android: {
/** Whether device is an Android phone */
phone: boolean;
/** Whether device is an Android tablet */
tablet: boolean;
/** Whether device is any Android device */
device: boolean;
};
/**
* Windows device detection information.
* Identifies Windows phones and tablets.
* @example
* ```ts
* // Windows device checks
* if (isMobile.windows.tablet) {
* // Surface tablet optimizations
* enableTouchFeatures();
* }
* ```
*/
windows: {
/** Whether device is a Windows Phone */
phone: boolean;
/** Whether device is a Windows tablet */
tablet: boolean;
/** Whether device is any Windows mobile device */
device: boolean;
};
/**
* Other device detection information.
* Covers additional platforms and browsers.
* @example
* ```ts
* // Check other platforms
* if (isMobile.other.blackberry10) {
* // BlackBerry 10 specific code
* } else if (isMobile.other.chrome) {
* // Chrome mobile specific code
* }
* ```
*/
other: {
/** Whether device is a BlackBerry */
blackberry: boolean;
/** Whether device is a BlackBerry 10 */
blackberry10: boolean;
/** Whether browser is Opera Mobile */
opera: boolean;
/** Whether browser is Firefox Mobile */
firefox: boolean;
/** Whether browser is Chrome Mobile */
chrome: boolean;
/** Whether device is any other mobile device */
device: boolean;
};
/**
* Whether the device is any type of phone.
* Combines detection across all platforms.
* @example
* ```ts
* // Check if device is a phone
* if (isMobile.phone) {
* console.log('Running on a mobile phone');
* }
* ```
*/
phone: boolean;
/**
* Whether the device is any type of tablet.
* Combines detection across all platforms.
* @example
* ```ts
* // Check if device is a tablet
* if (isMobile.tablet) {
* console.log('Running on a mobile tablet');
* }
* ```
*/
tablet: boolean;
/**
* Whether the device is any type of mobile device.
* True if any mobile platform is detected.
* @example
* ```ts
* // Check if device is mobile
* if (isMobile.any) {
* console.log('Running on a mobile device');
* }
* ```
*/
any: boolean;
};
/**
* Detects whether the device is mobile and what type of mobile device it is.
* Provides a comprehensive detection system for mobile platforms and devices.
* @example
* ```ts
* import { isMobile } from 'pixi.js';
*
* // Check specific device types
* if (isMobile.apple.tablet) {
* console.log('Running on iPad');
* }
*
* // Check platform categories
* if (isMobile.android.any) {
* console.log('Running on Android');
* }
*
* // Conditional rendering
* if (isMobile.phone) {
* renderer.resolution = 2;
* view.style.width = '100vw';
* }
* ```
* @remarks
* - Detects all major mobile platforms
* - Distinguishes between phones and tablets
* - Updates when navigator changes
* - Common in responsive design
*/
export declare const isMobile: isMobileResult;
/**
* The Accessibility system provides screen reader and keyboard navigation support for PixiJS content.
* It creates an accessible DOM layer over the canvas that can be controlled programmatically or through user interaction.
*
* By default, the system activates when users press the tab key. This behavior can be customized through options:
* ```js
* const app = new Application({
* accessibilityOptions: {
* // Enable immediately instead of waiting for tab
* enabledByDefault: true,
* // Disable tab key activation
* activateOnTab: false,
* // Show/hide accessibility divs
* debug: false,
* // Prevent accessibility from being deactivated when mouse moves
* deactivateOnMouseMove: false,
* }
* });
* ```
*
* The system can also be controlled programmatically by accessing the `renderer.accessibility` property:
* ```js
* app.renderer.accessibility.setAccessibilityEnabled(true);
* ```
*
* To make individual containers accessible:
* ```js
* container.accessible = true;
* ```
* There are several properties that can be set on a Container to control its accessibility which can
* be found here: {@link AccessibleOptions}.
*/
export declare class AccessibilitySystem implements System {
/**
* The default options used by the system.
* You can set these before initializing the {@link Application} to change the default behavior.
* @example
* ```js
* import { AccessibilitySystem } from 'pixi.js';
*
* AccessibilitySystem.defaultOptions.enabledByDefault = true;
*
* const app = new Application()
* app.init()
* ```
*/
static defaultOptions: AccessibilityOptions;
/** Whether accessibility divs are visible for debugging */
debug: boolean;
/**
* @param {WebGLRenderer|WebGPURenderer} renderer - A reference to the current renderer
*/
constructor(renderer: Renderer, _mobileInfo?: isMobileResult);
/**
* Value of `true` if accessibility is currently active and accessibility layers are showing.
* @type {boolean}
*/
get isActive(): boolean;
/**
* Value of `true` if accessibility is enabled for touch devices.
* @type {boolean}
*/
get isMobileAccessibility(): boolean;
/**
* The DOM element that will sit over the PixiJS element. This is where the div overlays will go.
*/
get hookDiv(): HTMLElement;
/**
* Destroys the accessibility system. Removes all elements and listeners.
* > [!IMPORTANT] This is typically called automatically when the {@link Application} is destroyed.
* > A typically user should not need to call this method directly.
*/
destroy(): void;
/**
* Enables or disables the accessibility system.
* @param enabled - Whether to enable or disable accessibility.
* @example
* ```js
* app.renderer.accessibility.setAccessibilityEnabled(true); // Enable accessibility
* app.renderer.accessibility.setAccessibilityEnabled(false); // Disable accessibility
* ```
*/
setAccessibilityEnabled(enabled: boolean): void;
}
declare global {
namespace PixiMixins {
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
interface Container extends Partial {
}
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
interface ContainerOptions extends Partial {
}
interface RendererSystems {
accessibility: AccessibilitySystem;
}
}
}
/**
* A callback which can be added to a ticker.
* ```js
* ticker.add(() => {
* // do something every frame
* });
* ```
*/
export type TickerCallback = (this: T, ticker: Ticker) => any;
/**
* A Ticker class that runs an update loop that other objects listen to.
* Used for managing animation frames and timing in a PixiJS application.
*
* It provides a way to add listeners that will be called on each frame,
* allowing for smooth animations and updates.
*
* Animation frames are requested
* only when necessary, e.g., when the ticker is started and the emitter has listeners.
* @example
* ```ts
* // Basic ticker usage
* const ticker = new Ticker();
* ticker.add((ticker) => {
* // Update every frame
* sprite.rotation += 0.1 * ticker.deltaTime;
* });
* ticker.start();
*
* // Control update priority
* ticker.add(
* (ticker) => {
* // High priority updates run first
* physics.update(ticker.deltaTime);
* },
* undefined,
* UPDATE_PRIORITY.HIGH
* );
*
* // One-time updates
* ticker.addOnce(() => {
* console.log('Runs on next frame only');
* });
* ```
*/
export declare class Ticker {
/**
* Target frame rate in frames per millisecond.
* Used for converting deltaTime to a scalar time delta.
* @example
* ```ts
* // Default is 0.06 (60 FPS)
* console.log(Ticker.targetFPMS); // 0.06
*
* // Calculate target frame duration
* const frameDuration = 1 / Ticker.targetFPMS; // ≈ 16.67ms
*
* // Use in custom timing calculations
* const deltaTime = elapsedMS * Ticker.targetFPMS;
* ```
* @remarks
* - Default is 0.06 (equivalent to 60 FPS)
* - Used in deltaTime calculations
* - Affects all ticker instances
* @default 0.06
*/
static targetFPMS: number;
/**
* Whether or not this ticker should invoke the method {@link Ticker#start|start}
* automatically when a listener is added.
* @example
* ```ts
* // Default behavior (manual start)
* const ticker = new Ticker();
* ticker.autoStart = false;
* ticker.add(() => {
* // Won't run until ticker.start() is called
* });
*
* // Auto-start behavior
* const autoTicker = new Ticker();
* autoTicker.autoStart = true;
* autoTicker.add(() => {
* // Runs immediately when added
* });
* ```
* @default false
*/
autoStart: boolean;
/**
* Scalar time value from last frame to this frame.
* Used for frame-based animations and updates.
*
* This value is capped by setting {@link Ticker#minFPS|minFPS}
* and is scaled with {@link Ticker#speed|speed}.
* > [!NOTE] The cap may be exceeded by scaling.
* @example
* ```ts
* // Basic animation
* ticker.add((ticker) => {
* // Rotate sprite by 0.1 radians per frame, scaled by deltaTime
* sprite.rotation += 0.1 * ticker.deltaTime;
* });
* ```
*/
deltaTime: number;
/**
* Scalar time elapsed in milliseconds from last frame to this frame.
* Provides precise timing for animations and updates.
*
* This value is capped by setting {@link Ticker#minFPS|minFPS}
* and is scaled with {@link Ticker#speed|speed}.
*
* If the platform supports DOMHighResTimeStamp,
* this value will have a precision of 1 µs.
*
* Defaults to target frame time
*
* > [!NOTE] The cap may be exceeded by scaling.
* @example
* ```ts
* // Animation timing
* ticker.add((ticker) => {
* // Use millisecond timing for precise animations
* const progress = (ticker.deltaMS / animationDuration);
* sprite.alpha = Math.min(1, progress);
* });
* ```
* @default 16.66
*/
deltaMS: number;
/**
* Time elapsed in milliseconds from last frame to this frame.
* Provides raw timing information without modifications.
*
* Opposed to what the scalar {@link Ticker#deltaTime|deltaTime}
* is based, this value is neither capped nor scaled.
*
* If the platform supports DOMHighResTimeStamp,
* this value will have a precision of 1 µs.
*
* Defaults to target frame time
* @example
* ```ts
* // Basic timing information
* ticker.add((ticker) => {
* console.log(`Raw frame time: ${ticker.elapsedMS}ms`);
* });
* ```
* @default 16.66
*/
elapsedMS: number;
/**
* The last time {@link Ticker#update|update} was invoked.
* Used for calculating time deltas between frames.
*
* This value is also reset internally outside of invoking
* update, but only when a new animation frame is requested.
*
* If the platform supports DOMHighResTimeStamp,
* this value will have a precision of 1 µs.
* @example
* ```ts
* // Basic timing check
* ticker.add(() => {
* const timeSinceStart = performance.now() - ticker.lastTime;
* console.log(`Time running: ${timeSinceStart}ms`);
* });
* ```
*/
lastTime: number;
/**
* Factor of current {@link Ticker#deltaTime|deltaTime}.
* Used to scale time for slow motion or fast-forward effects.
* @example
* ```ts
* // Basic speed adjustment
* ticker.speed = 0.5; // Half speed (slow motion)
* ticker.speed = 2.0; // Double speed (fast forward)
*
* // Temporary speed changes
* function slowMotion() {
* const normalSpeed = ticker.speed;
* ticker.speed = 0.2;
* setTimeout(() => {
* ticker.speed = normalSpeed;
* }, 1000);
* }
* ```
*/
speed: number;
/**
* Whether or not this ticker has been started.
*
* `true` if {@link Ticker#start|start} has been called.
* `false` if {@link Ticker#stop|Stop} has been called.
*
* While `false`, this value may change to `true` in the
* event of {@link Ticker#autoStart|autoStart} being `true`
* and a listener is added.
* @example
* ```ts
* // Check ticker state
* const ticker = new Ticker();
* console.log(ticker.started); // false
*
* // Start and verify
* ticker.start();
* console.log(ticker.started); // true
* ```
*/
started: boolean;
constructor();
/**
* Register a handler for tick events. Calls continuously unless
* it is removed or the ticker is stopped.
* @example
* ```ts
* // Basic update handler
* ticker.add((ticker) => {
* // Update every frame
* sprite.rotation += 0.1 * ticker.deltaTime;
* });
*
* // With specific context
* const game = {
* update(ticker) {
* this.physics.update(ticker.deltaTime);
* }
* };
* ticker.add(game.update, game);
*
* // With priority
* ticker.add(
* (ticker) => {
* // Runs before normal priority updates
* physics.update(ticker.deltaTime);
* },
* undefined,
* UPDATE_PRIORITY.HIGH
* );
* ```
* @param fn - The listener function to be added for updates
* @param context - The listener context
* @param priority - The priority for emitting (default: UPDATE_PRIORITY.NORMAL)
* @returns This instance of a ticker
*/
add(fn: TickerCallback, context?: T, priority?: number): this;
/**
* Add a handler for the tick event which is only executed once on the next frame.
* @example
* ```ts
* // Basic one-time update
* ticker.addOnce(() => {
* console.log('Runs next frame only');
* });
*
* // With specific context
* const game = {
* init(ticker) {
* this.loadResources();
* console.log('Game initialized');
* }
* };
* ticker.addOnce(game.init, game);
*
* // With priority
* ticker.addOnce(
* () => {
* // High priority one-time setup
* physics.init();
* },
* undefined,
* UPDATE_PRIORITY.HIGH
* );
* ```
* @param fn - The listener function to be added for one update
* @param context - The listener context
* @param priority - The priority for emitting (default: UPDATE_PRIORITY.NORMAL)
* @returns This instance of a ticker
*/
addOnce(fn: TickerCallback, context?: T, priority?: number): this;
/**
* Removes any handlers matching the function and context parameters.
* If no handlers are left after removing, then it cancels the animation frame.
* @example
* ```ts
* // Basic removal
* const onTick = () => {
* sprite.rotation += 0.1;
* };
* ticker.add(onTick);
* ticker.remove(onTick);
*
* // Remove with context
* const game = {
* update(ticker) {
* this.physics.update(ticker.deltaTime);
* }
* };
* ticker.add(game.update, game);
* ticker.remove(game.update, game);
*
* // Remove all matching handlers
* // (if same function was added multiple times)
* ticker.add(onTick);
* ticker.add(onTick);
* ticker.remove(onTick); // Removes all instances
* ```
* @param fn - The listener function to be removed
* @param context - The listener context to be removed
* @returns This instance of a ticker
*/
remove(fn: TickerCallback, context?: T): this;
/**
* The number of listeners on this ticker, calculated by walking through linked list.
* @example
* ```ts
* // Check number of active listeners
* const ticker = new Ticker();
* console.log(ticker.count); // 0
*
* // Add some listeners
* ticker.add(() => {});
* ticker.add(() => {});
* console.log(ticker.count); // 2
*
* // Check after cleanup
* ticker.destroy();
* console.log(ticker.count); // 0
* ```
*/
get count(): number;
/**
* Starts the ticker. If the ticker has listeners a new animation frame is requested at this point.
* @example
* ```ts
* // Basic manual start
* const ticker = new Ticker();
* ticker.add(() => {
* // Animation code here
* });
* ticker.start();
* ```
*/
start(): void;
/**
* Stops the ticker. If the ticker has requested an animation frame it is canceled at this point.
* @example
* ```ts
* // Basic stop
* const ticker = new Ticker();
* ticker.stop();
* ```
*/
stop(): void;
/**
* Destroy the ticker and don't use after this. Calling this method removes all references to internal events.
* @example
* ```ts
* // Clean up with active listeners
* const ticker = new Ticker();
* ticker.add(() => {});
* ticker.destroy(); // Removes all listeners
* ```
*/
destroy(): void;
/**
* Triggers an update.
*
* An update entails setting the
* current {@link Ticker#elapsedMS|elapsedMS},
* the current {@link Ticker#deltaTime|deltaTime},
* invoking all listeners with current deltaTime,
* and then finally setting {@link Ticker#lastTime|lastTime}
* with the value of currentTime that was provided.
*
* This method will be called automatically by animation
* frame callbacks if the ticker instance has been started
* and listeners are added.
* @example
* ```ts
* // Basic manual update
* const ticker = new Ticker();
* ticker.update(performance.now());
* ```
* @param currentTime - The current time of execution (defaults to performance.now())
*/
update(currentTime?: number): void;
/**
* The frames per second at which this ticker is running.
* The default is approximately 60 in most modern browsers.
* > [!NOTE] This does not factor in the value of
* > {@link Ticker#speed|speed}, which is specific
* > to scaling {@link Ticker#deltaTime|deltaTime}.
* @example
* ```ts
* // Basic FPS monitoring
* ticker.add(() => {
* console.log(`Current FPS: ${Math.round(ticker.FPS)}`);
* });
* ```
*/
get FPS(): number;
/**
* Manages the maximum amount of milliseconds allowed to
* elapse between invoking {@link Ticker#update|update}.
*
* This value is used to cap {@link Ticker#deltaTime|deltaTime},
* but does not effect the measured value of {@link Ticker#FPS|FPS}.
*
* When setting this property it is clamped to a value between
* `0` and `Ticker.targetFPMS * 1000`.
* @example
* ```ts
* // Set minimum acceptable frame rate
* const ticker = new Ticker();
* ticker.minFPS = 30; // Never go below 30 FPS
*
* // Use with maxFPS for frame rate clamping
* ticker.minFPS = 30;
* ticker.maxFPS = 60;
*
* // Monitor delta capping
* ticker.add(() => {
* // Delta time will be capped based on minFPS
* console.log(`Delta time: ${ticker.deltaTime}`);
* });
* ```
* @default 10
*/
get minFPS(): number;
set minFPS(fps: number);
/**
* Manages the minimum amount of milliseconds required to
* elapse between invoking {@link Ticker#update|update}.
*
* This will effect the measured value of {@link Ticker#FPS|FPS}.
*
* If it is set to `0`, then there is no limit; PixiJS will render as many frames as it can.
* Otherwise it will be at least `minFPS`
* @example
* ```ts
* // Set minimum acceptable frame rate
* const ticker = new Ticker();
* ticker.maxFPS = 60; // Never go above 60 FPS
*
* // Use with maxFPS for frame rate clamping
* ticker.minFPS = 30;
* ticker.maxFPS = 60;
*
* // Monitor delta capping
* ticker.add(() => {
* // Delta time will be capped based on maxFPS
* console.log(`Delta time: ${ticker.deltaTime}`);
* });
* ```
* @default 0
*/
get maxFPS(): number;
set maxFPS(fps: number);
/**
* The shared ticker instance used by {@link AnimatedSprite} and by
* {@link VideoSource} to update animation frames / video textures.
*
* It may also be used by {@link Application} if created with the `sharedTicker` option property set to true.
*
* The property {@link Ticker#autoStart|autoStart} is set to `true` for this instance.
* Please follow the examples for usage, including how to opt-out of auto-starting the shared ticker.
* @example
* import { Ticker } from 'pixi.js';
*
* const ticker = Ticker.shared;
* // Set this to prevent starting this ticker when listeners are added.
* // By default this is true only for the Ticker.shared instance.
* ticker.autoStart = false;
*
* // FYI, call this to ensure the ticker is stopped. It should be stopped
* // if you have not attempted to render anything yet.
* ticker.stop();
*
* // Call this when you are ready for a running shared ticker.
* ticker.start();
* @example
* import { autoDetectRenderer, Container } from 'pixi.js';
*
* // You may use the shared ticker to render...
* const renderer = autoDetectRenderer();
* const stage = new Container();
* document.body.appendChild(renderer.view);
* ticker.add((time) => renderer.render(stage));
*
* // Or you can just update it manually.
* ticker.autoStart = false;
* ticker.stop();
* const animate = (time) => {
* ticker.update(time);
* renderer.render(stage);
* requestAnimationFrame(animate);
* };
* animate(performance.now());
* @type {Ticker}
*/
static get shared(): Ticker;
}
type ResizeableRenderer = Pick;
/**
* Application options for the {@link ResizePlugin}.
* These options control how your application handles window and element resizing.
* @example
* ```ts
* // Auto-resize to window
* await app.init({ resizeTo: window });
*
* // Auto-resize to container element
* await app.init({ resizeTo: document.querySelector('#game') });
* ```
*/
export interface ResizePluginOptions {
/**
* Element to automatically resize the renderer to.
* @example
* ```ts
* const app = new Application();
* await app.init({
* resizeTo: window, // Resize to the entire window
* // or
* resizeTo: document.querySelector('#game-container'), // Resize to a specific element
* // or
* resizeTo: null, // Disable auto-resize
* });
* ```
* @default null
*/
resizeTo?: Window | HTMLElement;
}
/**
* Middleware for Application's resize functionality. This plugin handles automatic
* and manual resizing of your PixiJS application.
*
* Adds the following features to {@link Application}:
* - `resizeTo`: Set an element to automatically resize to
* - `resize`: Manually trigger a resize
* - `queueResize`: Queue a resize for the next animation frame
* - `cancelResize`: Cancel a queued resize
* @example
* ```ts
* import { Application, ResizePlugin } from 'pixi.js';
*
* // Create application
* const app = new Application();
*
* // Example 1: Auto-resize to window
* await app.init({ resizeTo: window });
*
* // Example 2: Auto-resize to specific element
* const container = document.querySelector('#game-container');
* await app.init({ resizeTo: container });
*
* // Example 3: Change resize target at runtime
* app.resizeTo = window; // Enable auto-resize to window
* app.resizeTo = null; // Disable auto-resize
* ```
*/
export declare class ResizePlugin {
}
/**
* Application options for the {@link TickerPlugin}.
* These options control the animation loop and update cycle of your PixiJS application.
* @example
* ```ts
* import { Application } from 'pixi.js';
*
* // Basic setup with default options
* const app = new Application();
* await app.init({
* autoStart: true, // Start animation loop automatically
* sharedTicker: false // Use dedicated ticker instance
* });
*
* // Advanced setup with shared ticker
* const app2 = new Application();
* await app2.init({
* autoStart: false, // Don't start automatically
* sharedTicker: true // Use global shared ticker
* });
*
* // Start animation when ready
* app2.start();
* ```
* @remarks
* The ticker is the heart of your application's animation system. It:
* - Manages the render loop
* - Provides accurate timing information
* - Handles frame-based updates
* - Supports priority-based execution order
*/
export interface TickerPluginOptions {
/**
* Controls whether the animation loop starts automatically after initialization.
* > [!IMPORTANT]
* > Setting this to `false` does NOT stop the shared ticker even if `sharedTicker` is `true`.
* > You must stop the shared ticker manually if needed.
* @example
* ```ts
* // Auto-start (default behavior)
* await app.init({ autoStart: true });
*
* // Manual start
* await app.init({ autoStart: false });
* app.start(); // Start when ready
* ```
* @default true
*/
autoStart?: boolean;
/**
* Controls whether to use the shared global ticker or create a new instance.
*
* The shared ticker is useful when you have multiple instances that should sync their updates.
* However, it has some limitations regarding update order control.
*
* Update Order:
* 1. System ticker (always runs first)
* 2. Shared ticker (if enabled)
* 3. App ticker (if using own ticker)
* @example
* ```ts
* // Use shared ticker (global instance)
* await app.init({ sharedTicker: true });
*
* // Use dedicated ticker (default)
* await app.init({ sharedTicker: false });
*
* // Access ticker properties
* console.log(app.ticker.FPS); // Current FPS
* console.log(app.ticker.deltaMS); // MS since last update
* ```
* @default false
*/
sharedTicker?: boolean;
}
/**
* Middleware for Application's {@link Ticker} functionality. This plugin manages the
* animation loop and update cycle of your PixiJS application.
*
* Adds the following features to {@link Application}:
* - `ticker`: Access to the application's ticker
* - `start`: Start the animation loop
* - `stop`: Stop the animation loop
* @example
* ```ts
* import { Application, TickerPlugin, extensions } from 'pixi.js';
*
* // Create application
* const app = new Application();
*
* // Example 1: Basic ticker usage (default autoStart)
* await app.init({ autoStart: true }); // Starts ticker automatically
*
* // Example 2: Manual ticker control
* await app.init({ autoStart: false }); // Don't start automatically
* app.start(); // Start manually
* app.stop(); // Stop manually
*
* // Example 3: Add custom update logic
* app.ticker.add((ticker) => {
* // Run every frame, delta is the time since last update
* sprite.rotation += 0.1 * ticker.deltaTime;
* });
*
* // Example 4: Control update priority
* import { UPDATE_PRIORITY } from 'pixi.js';
*
* app.ticker.add(
* (ticker) => {
* // Run before normal priority updates
* },
* null,
* UPDATE_PRIORITY.HIGH
* );
*
* // Example 5: One-time update
* app.ticker.addOnce(() => {
* console.log('Runs next frame only');
* });
* ```
*/
export declare class TickerPlugin {
}
declare global {
namespace PixiMixins {
// Extend the Application interface with resize and ticker functionalities
interface Application {
/**
* Element to automatically resize the renderer to.
* @example
* ```ts
* const app = new Application();
* await app.init({
* resizeTo: window, // Resize to the entire window
* // or
* resizeTo: document.querySelector('#game-container'), // Resize to a specific element
* // or
* resizeTo: null, // Disable auto-resize
* });
* ```
* @default null
*/
resizeTo: Window | HTMLElement;
/**
* Element to automatically resize the renderer to.
* > [!IMPORTANT]
* > You do not need to call this method manually in most cases.
* > A `resize` event will be dispatched automatically when the `resizeTo` element changes size.
* @remarks
* - Automatically resizes the renderer to match the size of the `resizeTo` element
* - If `resizeTo` is `null`, auto-resizing is disabled
* - If `resizeTo` is a `Window`, it resizes to the full window size
* - If `resizeTo` is an `HTMLElement`, it resizes to the element's bounding client rectangle
* @example
* ```ts
* const app = new Application();
* await app.init({
* resizeTo: window, // Resize to the entire window
* // or
* resizeTo: document.querySelector('#game-container'), // Resize to a specific element
* // or
* resizeTo: null, // Disable auto-resize
* });
*
* // Manually trigger a resize
* app.resize();
* ```
* @default null
*/
resize(): void;
/**
* Queue a resize operation for the next animation frame. This method is throttled
* and optimized for frequent calls.
* > [!IMPORTANT]
* > You do not need to call this method manually in most cases.
* > A `resize` event will be dispatched automatically when the `resizeTo` element changes size.
* @remarks
* - Safe to call multiple times per frame
* - Only one resize will occur on next frame
* - Cancels any previously queued resize
* @example
* ```ts
* app.queueResize(); // Queue for next frame
* ```
*/
queueResize(): void;
/**
* Cancel any pending resize operation that was queued with `queueResize()`.
* @remarks
* - Clears the resize operation queued for next frame
* @example
* ```ts
* // Queue a resize
* app.queueResize();
*
* // Cancel if needed
* app.cancelResize();
* ```
*/
cancelResize(): void;
/**
* The application's ticker instance that manages the update/render loop.
* @example
* ```ts
* // Basic animation
* app.ticker.add((ticker) => {
* sprite.rotation += 0.1 * ticker.deltaTime;
* });
*
* // Control update priority
* app.ticker.add(
* (ticker) => {
* // Physics update (runs first)
* },
* undefined,
* UPDATE_PRIORITY.HIGH
* );
*
* // One-time update
* app.ticker.addOnce(() => {
* console.log('Runs next frame only');
* });
*
* // Access timing info
* console.log(app.ticker.FPS); // Current FPS
* console.log(app.ticker.deltaTime); // Scaled time delta
* console.log(app.ticker.deltaMS); // MS since last update
* ```
*/
ticker: Ticker;
/**
* Stops the render/update loop.
* @example
* ```ts
* // Stop the application
* app.stop();
* // ... custom update logic ...
* app.render(); // Manual render
* ```
*/
stop(): void;
/**
* Starts the render/update loop.
* @example
* ```ts
* // Initialize without auto-start
* await app.init({ autoStart: false });
*
* // Start when ready
* app.start();
* ```
*/
start(): void;
}
// Combine ResizePluginOptions and TickerPluginOptions into ApplicationOptions
interface ApplicationOptions extends ResizePluginOptions, TickerPluginOptions {
}
}
}
declare global {
namespace PixiMixins {
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
interface AssetsPreferences {
}
}
}
/**
* The CullingMixin interface provides properties and methods for managing culling behavior
* of a display object. Culling is the process of determining whether an object should be rendered
* based on its visibility within the current view or frame.
*
* Key Features:
* - Custom culling areas for better performance
* - Per-object culling control
* - Child culling management
* @example
* ```ts
* // Enable culling for a container
* const container = new Container();
* container.cullable = true;
*
* // Set custom cull area for better performance
* container.cullArea = new Rectangle(0, 0, 800, 600);
*
* // Disable child culling for static scenes
* container.cullableChildren = false;
* ```
*/
export interface CullingMixinConstructor {
/**
* Custom shape used for culling calculations instead of object bounds.
* Defined in local space coordinates relative to the object.
* > [!NOTE]
* > Setting this to a custom Rectangle allows you to define a specific area for culling,
* > which can improve performance by avoiding expensive bounds calculations.
* @example
* ```ts
* const container = new Container();
*
* // Define custom culling boundary
* container.cullArea = new Rectangle(0, 0, 800, 600);
*
* // Reset to use object bounds
* container.cullArea = null;
* ```
* @remarks
* - Improves performance by avoiding bounds calculations
* - Useful for containers with many children
* - Set to null to use object bounds
* @default null
*/
cullArea: Rectangle;
/**
* Controls whether this object should be culled when out of view.
* When true, the object will not be rendered if its bounds are outside the visible area.
* @example
* ```ts
* const sprite = new Sprite(texture);
*
* // Enable culling
* sprite.cullable = true;
*
* // Force object to always render
* sprite.cullable = false;
* ```
* @remarks
* - Does not affect transform updates
* - Applies to this object only
* - Children follow their own cullable setting
* @default false
*/
cullable: boolean;
/**
* Controls whether children of this container can be culled.
* When false, skips recursive culling checks for better performance.
* @example
* ```ts
* const container = new Container();
*
* // Enable container culling
* container.cullable = true;
*
* // Disable child culling for performance
* container.cullableChildren = false;
*
* // Children will always render if container is visible
* container.addChild(sprite1, sprite2, sprite3);
* ```
* @remarks
* - Improves performance for static scenes
* - Useful when children are always within container bounds
* - Parent culling still applies
* @default true
*/
cullableChildren: boolean;
}
declare global {
namespace PixiMixins {
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
interface Container extends Partial {
}
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
interface ContainerOptions extends Partial {
}
}
}
/**
* Options for configuring a {@link DOMContainer}.
* Controls how DOM elements are integrated into the PixiJS scene graph.
* @example
* ```ts
* // Create with a custom element
* const domContainer = new DOMContainer({
* element: document.createElement('input'),
* anchor: { x: 0.5, y: 0.5 } // or anchor: 0.5 to center both x and y
* });
* ```
*/
export interface DOMContainerOptions extends ViewContainerOptions {
/**
* The DOM element to use for the container.
* Can be any HTML element like div, input, textarea, etc.
*
* If not provided, creates a new div element.
* @default document.createElement('div')
*/
element?: HTMLElement;
/**
* The anchor point of the container.
* - Can be a single number to set both x and y
* - Can be a point-like object with x,y coordinates
* - (0,0) is top-left
* - (1,1) is bottom-right
* - (0.5,0.5) is center
* @default 0
*/
anchor?: PointData | number;
}
/**
* The DOMContainer object is used to render DOM elements within the PixiJS scene graph.
* It allows you to integrate HTML elements into your PixiJS application while maintaining
* proper transform hierarchy and visibility.
*
* DOMContainer is especially useful for rendering standard DOM elements
* that handle user input, such as `` or `