# 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. ## 生态系统 PixiJS 本身只是一个渲染引擎。但是,有一个强大的库和工具生态系统可以增强和扩展其功能。这些工具与 PixiJS 无缝集成,使开发者能够轻松创建更丰富、更具交互性的应用。 ¥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} ¥Core Ecosystem Libraries ### [DevTools](https://pixijs.io/devtools/) {#devtoolshttpspixijsiodevtools} 使用 DevTools 优化和调试你的 PixiJS 项目。此浏览器扩展程序提供对应用性能、渲染层次结构和纹理管理的实时洞察,确保你的项目顺利运行。 ¥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 集成](https:/react.pixijs.io/) {#react-integrationhttpsreactpixijsio} ¥[React Integration](https:/react.pixijs.io/) :::info 信息 PixiJS React 需要 React 19 或更高版本。 ¥PixiJS React requires React 19 or higher. ::: 使用 Pixi-React 库简化 React 应用中 PixiJS 的使用。此库提供绑定,允许你将 PixiJS 组件作为 React 元素进行管理,从而轻松地将强大的图形功能集成到 React 的声明式框架中。 ¥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. ### [布局](https://layout.pixijs.io/) {#layouthttpslayoutpixijsio} ¥[Layout](https://layout.pixijs.io/) 使用 PixiJS 布局库(由 Facebook 的 [Yoga](https://www.yogalayout.dev/) 引擎提供支持)为 PixiJS 添加弹性框样式的布局。它引入了一种声明式方法,使用熟悉的类似 CSS 的规则来控制 PixiJS 显示对象的位置、对齐和大小。 ¥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: - 基于 Yoga 构建,可实现标准化、可靠的布局。 ¥Built on Yoga for standardized, reliable layouts - 完全可选:仅在需要时应用布局 ¥Fully opt-in: apply layout only where you need it - 任何 PixiJS 对象现在都可以感知布局。 ¥Any PixiJS object can now be layout-aware - 支持 PixiJS React ¥Supports PixiJS React - 新的 Web 风格功能:objectFit、objectPosition 和溢出滚动 ¥New web-style features: objectFit, objectPosition, and overflow scrolling ### [Spine 集成](https://esotericsoftware.com/spine-pixi) {#spine-integrationhttpsesotericsoftwarecomspine-pixi} ¥[Spine Integration](https://esotericsoftware.com/spine-pixi) 使用 Spine-Pixi 让动画栩栩如生。此次集成整合了 PixiJS 和领先的动画工具 Spine 的强大功能,为游戏和交互式内容创建流畅的基于骨骼的动画。 ¥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. ### [过滤器](https://github.com/pixijs/filters) {#filtershttpsgithubcompixijsfilters} ¥[Filters](https://github.com/pixijs/filters) 使用 PixiJS 滤镜转换你的视觉效果。这个丰富的高性能效果集合包含模糊、发光和颜色调整等选项,为你提供创建视觉震撼图形的工具。 ¥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. ### [声音](https://github.com/pixijs/sound) {#soundhttpsgithubcompixijssound} ¥[Sound](https://github.com/pixijs/sound) 使用 PixiJS Sound(一个带有滤镜的 WebAudio API 播放库)为你的项目添加音频。 ¥Add audio to your projects with PixiJS Sound a WebAudio API playback library, with filters. ### [UI](https://github.com/pixijs/ui) {#uihttpsgithubcompixijsui} 使用 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 在 PixiJS 中构建交互式界面的所有基本功能。 ¥All the essentials for building interactive interfaces in PixiJS. ### [AssetPack](https://pixijs.io/assetpack/) {#assetpackhttpspixijsioassetpack} 使用 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 用户空间](https://github.com/pixijs-userland) - 社区驱动代码库 {#pixijs-userlandhttpsgithubcompixijs-userland---community-driven-repositories} ¥[PixiJS Userland](https://github.com/pixijs-userland) - Community-Driven Repositories PixiJS Userland 是一个专门用于托管社区驱动代码库的空间。此组织允许开发者在 PixiJS 相关项目上进行协作,并与更广泛的社区分享他们的工作。 ¥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. 如果你对新的库或工具有想法,你可以申请访问 PixiJS Userland,以便在组织内创建和维护代码库。这是一个为不断发展的 PixiJS 生态系统做出贡献并与志同道合的开发者交流的绝佳机会。 ¥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. 请注意,用户空间代码库由社区驱动,可能未与最新的 PixiJS 版本保持同步。但是,它们为希望增强其 PixiJS 项目的开发者提供了丰富的资源和灵感。 ¥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} ¥Getting Started with the Ecosystem 要探索这些库,请访问其各自的文档和 GitHub 存储库,获取安装说明和使用指南。此外,PixiJS 提供从 [**创建模板**](https://pixijs.io/create-pixi/docs/guide/creations/intro/) 到 [PixiJS Create CLI](https://pixijs.io/create-pixi/) 的 [**创建模板**](https://pixijs.io/create-pixi/docs/guide/creations/intro/) 版本,将许多库组合成预配置的设置,非常适合特定用例和平台。 ¥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. 为了获得灵感,你还可以查看 [open-games 仓库](https://github.com/pixijs/open-games),它展示了使用 PixiJS 及其生态系统库构建的各种游戏。 ¥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 --- ## 在线试用 PixiJS {#try-pixijs-online} ¥Try PixiJS Online - 要快速体验 PixiJS,你可以直接在我们的 [PixiJS 在线运行](/8.x/playground) 中尝试。 ¥To quickly get a taste of PixiJS, you can try it directly in our [PixiJS Playground](/8.x/playground). --- ## 创建新项目 {#creating-a-new-project} ¥Creating a New Project :::info[先决条件] - 熟悉命令行并对 JavaScript 有基本的了解。 ¥Familiarity with the command line and a basic understanding of JavaScript. - 安装 [Node.js](https://nodejs.cn/) v20.0 或更高版本。::: ¥Install [Node.js](https://nodejs.cn/) v20.0 or higher. ::: 在本节中,我们将介绍如何在本地机器上搭建 PixiJS 应用。创建的项目将使用预配置的构建设置,让你快速开始 PixiJS 开发。 ¥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 ``` 此命令将安装并执行 [PixiJS Create](https://pixijs.io/create-pixi/) CLI,并开始构建你的项目。系统将提示你通过选择各种选项来配置项目,包括选择用于设置项目的模板类型。主要有两种类型的模板可供选择: ¥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 ``` 你还可以将 PixiJS 添加到现有项目中: ¥You can also add PixiJS to an existing project: ```bash npm install pixi.js ``` ## 用法 {#usage} ¥Usage 设置好项目后,以下是一个简单的 PixiJS 入门示例: ¥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 警告 如果使用 Vite,你仍然需要将代码封装在异步函数中。在生产环境中构建时,使用 PixiJS 的顶层 await 会出现问题。 ¥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. 已知此问题会影响 Vite \<=6.0.6。Vite 的未来版本可能会解决此问题。 ¥This issue is known to affect Vite \<=6.0.6. Future versions of Vite may resolve this issue. ::: --- ## 架构 {#architecture} # 架构 {#architecture} ¥Architecture 以下是构成 PixiJS 的主要组件的列表。请注意,此列表并不详尽。此外,不必太担心每个组件的工作原理。这里的目标是让你在我们开始探索引擎时了解引擎盖下的内容。 ¥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} ¥Major Components | 组件 | 描述 | | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------- | | **渲染器** | PixiJS 系统的核心是渲染器,它显示场景图并将其绘制到屏幕上。PixiJS 会自动决定是否在后台为你提供 WebGPU 或 WebGL 渲染器。 | | **容器** | 创建场景图的主场景对象:要显示的可渲染对象树,例如精灵、图形和文本。详细信息请参见 [场景图](scene-graph)。 | | **资源** | Asset 系统提供了异步加载图片、音频文件等资源的工具。 | | **股票行情指示器** | 代码提供基于时钟的定期回调。你的游戏更新逻辑通常会响应每帧一次的勾选而运行。你可以同时使用多个代码。 | | **应用** | 该应用是一个简单的辅助程序,它将加载器、Ticker 和 Renderer 封装到一个方便易用的对象中。非常适合快速入门、原型设计和构建简单的项目。 | | **事件** | PixiJS 支持基于指针的交互 - 使对象可点击、触发悬停事件等。 | | **无障碍** | 我们的显示系统中包含了一组丰富的工具,用于实现键盘和屏幕阅读器的可访问性。 | | **过滤器** | PixiJS 支持多种滤镜,包括自定义着色器,可将效果应用于可渲染对象。 | ## 扩展 {#extensions} ¥Extensions PixiJS v8 完全基于扩展概念构建。PixiJS 中的每个系统都以模块化扩展的形式实现。这使得 PixiJS 保持轻量级、灵活且易于扩展。 ¥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 信息 在大多数情况下,除非你正在开发第三方库或为 PixiJS 生态系统本身做出贡献,否则你无需直接与扩展系统交互。 ¥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} ¥Extension Types PixiJS 支持多种扩展类型,每种扩展类型在架构中都发挥着独特的作用: ¥PixiJS supports a wide range of extension types, each serving a unique role in the architecture: ### 资源 {#assets} ¥Assets - `ExtensionType.Asset`:将加载器、解析器、缓存和检测扩展组合成一个方便的对象,无需单独注册每个对象。 ¥`ExtensionType.Asset`: Groups together loaders, resolvers, cache and detection extensions into one convenient object instead of having to register each one separately. - `ExtensionType.LoadParser`:加载图片、JSON、视频等资源。 ¥`ExtensionType.LoadParser`: Loads resources like images, JSON, videos. - `ExtensionType.ResolveParser`:将资源 URL 转换为加载器可以使用的格式。 ¥`ExtensionType.ResolveParser`: Converts asset URLs into a format that can be used by the loader. - `ExtensionType.CacheParser`:确定特定资源的缓存行为。 ¥`ExtensionType.CacheParser`: Determines caching behavior for a particular asset. - `ExtensionType.DetectionParser`:标识当前平台上的资源格式支持。 ¥`ExtensionType.DetectionParser`: Identifies asset format support on the current platform. ### 渲染器 (WebGL、WebGPU、Canvas) {#renderer-webgl-webgpu-canvas} ¥Renderer (WebGL, WebGPU, Canvas) - `ExtensionType.WebGLSystem`, `ExtensionType.WebGPUSystem`, `ExtensionType.CanvasSystem`:将系统添加到相应的渲染器。这些系统的功能差异很大,从管理纹理到辅助功能。 ¥`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`:添加新的渲染管道。RenderPipes 专门用于渲染网格等可渲染对象。 ¥`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`:根据相应的渲染器调整渲染管道。 ¥`ExtensionType.WebGLPipesAdaptor`, `ExtensionType.WebGPUPipesAdaptor`, `ExtensionType.CanvasPipesAdaptor`: Adapt rendering pipes for the respective renderers. ### 应用 {#application} ¥Application - `ExtensionType.Application`:用于扩展 `Application` 生命周期的插件。例如,`TickerPlugin` 和 `ResizePlugin` 都是应用扩展。 ¥`ExtensionType.Application`: Used for plugins that extend the `Application` lifecycle. For example the `TickerPlugin` and `ResizePlugin` are both application extensions. ### 环境 {#environment} ¥Environment - `ExtensionType.Environment`:用于检测和配置特定于平台的行为。这对于配置 PixiJS 以在 Node.js、Web Workers 或浏览器等环境中工作非常有用。 ¥`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} ¥Other (Primarily Internal Use) 这些扩展类型主要在内部使用,在大多数面向用户的应用中通常不需要: ¥These extension types are mainly used internally and are typically not required in most user-facing applications: - `ExtensionType.MaskEffect`:由 MaskEffectManager 用于自定义遮罩行为。 ¥`ExtensionType.MaskEffect`: Used by MaskEffectManager for custom masking behaviors. - `ExtensionType.BlendMode`:一种用于创建新的高级混合模式的扩展。 ¥`ExtensionType.BlendMode`: A type of extension for creating a new advanced blend mode. - `ExtensionType.TextureSource`:一种用于自动检测资源类型的扩展,例如 `VideoSource` ¥`ExtensionType.TextureSource`: A type of extension that will be used to auto detect a resource type E.g `VideoSource` - `ExtensionType.ShapeBuilder`:一种用于构建和三角剖分图形中使用的自定义形状的扩展。 ¥`ExtensionType.ShapeBuilder`: A type of extension for building and triangulating custom shapes used in graphics. - `ExtensionType.Batcher`:一种用于创建渲染中使用的自定义批处理器的扩展。 ¥`ExtensionType.Batcher`: A type of extension for creating custom batchers used in rendering. ## 创建扩展 {#creating-extensions} ¥Creating Extensions PixiJS 中的 `extensions` 对象是用于管理扩展的全局注册表。扩展必须声明一个包含元数据的 `extension` 字段,并通过 `extensions.add(...)` 注册。 ¥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); ``` --- ## 环境 # 在不同环境中使用 PixiJS {#using-pixijs-in-different-environments} ¥Using PixiJS in Different Environments PixiJS 是一个高度适应性的库,可以在各种环境中运行,包括浏览器、Web Workers 和自定义执行上下文(如 Node.js)。本指南解释 PixiJS 如何处理不同的环境,以及如何配置它以满足你的应用需求。 ¥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. ## 在浏览器中运行 PixiJS {#running-pixijs-in-the-browser} ¥Running PixiJS in the Browser 对于浏览器环境,PixiJS 默认使用 `BrowserAdapter`,你无需进行任何配置。 ¥For browser environments, PixiJS uses the `BrowserAdapter` by default, you should not need to configure anything ### 示例: {#example} ¥Example: ```typescript import { Application } from 'pixi.js'; const app = new Application(); await app.init({ width: 800, height: 600, }); document.body.appendChild(app.canvas); ``` ## 在 Web Workers 中运行 PixiJS {#running-pixijs-in-web-workers} ¥Running PixiJS in Web Workers Web Workers 提供并行执行环境,非常适合卸载渲染任务。PixiJS 使用 `WebWorkerAdapter` 支持 Web Workers: ¥Web Workers provide a parallel execution environment, ideal for offloading rendering tasks. PixiJS supports Web Workers using the `WebWorkerAdapter`: ### 示例: {#example-1} ¥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} ¥Custom Environments 对于非标准环境,你可以通过实现 `Adapter` 接口来创建自定义适配器。这使得 PixiJS 能够在 Node.js 或无头测试设置等环境中运行。 ¥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} ¥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); ``` --- ## 垃圾合集 # 在 PixiJS 中管理垃圾回收 {#managing-garbage-collection-in-pixijs} ¥Managing Garbage Collection in PixiJS 高效的资源管理对于在任何 PixiJS 应用中保持最佳性能都至关重要。本指南探讨了 PixiJS 如何处理垃圾回收、它提供的工具以及有效管理 GPU 资源的最佳实践。 ¥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. ## 使用 `destroy` 进行显式资源管理 {#explicit-resource-management-with-destroy} ¥Explicit Resource Management with `destroy` PixiJS 对象(例如纹理、网格和其他 GPU 支持的数据)会保存占用内存的引用。要明确释放这些资源,请在不再需要的对象上调用 `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(); ``` 调用 `destroy` 可确保立即释放对象的 GPU 资源,从而降低内存泄漏的可能性并提高性能。 ¥Calling `destroy` ensures that the object’s GPU resources are freed immediately, reducing the likelihood of memory leaks and improving performance. ## 使用 `texture.unload` 管理纹理 {#managing-textures-with-textureunload} ¥Managing Textures with `texture.unload` 如果 PixiJS 的自动纹理垃圾收集功能不足,你可以使用 `texture.unload()` 手动从 GPU 卸载纹理: ¥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. ## 使用 `TextureGCSystem` 自动进行纹理垃圾回收 {#automatic-texture-garbage-collection-with-texturegcsystem} ¥Automatic Texture Garbage Collection with `TextureGCSystem` PixiJS 还包含 `TextureGCSystem`,这是一个管理 GPU 纹理内存的系统。默认情况下: ¥PixiJS also includes the `TextureGCSystem`, a system that manages GPU texture memory. By default: - 移除 3600 帧(约 1 小时,60 FPS)内未使用的纹理。 ¥**Removes textures unused for 3600 frames** (approximately 1 hour at 60 FPS). - 每 600 帧检查一次未使用的纹理。 ¥**Checks every 600 frames** for unused textures. ### 自定义 `TextureGCSystem` {#customizing-texturegcsystem} ¥Customizing `TextureGCSystem` 你可以调整 `TextureGCSystem` 的行为以适合你的应用: ¥You can adjust the behavior of `TextureGCSystem` to suit your application: - `textureGCActive`:启用或禁用垃圾回收。默认:`true`。 ¥**`textureGCActive`**: Enable or disable garbage collection. Default: `true`. - `textureGCMaxIdle`:纹理清理前的最大空闲帧数。默认:`3600` 帧。 ¥**`textureGCMaxIdle`**: Maximum idle frames before texture cleanup. Default: `3600` frames. - `textureGCCheckCountMax`:垃圾回收检查频率(以帧为单位)。默认:`600` 帧。 ¥**`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 }); ``` ## 垃圾回收最佳实践 PixiJS {#best-practices-for-garbage-collection-in-pixijs} ¥Best Practices for Garbage Collection in PixiJS 1. 明确销毁对象:始终对不再需要的对象调用 `destroy`,以确保及时释放 GPU 资源。 ¥**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. 主动管理纹理:必要时使用 `texture.unload()` 进行手动内存管理。 ¥**Proactively Manage Textures:** Use `texture.unload()` for manual memory management when necessary. 通过遵循这些实践并了解 PixiJS 的垃圾收集机制,你可以创建高效利用系统资源的高性能应用。 ¥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} ¥Performance Tips ### 一般的 {#general} ¥General - 仅在需要时进行优化!PixiJS 可以立即处理大量内容 ¥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 - 顺序可以提供帮助,例如 sprite/graphic/sprite/graphic 比 sprite/sprite/graphic/graphic 慢 ¥Order can help, for example sprite / graphic / sprite / graphic is slower than sprite / sprite / graphic / graphic - 一些较旧的移动设备运行速度稍慢。将选项 `useContextAlpha: false` 和 `antialias: false` 传递给渲染器或应用可以帮助提高性能 ¥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 - 默认情况下禁用剔除,因为通常最好在应用级别执行此操作或将对象设置为 `cullable = true`。如果你受 GPU 限制,它将提高性能;如果你受 CPU 限制,则会降低性能 ¥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} ¥Sprites - 尽可能使用 Spritesheets 来最小化总纹理 ¥Use Spritesheets where possible to minimize total textures - 精灵可以使用最多 16 种不同的纹理进行批处理(取决于硬件) ¥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 - 将扩展名 `@0.5x.png` 添加到缩小 50% 的 spritesheet 中,这样 PixiJS 就会自动在视觉上将它们加倍 ¥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 - 图形对象在不经常修改时速度最快(不包括变换、alpha 或色调!) ¥Graphics objects are fastest when they are not modified constantly (not including the transform, alpha or tint!) - 图形对象在低于一定大小(100 点或更小)时进行批处理 ¥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} ¥Texture - 纹理由纹理垃圾收集器自动管理 ¥Textures are automatically managed by a Texture Garbage Collector - 你也可以使用 `texture.destroy()` 自行管理它们 ¥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} ¥Text - 避免在每一帧上更改它,因为这可能会很昂贵(每次绘制到画布然后上传到 GPU 时) ¥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 - 文本分辨率与渲染器分辨率相匹配,可以通过设置 `resolution` 属性自行降低分辨率,这样可以消耗更少的内存 ¥Text resolution matches the renderer resolution, decrease resolution yourself by setting the `resolution` property, which can consume less memory ### 面具 {#masks} ¥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} ¥Filters - 释放内存:`container.filters = null` ¥Release memory: `container.filters = null` - 如果你知道它们的大小:`container.filterArea = new Rectangle(x,y,w,h)`。这可以加快速度,因为这意味着不需要测量对象 ¥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 {#blendmodes} - 不同的混合模式会导致批次中断(去优化) ¥Different blend modes will cause batches to break (de-optimize) - ScreenSprite / NormalSprite / ScreenSprite / NormalSprite 将是 4 次绘制调用 ¥ScreenSprite / NormalSprite / ScreenSprite / NormalSprite would be 4 draw calls - ScreenSprite / ScreenSprite / NormalSprite / NormalSprite 将是 2 次绘制调用 ¥ScreenSprite / ScreenSprite / NormalSprite / NormalSprite would be 2 draw calls ### 事件 {#events} ¥Events - 如果对象没有交互式子对象,则使用 `interactiveChildren = false`。然后事件系统将能够避免爬行对象 ¥If an object has no interactive children use `interactiveChildren = false`. The event system will then be able to avoid crawling through the object - 如上所述设置 `hitArea = new Rectangle(x,y,w,h)` 应该会阻止事件系统爬行对象 ¥Setting `hitArea = new Rectangle(x,y,w,h)` as above should stop the event system from crawling through the object --- ## 渲染群组 {#render-groups} # 渲染群组 {#render-groups} ¥Render Groups ## 了解 PixiJS 中的 RenderGroups {#understanding-rendergroups-in-pixijs} ¥Understanding RenderGroups in PixiJS 当你深入研究 PixiJS(尤其是版本 8)时,你将遇到一个称为 RenderGroups 的强大功能。将渲染组视为场景图中的专用容器,其行为类似于迷你场景图本身。为了在项目中有效地使用渲染组,你需要了解以下内容: ¥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} ¥What Are Render Groups? 渲染组本质上是 PixiJS 视为独立场景图的容器。当你将场景的一部分分配给渲染组时,你就是在告诉 PixiJS 将这些对象作为一个单元进行管理。这种管理包括监视变化以及专门为该组准备一组渲染指令。这是优化渲染过程的强大工具。 ¥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} ¥Why Use Render Groups? 使用渲染组的主要优点在于其优化功能。它们允许将某些计算(例如变换(位置、缩放、旋转)、色调和 Alpha 调整)卸载到 GPU。这意味着移动或调整渲染组等操作可以在对 CPU 影响最小的情况下完成,从而使你的应用性能更加高效。 ¥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. 实际上,即使没有明确的意识,你也会使用渲染组。你传递给 PixiJS 渲染函数的根元素会自动转换为 RenderGroup,因为这是其渲染指令将存储的位置。不过,你还可以选择根据需要显式创建其他渲染组以进一步优化你的项目。 ¥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: - 静态内容:对于不经常更改的内容,渲染组可以显着减少 CPU 的计算负载。在这种情况下,静态指的是场景图结构,而不是其中 PixiJS 元素的实际值(例如位置、事物的比例)。 ¥**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). - 独特的场景部分:你可以将场景分成逻辑部分,例如游戏世界和 HUD(平视显示器)。每个部分都可以单独优化,从而获得更好的整体性能。 ¥**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} ¥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 ``` 看看 [容器示例](../../examples/basic/container)。 ¥Check out the [container example](../../examples/basic/container). ### 最佳实践 {#best-practices} ¥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. 通过了解和利用渲染组,你可以充分利用 PixiJS 的渲染功能,使你的应用更流畅、更高效。此功能是 PixiJS 提供的优化工具包中的一个强大工具,使开发者能够创建在不同设备上流畅运行的丰富的交互式场景。 ¥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} ¥Render Layers PixiJS Layer API 提供了一种强大的方法来控制对象的渲染顺序,而不受场景图中逻辑父子关系的影响。使用 RenderLayers,你可以将对象的转换方式(通过其逻辑父级)与它们在屏幕上的可视化绘制方式分离开来。 ¥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. 使用 RenderLayers 可确保这些元素在视觉上具有优先级,同时保持逻辑上的父子关系。示例包括: ¥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 元素,如分数计数器或通知:无论游戏世界的复杂程度如何,都让它们保持可见。 ¥UI elements like score counters or notifications: Keep them visible regardless of the game world’s complexity. - 教程中的高亮元素:想象一下,在一个教程中,你需要在高亮特定对象的同时推回大多数游戏元素。RenderLayers 可以直观地拆分这些。高亮的对象可以放置在前景图层中,以在推回图层上方进行渲染。 ¥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. 本指南解释了关键概念,提供了实际示例,并强调了常见的陷阱,以帮助你有效地使用 Layer API。 ¥This guide explains the key concepts, provides practical examples, and highlights common gotchas to help you use the Layer API effectively. --- ### **关键概念** {#key-concepts} ¥**Key Concepts** 1. 独立渲染顺序: ¥**Independent Rendering Order**: - RenderLayers 允许独立于逻辑层次结构控制绘制顺序,确保对象按所需顺序渲染。 ¥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**: - 即使附加到 RenderLayers,对象也会从其逻辑父级保持变换(例如,位置、比例、旋转)。 ¥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**: - 在层内,可以使用 `zIndex` 和 `sortChildren` 动态重新排序对象,以细粒度控制渲染顺序。 ¥Within layers, objects can be dynamically reordered using `zIndex` and `sortChildren` for fine-grained control of rendering order. --- ### **基本 API 使用** {#basic-api-usage} ¥**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); ``` ![alt text](render-layers/image-1.png) 现在我们知道红色人将首先被渲染,然后是蓝色人。现在在这个简单的例子中,你只需对红色人和蓝色人的 `zIndex` 进行排序即可帮助重新排序。 ¥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. 使用 `renderLayer.attach` 将对象分配给图层。这会覆盖由其逻辑父级定义的对象的默认渲染顺序。 ¥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); ``` ![alt text](render-layers/image-2.png) 所以现在我们的场景图顺序是: ¥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.** {#3-removing-objects-from-a-layer} 现在让我们从图层中删除红色人。要阻止对象在图层中渲染,请使用 `removeFromLayer`。从图层中移除后,对象仍将位于场景图中,并将按照其场景图顺序进行渲染。 ¥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 ``` ![alt text](render-layers/image-1.png) 从逻辑父级(`removeChild`)中移除对象会自动将其从图层中移除。 ¥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 ``` ![alt text](render-layers/image-3.png) 但是,如果你从舞台上移除红色人,然后将其添加回舞台,它将不会再次添加到图层中。 ¥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); ``` ![alt text](render-layers/image-1.png) 你需要自己将其重新连接到层。 ¥You will need to reattach it to the layer yourself. ```typescript layer.attach(redGuy); // re attach it to the layer again! ``` ![alt text](render-layers/image-2.png) 这看起来很麻烦,但实际上是一件好事。这意味着你可以完全控制对象的渲染顺序,并且可以随时更改它。这也意味着你不会意外将对象添加到容器中,并让它自动重新附加到可能仍然存在也可能不存在的层 - 这会相当混乱,并导致一些很难调试的错误! ¥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.** {#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); ``` ![alt text](render-layers/image-1.png) ### **完整示例** {#complete-example} ¥**Complete Example** 这是一个真实的例子,展示了如何使用 RenderLayers 将 ap 播放器 ui 设置在世界之巅。 ¥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} ¥**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**: - 可以使用图层中的对象的 `zIndex` 属性动态排序。这对于细粒度控制渲染顺序很有用。 ¥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} ¥**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. 通过理解和有效利用 RenderLayers,你可以精确控制场景的视觉渲染,同时保持干净、合乎逻辑的层次结构。 ¥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} ¥Render Loop PixiJS 的核心在于其渲染循环,这是一个重复的循环,它会每帧更新并重新绘制场景。与基于事件(例如基于用户输入)渲染的传统 Web 开发不同,PixiJS 使用连续动画循环,可以完全控制实时渲染。 ¥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. 本指南深入探讨了 PixiJS 如何构建这个内部循环,从帧开始到渲染到屏幕。理解这一点将有助于你编写性能更佳、结构更合理的应用。 ¥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} ¥Overview PixiJS 每帧都会执行以下顺序: ¥Each frame, PixiJS performs the following sequence: 1. 代码执行(用户逻辑) ¥**Tickers are executed** (user logic) 2. 场景图已更新(变换和剔除) ¥**Scene graph is updated** (transforms and culling) 3. 渲染发生(GPU 绘制调用) ¥**Rendering occurs** (GPU draw calls) 只要你的应用正在运行且其代码块处于活动状态,此循环就会重复。 ¥This cycle repeats as long as your application is running and its ticker is active. ## 步骤 1:运行股票代码回调 {#step-1-running-ticker-callbacks} ¥Step 1: Running Ticker Callbacks 渲染循环由 `Ticker` 类驱动,该类使用 `requestAnimationFrame` 来调度工作。每次 tick: ¥The render loop is driven by the `Ticker` class, which uses `requestAnimationFrame` to schedule work. Each tick: - 测量自上一帧以来经过的时间 ¥Measures elapsed time since the previous frame - 基于 `minFPS` 和 `maxFPS` 进行限制 ¥Caps it based on `minFPS` and `maxFPS` - 调用每个在 `ticker.add()` 或 `app.ticker.add()` 中注册的监听器 ¥Calls every listener registered with `ticker.add()` or `app.ticker.add()` ### 示例 {#example} ¥Example ```ts app.ticker.add((ticker) => { bunny.rotation += ticker.deltaTime * 0.1; }); ``` 每个回调都会接收当前的 `Ticker` 实例。你可以访问 `ticker.deltaTime`(缩放的帧增量)和 `ticker.elapsedMS`(未缩放的增量,以毫秒为单位)来控制动画的时间。 ¥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. ## 步骤 2:更新场景图 {#step-2-updating-the-scene-graph} ¥Step 2: Updating the Scene Graph PixiJS 使用分层场景图来表示所有可视对象。渲染前,需要遍历图形: ¥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) - 通过 `onRender` 处理程序应用自定义逻辑 ¥Apply custom logic via `onRender` handlers - 如果启用,则应用剔除 ¥Apply culling if enabled ## 步骤 3:渲染场景 {#step-3-rendering-the-scene} ¥Step 3: Rendering the Scene 场景图准备就绪后,渲染器将从 `app.stage` 开始遍历显示列表: ¥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. 上传几何体、纹理和 uniform ¥Uploads geometry, textures, and uniforms 4. 发出 GPU 命令 ¥Issues GPU commands 所有渲染均采用保留模式:除非明确移除,否则对象会跨帧保留。 ¥All rendering is **retained mode**: objects persist across frames unless explicitly removed. 渲染通过 WebGL 或 WebGPU 完成,具体取决于你的环境。渲染器将差异抽象到通用 API 背后。 ¥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} ¥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} ¥Scene Graph 每一帧,PixiJS 都会更新并渲染场景图。让我们讨论一下场景图中的内容,以及它如何影响你开发项目的方式。如果你以前构建过游戏,这听起来应该非常熟悉,但如果你来自 HTML 和 DOM,那么在我们讨论可以渲染的特定对象类型之前,值得先了解一下。 ¥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 Is a Tree 场景图的根节点是由应用维护的容器,并用 `app.stage` 引用。当你将精灵或其他可渲染对象作为子对象添加到舞台时,它会添加到场景图中,并且将被渲染和交互。PixiJS `Containers` 也可以有子级,因此当你构建更复杂的场景时,你最终会得到一棵植根于应用阶段的父子关系树。 ¥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. (探索项目的一个有用工具是 [Pixi.js 开发工具插件](https://chrome.google.com/webstore/detail/pixijs-devtools/aamddddknhcagpehecnhphigffljadon) for Chrome,它允许你在场景图运行时实时查看和操作场景图!) ¥(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} ¥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. 每一帧,PixiJS 都会遍历场景图,从根节点向下遍历所有子节点,直至叶子节点,以计算每个对象的最终位置、旋转、可见性、透明度等。如果父级的 Alpha 设置为 0.5(使其透明度为 50%),则其所有子级也将从透明度的 50% 开始。如果将子项设置为 0.5 alpha,则它不会是 50% 透明,而是 0.5 x 0.5 = 0.25 alpha,或 75% 透明。同样,对象的位置是相对于其父对象的,因此如果将父对象的 x 位置设置为 50 像素,将子对象的 x 位置设置为 100 像素,则将以 150 像素的屏幕偏移量绘制对象, 或 50 + 100。 ¥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. 这是一个例子。我们将创建三个精灵,每个精灵都是最后一个精灵的子级,并为它们的位置、旋转、缩放和 Alpha 设置动画。即使每个精灵的属性设置为相同的值,父子链也会放大每个更改: ¥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; } }); })(); ``` 场景图中任何给定节点的累积平移、旋转、缩放和倾斜都存储在对象的 `worldTransform` 属性中。同样,累积 alpha 值存储在 `worldAlpha` 属性中。 ¥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} ¥Render Order 所以我们有一棵树要画。谁先被抽中? ¥So we have a tree of things to draw. Who gets drawn first? PixiJS 从根部向下渲染树。在每个级别,渲染当前对象,然后按插入顺序渲染每个子对象。因此,第二个子项渲染在第一个子项之上,第三个子项渲染在第二个子项之上。 ¥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. 查看此示例,其中 A 下有两个父对象 A 和 D,以及两个子对象 B 和 C: ¥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; } }); })(); ``` 如果你想重新排序子对象,可以使用 `setChildIndex()`。要在父级列表中的给定点添加子级,请使用 `addChildAt()`。最后,你可以使用 `sortableChildren` 选项并结合为每个子对象设置 `zIndex` 属性来启用对象子对象的自动排序。 ¥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 {#rendergroups} 当你深入研究 PixiJS 时,你将遇到一个称为渲染组的强大功能。将渲染组视为场景图中的专用容器,其作用类似于迷你场景图本身。以下是你在项目中有效使用渲染组需要了解的内容。欲了解更多信息,请查看 [渲染组概述](./render-groups.md) ¥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} ¥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 内置支持视口剔除。要启用剔除,请在对象上设置 `cullable = true`。你还可以将 `cullableChildren` 设置为 `false`,以允许 PixiJS 绕过递归剔除函数,从而提高性能。此外,你可以通过设置 `cullArea` 来定义要剔除的区域,从而进一步优化性能。 ¥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} ¥Local vs Global Coordinates 如果你将精灵添加到舞台,默认情况下它将显示在屏幕的左上角。这就是 PixiJS 使用的全局坐标空间的起源。如果你的所有对象都是舞台的子对象,那么这是你需要担心的唯一坐标。但一旦引入容器和子元素,事情就会变得更加复杂。[50, 100] 处的子对象距离其父对象向右 50 像素,向下 100 像素。 ¥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_. 我们将这两个坐标系称为 "global" 和 "local" 坐标。当你在对象上使用 `position.set(x, y)` 时,你始终使用相对于该对象的父对象的本地坐标。 ¥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. 要从局部坐标转换为全局坐标,请使用 `toGlobal()` 函数。这是一个示例用法: ¥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)); ``` 此代码片段将 `globalPos` 设置为子对象的全局坐标,相对于全局坐标系中的 [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} ¥Global vs Screen Coordinates 当你的项目使用主机操作系统或浏览器时,就会有第三个坐标系发挥作用 - "screen" 坐标(又名 "viewport" 坐标)。屏幕坐标表示相对于 PixiJS 渲染到的画布元素左上角的位置。DOM 和原生鼠标单击事件之类的东西在屏幕空间中工作。 ¥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. 现在,在许多情况下,屏幕空间相当于世界空间。如果画布的大小与创建 `Application` 时指定的渲染视图的大小相同,就会出现这种情况。默认情况下是这样的 - 例如,你将创建一个 800x600 的应用窗口并将其添加到你的 HTML 页面,并且它将保持该大小。世界坐标中的 100 个像素将等于屏幕空间中的 100 个像素。但!通常会拉伸渲染的视图以使其填满屏幕,或者以较低的分辨率和较高的比例进行渲染以提高速度。在这种情况下,canvas 元素的屏幕大小将会改变(例如通过 CSS),但底层渲染视图不会改变,从而导致世界坐标和屏幕坐标之间不匹配。 ¥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} ¥Accessibility PixiJS 通过基于 DOM 的叠加系统内置了无障碍支持,该系统集成了屏幕阅读器、键盘导航和其他辅助技术。它使用 `` 叠加层向屏幕阅读器描述视觉元素 ¥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} ¥**How It Works** PixiJS 将 DOM `` 元素放置在画布上,并与可访问对象的边界对齐。这些元素: ¥PixiJS places DOM `` elements over your canvas, aligned to the bounds of accessible objects. These elements: - 可以通过键盘接收焦点 (`tabIndex`) ¥Can receive focus via keyboard (`tabIndex`) - 向屏幕阅读器发布 `accessibleTitle` 或 `accessibleHint` ¥Announce `accessibleTitle` or `accessibleHint` to screen readers - 将 `click`、`mouseover`、`mouseout` 事件作为 Pixi 指针事件发送 ¥Dispatch `click`, `mouseover`, `mouseout` events as Pixi pointer events - 在适当的情况下使用 `aria-live` 和 `aria-label` ¥Use `aria-live` and `aria-label` where appropriate ## 启用系统 {#enabling-the-system} ¥Enabling the System 要启用辅助功能,必须在创建渲染器之前导入该模块: ¥To enable accessibility, you must import the module before creating your renderer: ```ts import 'pixi.js/accessibility'; ``` PixiJS 会自动将 `AccessibilitySystem` 安装到你的渲染器上。你可以配置其激活方式和时间。 ¥PixiJS automatically installs the `AccessibilitySystem` onto your renderer. You can configure how and when it's activated. ## **配置选项** {#configuration-options} ¥**Configuration Options** 你可以通过向 `Application` 构造函数传递选项来自定义无障碍系统的激活时间和方式: ¥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} ¥**Creating Accessible Objects** 要将显示对象标记为可访问并将其添加到可访问性系统,请将 `accessible` 属性设置为 `true`。这将创建一个屏幕阅读器可以与之交互的 `` 叠加层。 ¥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} ¥**Properties for Accessible Containers** 你可以设置可访问容器的多个属性来自定义其行为: ¥There are several properties you can set on accessible containers to customize their behavior: | 属性 | 描述 | | ------------------------- | ------------------------------------------------ | | `accessible` | 启用对象的可访问性 | | `accessibleTitle` | 设置屏幕阅读器的 `title` | | `accessibleHint` | 设置 `aria-label` | | `accessibleText` | div 的替代内部文本 | | `accessibleType` | 用于阴影元素的标签名称(`'button'`、`'div'` 等) | | `accessiblePointerEvents` | CSS `pointer-events` 值(`'auto'`、`'none'` 等) | | `tabIndex` | 允许通过键盘导航获得焦点 | | `accessibleChildren` | 此容器的子元素是否可访问 | --- ## **API 参考** {#api-reference} ¥**API Reference** - [概述](https://pixijs.download/release/docs/accessibility.html) ¥[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} ¥Color PixiJS 中的 `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 ``` ## 使用 `Color` 和 `ColorSource` {#using-color-and-colorsource} ¥Using `Color` and `ColorSource` PixiJS 通过 `ColorSource` 类型支持多种颜色格式: ¥PixiJS supports many color formats through the `ColorSource` type: - 颜色名称:`'red'`、`'white'`、`'blue'` 等。 ¥Color names: `'red'`, `'white'`, `'blue'`, etc. - 十六进制整数:`0xffcc00` ¥Hex integers: `0xffcc00` - 十六进制字符串:`'ffcc00'`, `'#f00'`, `'0xffcc00ff'` ¥Hex strings: `'ffcc00'`, `'#f00'`, `'0xffcc00ff'` - RGB(A) 对象:`{ r: 255, g: 0, b: 0 }`, `{ r: 255, g: 0, b: 0, a: 0.5 }` ¥RGB(A) objects: `{ r: 255, g: 0, b: 0 }`, `{ r: 255, g: 0, b: 0, a: 0.5 }` - RGB(A) 字符串:`'rgb(255,0,0)'`, `'rgba(255,0,0,0.5)'` ¥RGB(A) strings: `'rgb(255,0,0)'`, `'rgba(255,0,0,0.5)'` - RGB(A) 数组:`[1, 0, 0]`, `[1, 0, 0, 0.5]` ¥RGB(A) arrays: `[1, 0, 0]`, `[1, 0, 0, 0.5]` - 类型化数组:`Uint8Array`, `Float32Array` ¥Typed arrays: `Uint8Array`, `Float32Array` - HSL/HSV 对象和字符串 ¥HSL/HSV objects and strings - `Color` 实例 ¥`Color` instances 每当看到与颜色相关的属性(例如 `fill`、`tint`、`stroke`)时,都可以使用以下任何一种格式。该库将在内部自动将它们转换为适当的格式。 ¥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 参考 {#api-reference} ¥API Reference - [颜色](https://pixijs.download/release/docs/color.Color.html) ¥[Color](https://pixijs.download/release/docs/color.Color.html) --- ## 事件/交互 {#events--interaction} # 事件/交互 {#events--interaction} ¥Events / Interaction PixiJS 主要是一个渲染库,但它提供了一个灵活且高性能的事件系统,专为鼠标和触摸输入而设计。该系统用统一的、类似 DOM 的联合事件模型取代了以前版本中遗留的 `InteractionManager`。 ¥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} ¥Event Modes 要使用事件系统,请设置 `Container`(或其子类,例如 `Sprite`)的 `eventMode` 并订阅事件监听器。 ¥To use the event system, set the `eventMode` of a `Container` (or its subclasses like `Sprite`) and subscribe to event listeners. `eventMode` 属性控制对象与事件系统的交互方式: ¥The `eventMode` property controls how an object interacts with the event system: | 模式 | 描述 | | --------- | ------------------------------------------------------------------------ | | `none` | 忽略所有交互事件,包括子对象。针对非交互元素进行了优化。 | | `passive` | (默认)忽略自身碰撞测试,不触发事件,但可交互的子对象仍会接收事件。 | | `auto` | 仅当父级可交互时才参与命中测试。不触发事件。 | | `static` | 触发事件并进行命中测试。适用于按钮等非移动交互元素。 | | `dynamic` | 与 `static` 相同,但在指针空闲时还会接收合成事件。适用于动画或移动目标。 | ## 事件类型 {#event-types} ¥Event Types PixiJS 支持丰富的类似 DOM 的事件类型,涵盖鼠标、触摸和指针输入。以下是分类列表。 ¥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} ¥Pointer Events (Recommended for general use) | 事件类型 | 描述 | | ------------------- | ------------------------------------------------- | | `pointerdown` | 当指针(鼠标、笔或触摸)在显示对象上按下时触发。 | | `pointerup` | 当指针在显示对象上释放时触发。 | | `pointerupoutside` | 当指针在接收 `pointerdown` 的对象之外释放时触发。 | | `pointermove` | 当指针移到显示对象上时触发。 | | `pointerover` | 当指针进入显示对象边界时触发。 | | `pointerout` | 当指针离开显示对象边界时触发。 | | `pointerenter` | 当指针进入显示对象时触发(不冒泡)。 | | `pointerleave` | 当指针离开显示对象时触发(不冒泡)。 | | `pointercancel` | 当指针交互取消(例如触摸丢失)时触发。 | | `pointertap` | 当指针快速点击时触发。 | | `globalpointermove` | 每次指针移动时触发,无论是否点击显示对象。 | ### 鼠标事件(已使用用于鼠标特定输入) {#mouse-events-used-for-mouse-specific-input} ¥Mouse Events (Used for mouse-specific input) | 事件类型 | 描述 | | ----------------- | --------------------------------------------------- | | `mousedown` | 在显示对象上按下鼠标按钮时触发。 | | `mouseup` | 在对象上方释放鼠标按钮时触发。 | | `mouseupoutside` | 在接收 `mousedown` 的对象外部释放鼠标按钮时触发。 | | `mousemove` | 当鼠标移到显示对象上时触发。 | | `mouseover` | 当鼠标进入显示对象时触发。 | | `mouseout` | 鼠标离开显示对象时触发。 | | `mouseenter` | 当鼠标进入对象时触发,不冒泡。 | | `mouseleave` | 鼠标离开对象时触发,不会冒泡。 | | `click` | 当鼠标点击(按下并释放)对象时触发。 | | `rightdown` | 当在显示对象上按下鼠标右键时触发。 | | `rightup` | 鼠标右键在对象上松开时触发。 | | `rightupoutside` | 当在接收 `rightdown` 的对象之外释放鼠标右键时触发。 | | `rightclick` | 当鼠标右键单击(按下并释放)对象时触发。 | | `globalmousemove` | 每次鼠标移动时触发,无论是否点击显示对象。 | | `wheel` | 当鼠标滚轮在显示对象上滚动时触发。 | ### 触摸事件 {#touch-events} ¥Touch Events | 事件类型 | 描述 | | ----------------- | -------------------------------------------------- | | `touchstart` | 当新的触摸点放置在显示对象上时触发。 | | `touchend` | 当触摸点从显示对象上抬起时触发。 | | `touchendoutside` | 当触摸点在接收 `touchstart` 的对象之外结束时触发。 | | `touchmove` | 当触摸点在显示对象上移动时触发。 | | `touchcancel` | 当触摸交互取消(例如设备手势)时触发。 | | `tap` | 当触摸点点击显示对象时触发。 | | `globaltouchmove` | 每次触摸移动时触发,无论显示对象是否处于触摸之下。 | ### 全局事件 {#global-events} ¥Global Events 在 PixiJS 的早期版本中,当画布捕获任何移动事件时,即使指针不在显示对象上,也会触发 `pointermove`、`mousemove` 和 `touchmove` 等事件。此行为在 v8 中发生了变化,现在只有当指针位于显示对象上时才会触发这些事件。 ¥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. 要保留旧行为,你可以使用 `globalpointermove`、`globalmousemove` 和 `globaltouchmove` 事件。这些事件会在每次指针/触摸移动时触发,无论是否有任何显示对象被点击。 ¥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} ¥How Hit Testing Works 当发生输入事件(鼠标移动、点击等)时,PixiJS 会遍历显示树,以查找指针下方最顶层的交互元素: ¥When an input event occurs (mouse move, click, etc.), PixiJS walks the display tree to find the top-most interactive element under the pointer: - 如果 `Container` 上的 `interactiveChildren` 为 `false`,则将跳过其子元素。 ¥If `interactiveChildren` is `false` on a `Container`, its children will be skipped. - 如果设置了 `hitArea`,它将覆盖基于边界的命中测试。 ¥If a `hitArea` is set, it overrides bounds-based hit testing. - 如果 `eventMode` 为 `'none'`,则将跳过该元素及其子元素。 ¥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 Area 可以使用 `hitArea` 属性定义自定义命中区域。此属性可以在任何场景对象上设置,包括 `Sprite`、`Container` 和 `Graphics`。 ¥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} ¥Listening to Events PixiJS 支持 `on()`/`off()` 和 `addEventListener()`/`removeEventListener()` 以及用于添加和删除事件监听器的事件回调 (`onclick: ()=> {}`)。大多数情况下都推荐使用 `on()` 方法,因为它在 PixiJS 中使用的不同事件类型之间提供了更一致的 API。 ¥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. ### 使用 `on()`(来自 EventEmitter) {#using-on-from-eventemitter} ¥Using `on()` (from EventEmitter) ```ts const eventFn = (e) => console.log('clicked'); sprite.on('pointerdown', eventFn); sprite.once('pointerdown', eventFn); sprite.off('pointerdown', eventFn); ``` ### 使用 DOM 样式事件 {#using-dom-style-events} ¥Using DOM-style Events ```ts sprite.addEventListener( 'click', (event) => { console.log('Clicked!', event.detail); }, { once: true }, ); ``` ### 使用回调 {#using-callbacks} ¥Using callbacks ```ts sprite.onclick = (event) => { console.log('Clicked!', event.detail); }; ``` ## 检查交互性 {#checking-for-interactivity} ¥Checking for Interactivity 你可以使用 `isInteractive()` 方法检查 `Sprite` 或 `Container` 是否可交互。如果对象是交互式的并且可以接收事件,则此方法返回 `true`。 ¥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} ¥Custom Cursors PixiJS 允许你使用 `cursor` 属性为交互式对象设置自定义光标。此属性接受表示 CSS 光标类型的字符串。 ¥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} ¥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://pixi.nodejs.cn/assets/bunny.png'),auto"; const hoverIcon = "url('https://pixi.nodejs.cn/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 参考 {#api-reference} ¥API Reference - [概述](https://pixijs.download/release/docs/events.html) ¥[Overview](https://pixijs.download/release/docs/events.html) - [EventSystem](https://pixijs.download/release/docs/events.EventSystem.html) - [光标](https://pixijs.download/release/docs/events.html#Cursor) ¥[Cursor](https://pixijs.download/release/docs/events.html#Cursor) - [EventMode](https://pixijs.download/release/docs/events.html#EventMode) - [容器](https://pixijs.download/release/docs/scene.Container.html) ¥[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} ¥Filters / Blend Modes PixiJS 滤镜允许你将后处理视觉效果应用于任何场景对象及其子对象。滤镜可用于实现模糊、色彩调整、噪点或基于自定义着色器的操作等效果。 ¥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 应用滤镜很简单。你可以将滤镜实例分配给任何场景对象的 `filters` 属性,例如 `Sprite`、`Container` 或 `Graphics`。你可以通过传递滤镜实例数组来应用多个滤镜。 ¥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} ¥Advanced Blend Modes PixiJS v8 为滤镜引入了高级混合模式,允许实现更复杂的合成效果。这些混合模式可用于创建独特的视觉样式和效果。要使用像 `HARD_LIGHT` 这样的高级模式,你必须手动导入高级混合模式扩展: ¥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} ¥Built-In Filters Overview PixiJS v8 提供了多种开箱即用的过滤器: ¥PixiJS v8 provides a variety of filters out of the box: | 过滤器类别 | 描述 | | -------------------- | ---------------------------- | | `AlphaFilter` | 将透明度应用于对象。 | | `BlurFilter` | 高斯模糊。 | | `ColorMatrixFilter` | 通过矩阵应用颜色变换。 | | `DisplacementFilter` | 使用其他纹理扭曲对象。 | | `NoiseFilter` | 添加随机噪声以产生颗粒效果。 | :::info 信息 要了解更多社区滤镜,请参阅 [pixi-filters](https://pixijs.io/filters/docs/)。 ¥To explore more community filters, see [pixi-filters](https://pixijs.io/filters/docs/). ::: 混合滤镜:用于自定义合成模式 ¥**Blend Filters**: Used for custom compositing modes | 过滤器类别 | 描述 | | ------------------ | -------------------------- | | `ColorBurnBlend` | 使基色变暗以反映混合色。 | | `ColorDodgeBlend` | 使基色变亮。 | | `DarkenBlend` | 保留最暗的颜色分量。 | | `DivideBlend` | 将基色除以混合色。 | | `HardMixBlend` | 高对比度混合。 | | `LinearBurnBlend` | 使用线性公式变暗。 | | `LinearDodgeBlend` | 使用线性公式进行亮度调整。 | | `LinearLightBlend` | 线性减淡和加深的组合。 | | `PinLightBlend` | 选择性替换颜色。 | | `SubtractBlend` | 从基色中减去混合色。 | --- ## 创建自定义滤镜 {#creating-a-custom-filter} ¥Creating a Custom Filter 要在 PixiJS v8 中定义自定义滤镜,请将 `Filter.from()` 与着色器程序和 GPU 资源结合使用。 ¥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** 着色器必须兼容 WebGL 或 WebGPU。对于双渲染器支持,请包含 `gpuProgram`。 ¥Shaders must be WebGL- or WebGPU-compatible. For dual-renderer support, include a `gpuProgram`. ::: --- ## API 参考 {#api-reference} ¥API Reference - [概述](https://pixijs.download/release/docs/filters.html) ¥[Overview](https://pixijs.download/release/docs/filters.html) - [筛选](https://pixijs.download/release/docs/filters.Filter.html) ¥[Filter](https://pixijs.download/release/docs/filters.Filter.html) --- ## 数学 {#math} # 数学 {#math} ¥Math PixiJS 包含多个用于 2D 变换、几何和形状操作的数学实用程序。本指南介绍了最重要的类及其用例,包括通过 `math-extras` 启用的可选高级方法。 ¥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} ¥Matrix `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 and ObservablePoint ### `Point` {#point} Point 对象表示二维坐标系中的位置,其中 `x` 表示水平轴上的位置,`y` 表示垂直轴上的位置。许多 Pixi 函数接受 `PointData` 类型作为 `Point` 的替代,后者只需要 `x` 和 `y` 属性。 ¥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` {#observablepoint} 扩展 `Point` 并在其值发生变化时触发回调。内部用于位置和比例更新等响应式系统。 ¥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} ¥Shapes PixiJS 包含多个 2D 形状,用于命中测试、渲染和几何计算。 ¥PixiJS includes several 2D shapes, used for hit testing, rendering, and geometry computations. ### `Rectangle` {#rectangle} 由 `x`、`y`、`width` 和 `height` 定义的轴对齐矩形。 ¥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` {#circle} 由 `x`、`y`(中心)和 `radius` 定义。 ¥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` {#ellipse} 与 `Circle` 类似,但支持不同的宽度和高度(半径)。 ¥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` {#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` {#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` {#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 ``` --- ## 可选:`math-extras` {#optional-math-extras} ¥Optional: `math-extras` 导入 `pixi.js/math-extras` 会扩展 `Point` 和 `Rectangle`,并为其添加额外的矢量和几何实用程序。 ¥Importing `pixi.js/math-extras` extends `Point` and `Rectangle` with additional vector and geometry utilities. ### 启用方法: {#to-enable} ¥To enable: ```ts import 'pixi.js/math-extras'; ``` ### 增强的 `Point` 方法 {#enhanced-point-methods} ¥Enhanced `Point` Methods | 方法 | 描述 | | ------------------------------- | -------------------------------- | | `add(other[, out])` | 在此基础上添加另一个点。 | | `subtract(other[, out])` | 从此点减去另一个点。 | | `multiply(other[, out])` | 将此点与另一个点按分量相乘。 | | `multiplyScalar(scalar[, out])` | 将点与一个标量相乘。 | | `dot(other)` | 计算两个向量的点积。 | | `cross(other)` | 计算 3D 向量积的标量 z 分量。 | | `normalize([out])` | 返回一个标准化(单位长度)向量。 | | `magnitude()` | 返回欧几里得长度。 | | `magnitudeSquared()` | 返回平方长度(更便于比较)。 | | `project(onto[, out])` | 将此点投影到另一个向量上。 | | `reflect(normal[, out])` | 反射给定法线方向上的点。 | ### 增强的 `Rectangle` 方法 {#enhanced-rectangle-methods} ¥Enhanced `Rectangle` Methods | 方法 | 描述 | | ---------------------------- | --------------------------------------- | | `containsRect(other)` | 如果此矩形包含另一个矩形,则返回 true。 | | `equals(other)` | 检查所有属性是否相等。 | | `intersection(other[, out])` | 返回一个表示重叠的新矩形。 | | `union(other[, out])` | 返回一个包含两个矩形的矩形。 | --- ## API 参考 {#api-reference} ¥API Reference - [概述](https://pixijs.download/release/docs/maths.html) ¥[Overview](https://pixijs.download/release/docs/maths.html) - [矩阵](https://pixijs.download/release/docs/maths.Matrix.html) ¥[Matrix](https://pixijs.download/release/docs/maths.Matrix.html) - [点](https://pixijs.download/release/docs/maths.Point.html) ¥[Point](https://pixijs.download/release/docs/maths.Point.html) - [ObservablePoint](https://pixijs.download/release/docs/maths.ObservablePoint.html) - [矩形](https://pixijs.download/release/docs/maths.Rectangle.html) ¥[Rectangle](https://pixijs.download/release/docs/maths.Rectangle.html) - [圆圈](https://pixijs.download/release/docs/maths.Circle.html) ¥[Circle](https://pixijs.download/release/docs/maths.Circle.html) - [椭圆](https://pixijs.download/release/docs/maths.Ellipse.html) ¥[Ellipse](https://pixijs.download/release/docs/maths.Ellipse.html) - [多边形](https://pixijs.download/release/docs/maths.Polygon.html) ¥[Polygon](https://pixijs.download/release/docs/maths.Polygon.html) - [RoundedRectangle](https://pixijs.download/release/docs/maths.RoundedRectangle.html) - [三角形](https://pixijs.download/release/docs/maths.Triangle.html) ¥[Triangle](https://pixijs.download/release/docs/maths.Triangle.html) --- ## 纹理 {#textures} # 纹理 {#textures} ¥Textures 纹理是 PixiJS 渲染管道中最重要的组件之一。它们定义了精灵、网格和其他可渲染对象所使用的视觉内容。本指南介绍如何加载、创建和使用纹理,以及 PixiJS 支持的各种数据源类型。 ¥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} ¥Texture Lifecycle 纹理系统基于两个主要类构建: ¥The texture system is built around two major classes: - `TextureSource`:表示像素源,例如图片、画布或视频。 ¥**`TextureSource`**: Represents a pixel source, such as an image, canvas, or video. - `Texture`:将视图定义为 `TextureSource`,包括子矩形、修剪和变换。 ¥**`Texture`**: Defines a view into a `TextureSource`, including sub-rectangles, trims, and transformations. ### 生命周期流程 {#lifecycle-flow} ¥Lifecycle Flow ``` Source File/Image -> TextureSource -> Texture -> Sprite (or other display object) ``` ### 加载纹理 {#loading-textures} ¥Loading Textures 可以使用 `Assets` 系统异步加载纹理: ¥Textures can be loaded asynchronously using the `Assets` system: ```ts const texture = await Assets.load('myTexture.png'); const sprite = new Sprite(texture); ``` ### 准备纹理 {#preparing-textures} ¥Preparing Textures 即使在加载纹理之后,图片仍然需要被推送到 GPU 并进行解码。对大量源图片执行此操作可能会很慢,并且在项目首次加载时会导致延迟峰值。为了解决这个问题,你可以使用 [准备](https://pixijs.download/release/docs/rendering.PrepareSystem.html) 插件,它允许你在显示项目之前的最后一步中预加载纹理。 ¥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. ## 纹理 vs. 纹理源 {#texture-vs-texturesource} ¥Texture vs. TextureSource `TextureSource` 类处理原始像素数据和 GPU 上传。`Texture` 是该源的轻量级视图,包含修剪、矩形框、UV 映射等元数据。多个 `Texture` 实例可以共享一个 `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} ¥Texture Creation 你可以使用构造函数手动创建纹理: ¥You can manually create textures using the constructor: ```ts const mySource = new TextureSource({ resource: myImage }); const texture = new Texture({ source: mySource }); ``` 如果你计划在运行时修改其 `frame`、`trim` 或 `source`,请在 `Texture` 选项中设置 `dynamic: true`。 ¥Set `dynamic: true` in the `Texture` options if you plan to modify its `frame`, `trim`, or `source` at runtime. ## 销毁纹理 {#destroying-textures} ¥Destroying Textures 使用完纹理后,你可能希望释放它使用的内存(WebGL 管理的缓冲区和基于浏览器的缓冲区)。为此,你应该调用 `Assets.unload('texture.png')`;如果你在 Assets 之外创建了纹理,则应调用 `texture.destroy()`。 ¥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. 对于短暂的图片(例如大型且仅使用一次的过场动画)来说,这是一个特别好的主意。如果通过 `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. ## 从 GPU 卸载纹理 {#unload-texture-from-gpu} ¥Unload Texture from GPU 如果你想从 GPU 卸载纹理但将其保留在内存中,可以调用 `texture.source.unload()`。这将从 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} ¥Texture Types PixiJS 支持多种 `TextureSource` 类型,具体取决于输入数据类型: ¥PixiJS supports multiple `TextureSource` types, depending on the kind of input data: | 纹理类型 | 描述 | | --------------------- | ---------------------------------------------------- | | **ImageSource** | HTMLImageElement、ImageBitmap、SVG、VideoFrame 等 | | **CanvasSource** | HTMLCanvasElement 或 OffscreenCanvas | | **VideoSource** | HTMLVideoElement 可选自动播放和更新 FPS | | **BufferImageSource** | 具有明确宽度、高度和格式的 TypedArray 或 ArrayBuffer | | **CompressedSource** | 压缩 mipmap 数组 (Uint8Array\[]) | ## 常用纹理属性 {#common-texture-properties} ¥Common Texture Properties 以下是 `Texture` 类的一些重要属性: ¥Here are some important properties of the `Texture` class: - `frame`:定义源中可见部分的矩形。 ¥`frame`: Rectangle defining the visible portion within the source. - `orig`:原始未裁剪尺寸。 ¥`orig`: Original untrimmed dimensions. - `trim`:定义修剪区域以排除透明空间。 ¥`trim`: Defines trimmed regions to exclude transparent space. - `uvs`:由 `frame` 和 `rotate` 生成的 UV 坐标。 ¥`uvs`: UV coordinates generated from `frame` and `rotate`. - `rotate`:GroupD8 旋转值用于图集兼容性。 ¥`rotate`: GroupD8 rotation value for atlas compatibility. - `defaultAnchor`:用于精灵图时的默认锚点。 ¥`defaultAnchor`: Default anchor when used in Sprites. - `defaultBorders`:用于 9 切片缩放。 ¥`defaultBorders`: Used for 9-slice scaling. - `source`:`TextureSource` 实例。 ¥`source`: The `TextureSource` instance. ## 常用 TextureSource 属性 {#common-texturesource-properties} ¥Common TextureSource Properties 以下是 `TextureSource` 类的一些重要属性: ¥Here are some important properties of the `TextureSource` class: - `resolution`:影响相对于实际像素大小的渲染大小。 ¥`resolution`: Affects render size relative to actual pixel size. - `format`:纹理格式(例如 `rgba8unorm`、`bgra8unorm` 等) ¥`format`: Texture format (e.g., `rgba8unorm`, `bgra8unorm`, etc.) - `alphaMode`:控制上传时如何解释 Alpha 值。 ¥`alphaMode`: Controls how alpha is interpreted on upload. - `wrapMode` / `scaleMode`:控制如何在边界外或缩放时对纹理进行采样。 ¥`wrapMode` / `scaleMode`: Controls how texture is sampled outside of bounds or when scaled. - `autoGenerateMipmaps`:上传时是否生成 mipmap。 ¥`autoGenerateMipmaps`: Whether to generate mipmaps on upload. 你可以在创建 `TextureSource` 时设置以下属性: ¥You can set these properties when creating a `TextureSource`: ```ts texture.source.scaleMode = 'linear'; texture.source.wrapMode = 'repeat'; ``` --- ## API 参考 {#api-reference} ¥API Reference - [质地](https://pixijs.download/release/docs/rendering.Texture.html) ¥[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} ¥Ticker PixiJS 中的 `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} ¥Adding and Removing Listeners `Ticker` 类允许你添加多个将在每帧调用的监听器。你还可以为回调指定上下文,这对于维护正确的 `this` 引用非常有用。 ¥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); ``` ## 控制 Ticker {#controlling-the-ticker} ¥Controlling the Ticker ```ts ticker.start(); // Begin calling listeners every frame ticker.stop(); // Pause the ticker and cancel the animation frame ``` 要在添加监听器时自动启动代码,请启用 `autoStart`: ¥To automatically start the ticker when a listener is added, enable `autoStart`: ```ts ticker.autoStart = true; ``` ## 确定监听器优先级 {#prioritizing-listeners} ¥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` ## 配置 FPS {#configuring-fps} ¥Configuring FPS Tickers 允许通过 FPS 限制来控制更新速率。 ¥Tickers allows FPS limits to control the update rate. ### `minFPS` {#minfps} 限制允许的帧慢速。用于限制 `deltaTime`: ¥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` {#maxfps} 限制 ticker 的运行速度。有助于节省 CPU/GPU: ¥Limits how _fast_ the ticker runs. Useful for conserving CPU/GPU: ```ts ticker.maxFPS = 60; // will not tick faster than 60fps ``` 设置为 `0` 以允许无限帧率: ¥Set to `0` to allow unlimited framerate: ```ts ticker.maxFPS = 0; ``` --- ## API 参考 {#api-reference} ¥API Reference - [股票行情指示器](https://pixijs.download/release/docs/ticker.Ticker.html) ¥[Ticker](https://pixijs.download/release/docs/ticker.Ticker.html) - [应用](https://pixijs.download/release/docs/app.Application.html) ¥[Application](https://pixijs.download/release/docs/app.Application.html) --- ## 混合 PixiJS 和 Three.js {#mixing-pixijs-and-threejs} # 混合 PixiJS 和 Three.js {#mixing-pixijs-and-threejs} ¥Mixing PixiJS and Three.js 在许多项目中,开发者旨在利用 3D 和 2D 图形的优势。将 Three.js 的高级 3D 渲染功能与 PixiJS 的 2D 速度和多功能性相结合,可以带来强大、无缝的体验。这些技术共同为动态和视觉上引人注目的应用创造了机会。让我们看看如何做到这一点。 ¥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 注意 本指南假设 PixiJS 将用作顶层,在 Three.js 渲染的 3D 场景上提供 UI。但是,开发者可以根据需要以任何顺序多次渲染。这种灵活性允许创建富有创意和动态的应用。 ¥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-youll-learn} ¥What You’ll Learn - 设置 PixiJS 和 Three.js 以共享单个 WebGL 上下文。 ¥Setting up PixiJS and Three.js to share a single WebGL context. - 使用 `resetState` 管理渲染器状态。 ¥Using `resetState` to manage renderer states. - 使用多个渲染器时避免常见的陷阱。 ¥Avoiding common pitfalls when working with multiple renderers. --- ### 设置 {#setting-up} ¥Setting Up #### 步骤 1:初始化 Three.js 渲染器和场景 {#step-1-initialize-threejs-renderer-and-scene} ¥Step 1: Initialize Three.js Renderer and Scene Three.js 将处理 3D 渲染、dom 元素和上下文的创建。 ¥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 注意 我们使用 three.js 渲染器创建的 dom 元素和上下文传递给 pixijs 渲染器。这是确保两个渲染器使用相同 WebGL 上下文的最简单方法。如果你愿意,也可以反过来做。 ¥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. ::: #### 步骤 2:初始化 PixiJS 渲染器和舞台 {#step-2-initialize-pixijs-renderer-and-stage} ¥Step 2: Initialize PixiJS Renderer and Stage PixiJS 将处理 2D 叠加层。 ¥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} ¥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); ``` --- ### 示例:结合 3D 和 2D 元素 {#example-combining-3d-and-2d-elements} ¥Example: Combining 3D and 2D Elements 这是集成 PixiJS 和 Three.js 的完整示例: ¥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} ¥Gotchas - **启用模板缓冲区:** ¥**Enable Stencil Buffers:** - 创建 Three.js 渲染器时,请确保将 `stencil` 设置为 `true`。这允许 PixiJS 蒙版正常工作。 ¥When creating the Three.js renderer, ensure `stencil` is set to `true`. This allows PixiJS masks to work correctly. - **保持尺寸同步:** ¥**Keep Dimensions in Sync:** - 确保两个渲染器使用相同的 `width` 和 `height` 以避免视觉不匹配 - 因此在调整一个渲染器的大小时要小心,你需要调整另一个渲染器的大小! ¥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! - **传递 WebGL 上下文:** ¥**Pass the WebGL Context:** - 在使用 `pixiRenderer.init({ context: threeRenderer.getContext() });` 初始化期间将 WebGL 上下文从 Three.js 传递到 PixiJS。 ¥Pass the WebGL context from Three.js to PixiJS during initialization using `pixiRenderer.init({ context: threeRenderer.getContext() });`. - **禁用渲染前清除:** ¥**Disable Clear Before Render:** - 初始化 PixiJS 渲染器时设置 `clearBeforeRender: false`。这可防止 PixiJS 清除在它之前渲染的 Three.js 内容。 ¥Set `clearBeforeRender: false` when initializing the PixiJS renderer. This prevents PixiJS from clearing the Three.js content that was rendered before it. - 或者,你可以在 `pixiRenderer.render()` 调用中设置 `clear: false`。例如 `pixiRenderer.render({ container: stage, clear: false });`。 ¥Alternatively you can set `clear: false` in the `pixiRenderer.render()` call. eg `pixiRenderer.render({ container: stage, clear: false });`. - **管理渲染顺序:** ¥**Manage Render Order:** - 在此示例中,首先渲染 Three.js,然后渲染 UI 层使用 PixiJS。但是,这个顺序是灵活的。你可以根据需要渲染 pixi -> three -> pixi,只需确保在切换渲染器时重置状态即可。 ¥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:** - 请记住,PixiJS 和 Three.js 之间不共享纹理等资源。PixiJS 纹理不能直接用作 Three.js 纹理,反之亦然。 ¥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} ¥Conclusion 混合 PixiJS 和 Three.js 可以成为创建动态且具有视觉吸引力的应用的有效方法。通过仔细管理渲染循环和状态,你可以实现 3D 和 2D 层之间的无缝过渡。这种方法允许你利用两种技术的优势,创建视觉效果令人惊叹且性能卓越的应用。 ¥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. 此技术也可以与其他渲染器一起使用 - 只要它们有自己的重置状态的方式(主要的方式就是如此),你就可以混合它们。流行的 3D 引擎(如 Babylon.js 和 PlayCanvas)都通过各自的 API 支持状态管理,使它们与这种混合方法兼容。这使你能够灵活地选择最适合你需求的 3D 引擎,同时仍能利用 PixiJS 强大的 2D 功能。 ¥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 迁移指南 {#v8-migration-guide} # v8 迁移指南 {#v8-migration-guide} ¥v8 Migration Guide 欢迎来到 PixiJS v8 迁移指南!本文档旨在帮助你顺利地将项目从 PixiJS v7 过渡到最新、最好的 PixiJS v8。请按照以下步骤操作以确保成功迁移。 ¥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} ¥Table of Contents 1. [介绍](#introduction) ¥[Introduction](#introduction) 2. [重大变化](#breaking-changes) ¥[Breaking Changes](#breaking-changes) 3. [已弃用的功能](#deprecated-features) ¥[Deprecated Features](#deprecated-features) 4. [资源](#resources) ¥[Resources](#resources) ## 1. 介绍 {#introduction} ¥ Introduction PixiJS v8 引入了一些令人兴奋的变化和改进,极大地提高了渲染器的性能。尽管我们已尽力保持迁移过程尽可能顺利,但一些重大变化是不可避免的。本指南将引导你完成将 PixiJS v7 项目迁移到 PixiJS v8 的必要步骤。 ¥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 在深入了解迁移过程之前,我们先回顾一下 PixiJS v8 中引入的重大更改。请务必密切关注这些更改,因为它们可能会影响你现有的代码库。 ¥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} ¥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: - 你的项目是否利用了尚未迁移到 v8 的现有 Pixi 库?我们正在努力将我们的关键库迁移到 v8,但不希望这成为那些使用纯 Pixi 的人的障碍。这意味着一些库暂时没有 v8 对应库。如果你是这种情况,最好推迟迁移。 ¥**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(深奥版本) ¥Spine (esoteric version) **待迁移:** ¥**To Be Migrated:** - Pixi 层(我们可能会将其作为一项功能直接合并到 PixiJS v8 中,而不是迁移它) ¥Pixi layers (rather than migrating this, we will likely incorporate it directly into PixiJS v8 as a feature) ### **新的封装结构** {#new-package-structure} ¥**New Package Structure** 从版本 5 开始,PixiJS 使用单独的子包将其代码库组织成更小的单元。然而,这种方法会导致一些问题,例如不同 PixiJS 版本的安装冲突,导致内部缓存复杂化。 ¥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. 在 v8 中,PixiJS 已恢复为单包结构。虽然你仍然可以导入 PixiJS 的特定部分,但你只需要安装主包。 ¥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} ¥Custom Builds PixiJS 使用 "extensions" 系统来添加渲染器功能。默认情况下,PixiJS 包含许多扩展,可提供全面的开箱即用体验。但是,为了完全控制功能和包大小,你可以手动导入特定的 PixiJS 组件。 ¥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 }); ``` 初始化应用时,你可以禁用自动导入功能,防止 PixiJS 自动导入任何扩展。你需要手动导入它们,如上面所示。 ¥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. 还应该指出的是,`pixi.js/text-bitmap` 还添加了 `Assets` 加载功能。因此,如果你想在初始化渲染器之前加载位图字体,则需要导入此扩展。 ¥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} ¥**Async Initialisation** PixiJS 现在需要异步初始化。随着 WebGPU 渲染器的引入,PixiJS 现在需要等待才能使用 ¥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 })(); ``` 通过此更改,还意味着 `ApplicationOptions` 对象现在可以传递到 `init` 函数而不是构造函数中。 ¥With this change it also means that the `ApplicationOptions` object can now be passed into the `init` function instead of the constructor. ### \*\* 纹理调整 \*\* {#-texture-adjustments-} ¥\*\* Texture adjustments \*\* 纹理结构已被修改,以简化 v7 中后台变得相当混乱的情况。纹理不再知道或管理资源的加载。这需要由你或资源管理员提前完成。纹理只需要完全加载的资源。这使得事情变得更容易管理,因为纹理的验证基本上可以在构造时完成并就此结束!BaseTexture 不再存在。相反,我们现在有各种可用的 TextureSource。纹理源将纹理的设置与如何上传和使用该纹理相结合。在 v8 中有以下纹理源: ¥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 - 你可以根据需要渲染或上传的原始纹理。(主要由渲染纹理使用)ImageSource - 包含某种图片资源的纹理源(例如 ImageBitmap 或 html 图片)CanvasSource - 包含画布的画布源。主要用于渲染画布或渲染到画布 (webGPU) VideoSource - 包含视频的纹理源。负责更新 GPU 上的纹理,以确保它们保持同步。BufferSource - 包含缓冲区的纹理源。无论你真正想要什么!确保你的缓冲区类型和格式兼容!CompressedSource - 处理压缩纹理的纹理源。由 GPU 压缩纹理格式使用。 ¥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. 虽然大多数时候 `Assets` 都会返回你可能想要自己制作的纹理!祝你更强大! ¥Whilst the majority of the time `Assets` will return Textures you may want to make you own! More power to ya! 要创建纹理源,签名与 baseTexture 不同。示例: ¥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'; ``` ### **图形 API 大修** {#graphics-api-overhaul} ¥**Graphics API Overhaul** 图形 API 有一些关键更改。事实上,这可能是 v8 中变化最大的部分。我们在可能的情况下添加了弃用内容,但以下是更改的概要: ¥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: - v8 不是先开始填充或描边,然后构建形状,而是要求你构建形状,然后描边/填充它。`Line` 的术语已替换为 `Stroke` 的术语 ¥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 调用 | v8 API 等效项 | | ------------------ | ------------- | | drawChamferRect | chamferRect | | drawCircle | circle | | drawEllipse | ellipse | | drawFilletRect | filletRect | | drawPolygon | poly | | drawRect | rect | | drawRegularPolygon | regularPoly | | drawRoundedPolygon | roundPoly | | drawRoundedRect | roundRect | | drawRoundedShape | roundShape | | drawStar | star | - 填充函数需要 `FillStyle` 个选项或颜色,而不是参数字符串。这也取代了 `beginTextureFill` ¥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 函数需要 `StrokeStyle` 个选项或颜色,而不是一串参数。这也取代了旧的 `lineTextureStyle`: ¥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 }); ``` - 孔现在使用新的 `cut` 函数。与 `stroke` 和 `fill` 一样,`cut` 作用于先前的形状。老的: ¥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` 已替换为 `GraphicsContext`,这样可以更有效地共享 `Graphics` 数据。 ¥`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} ¥Shader changes 由于我们现在需要同时兼容 WebGL 和 WebGPU 着色器,因此它们的构造方式已进行调整以考虑到这一点。你会注意到的主要区别(这通常适用于着色器)是纹理不再被视为统一的(因为它们不能包含在统一组中)。相反,我们有资源的概念。资源可以是以下几种东西: ¥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 - 源纹理 `myTexture.source` ¥TextureSource - A source texture `myTexture.source` - TextureStyle - 纹理样式 `myTexture.style` ¥TextureStyle - A texture style `myTexture.style` - UniformGroup - 基于数字的统一 `myUniforms = new UniformGroup({})` 的集合 ¥UniformGroup - A collection of number based uniforms `myUniforms = new UniformGroup({})` - BufferResource - 被视为统一组的缓冲区(高级) ¥BufferResource - A buffer that is treated as a uniform group (advanced) 现在创建一个仅 webgl 的着色器如下所示: ¥creating a webgl only shader now looks like this: **old** ```ts const shader = PIXI.Shader.from(vertex, fragment, uniforms); ``` **new** 仅 WebGL ¥just WebGL ```ts const shader = Shader.from({ gl: { vertex, fragment }, resources, // resource used from above including uniform groups }); ``` WebGL 和 WebGPU ¥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! ``` 要充分了解此新设置,最好的方法是查看 Mesh 和 Shader 示例: ¥The best way to play and fully and get to know this new setup please check out the Mesh and Shader examples: 旧:[v7 示例](https://pixi.nodejs.cn/7.x/examples/mesh-and-shaders/triangle-color) 新:[v8 示例](https://pixi.nodejs.cn/8.x/examples/mesh-and-shaders/triangle-color) ¥**old**: [v7 example](https://pixi.nodejs.cn/7.x/examples/mesh-and-shaders/triangle-color) **new**: [v8 example](https://pixi.nodejs.cn/8.x/examples/mesh-and-shaders/triangle-color) ### 过滤器 {#filters} ¥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' }, }, }, }); ``` 旧:[v7 示例](https://pixi.nodejs.cn/7.x/examples/filters-advanced/custom) 新:[v8 示例](https://pixi.nodejs.cn/8.x/examples/filters-advanced/custom) ¥**old**: [v7 example](https://pixi.nodejs.cn/7.x/examples/filters-advanced/custom) **new**: [v8 example](https://pixi.nodejs.cn/8.x/examples/filters-advanced/custom) 如果你使用的是 [社区过滤器](https://github.com/pixijs/filters),请注意 `@pixi/filter-*` 包不再为 v8 维护,但是,你可以直接从 `pixi-filters` 包导入为子模块。 ¥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} `ParticleContainer` 在 v8 中经过重新设计,允许比以前更多的粒子。你应该注意一些关键更改: ¥`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: `ParticleContainer` 不再接受精灵作为其子级。相反,它需要一个 `Particle` 类(或实现 `IParticle` 接口的对象),它遵循此接口: ¥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; } ``` 进行此更改的原因是精灵带有许多额外的属性和事件,这些属性和事件在处理大量粒子时通常是不必要的。这种方法明确消除了我们在 v7 中遇到的任何歧义,例如 "为什么我的精灵不能与过滤器一起使用?" 或 "为什么我不能将子级嵌套在我的精灵中?" 它更可预测一些。此外,由于粒子的轻量级特性,这意味着我们可以渲染更多的粒子! ¥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! 因此,没有丢失任何功能 - 只是 API 调整,性能大幅提升! ¥So, no functionality is lost—just an API tweak with a massive performance boost! 粒子也不存储在 `ParticleContainer` 的 `children` 数组中,因为粒子在技术上不是场景图的一部分(出于性能原因)。相反,它们存储在一个名为 `particleChildren` 的扁平列表中,它是 `ParticleContainer` 类的一部分。你可以直接修改此数组以获得额外的速度,也可以使用 `addParticle` 和 `removeParticle` 方法来管理你的粒子。 ¥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. 另一个优化是 `ParticleContainer` 不计算自己的边界,因为这样做会抵消我们创造的性能提升!相反,在初始化 `ParticleContainer` 时,你需要提供 `boundsArea`。 ¥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 在这个版本的 PixiJS 中,我们更改了 `cullable` 属性在容器上的工作方式。以前,剔除是在渲染循环期间自动为你完成的。然而,我们已经移除了这个逻辑,并为用户提供了自己控制何时发生剔除的能力。 ¥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` - 容器是否可以被剔除 ¥`cullable` - Whether or not the container can be culled - `cullArea` - 将使用一个剔除区域来代替容器的边界 ¥`cullArea` - A cull area that will be used instead of the bounds of the container - `cullableChildren` - 容器子项是否可以被剔除。这可以帮助优化大场景 ¥`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); ``` 如果你想模拟旧的行为,还有一个 `CullerPlugin` 可用于每帧自动调用 `Culler.shared.cull`。 ¥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 - 重命名为 `SimpleMesh` -> `MeshSimple` ¥renamed `SimpleMesh` -> `MeshSimple` - 重命名为 `SimplePlane` -> `MeshPlane` ¥renamed `SimplePlane` -> `MeshPlane` - 重命名为 `SimpleRope` -> `MeshRope` ¥renamed `SimpleRope` -> `MeshRope` - 删除了对 `Assets` 的弃用 ¥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` 对象已被删除 ¥`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); ``` - 适配器和 Web Worker 更改 ¥Adapter and Web Worker Changes - `settings.ADAPTER` 已被删除并替换为 `DOMAdapter` ¥`settings.ADAPTER` has been removed and replaced with `DOMAdapter` - `DOMAdapter` 是一个静态类,可用于设置整个应用的适配器 ¥`DOMAdapter` is a static class that can be used to set the adapter for the entire application - PixiJS 有两个内置的适配器 `BrowserAdapter` 和 `WebWorkerAdapter` ¥PixiJS has two adapters built in `BrowserAdapter` and `WebWorkerAdapter` - `BrowserAdapter` 是默认适配器,在浏览器中运行时使用 ¥`BrowserAdapter` is the default adapter and is used when running in the browser - 在 Web Worker 中运行时使用 `WebWorkerAdapter` ¥`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(); ``` - 应用类型现在接受 Renderer 而不是 [https://github.com/pixijs/pixijs/pull/9740](https://github.com/pixijs/pixijs/pull/9740) 中 @Zyie 的视图 ¥Application type now accepts Renderer instead of view by @Zyie in [https://github.com/pixijs/pixijs/pull/9740](https://github.com/pixijs/pixijs/pull/9740) 这是为了让 `app.renderer` 能够正确输入 ¥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` 不再从 URL 加载纹理。 ¥`Texture.from` no longer will load a texture from a URL. 使用 `Texture.from` 时,你需要传入 `CanvasSource`/`ImageSource`/`VideoSource` 等源或 `HTMLImageElement`/`HTMLCanvasElement`/`HTMLVideoElement` 等资源或通过 `Assets.load` 加载的字符串 ¥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'); ``` - `Ticker` 的回调现在将传递 `Ticker` 实例而不是增量时间。这是为了更好地控制使用的时间单位。 ¥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` - 默认 `eventMode` 现在是 `passive` 而不是 `auto` ¥The default `eventMode` is now `passive` instead of `auto` - `utils` 已被删除。所有功能都可以直接导入。 ¥`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()` 现在返回 [`Bounds`](https://pixijs.download/release/docs/rendering.Bounds.html) 对象而不是 [`Rectangle`](https://pixijs.download/release/docs/maths.Rectangle.html) 对象。你可以使用 `container.getBounds().rectangle` 来访问矩形。 ¥`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` 已被 `container.cacheAsTexture()` 取代。它们的作用相同,只是我们更改了名称 `cacheAsTexture`,因为位图术语与 PixiJS 并不真正相关。 ¥`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 PixiJS v7 中的某些功能在 v8 中已被弃用。虽然它们仍然有效,但建议更新你的代码以使用新的替代方案。有关如何替换它们的详细信息,请参阅已弃用的功能部分。 ¥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 只有 `Containers` 可以生子级。这意味着 `Sprite`、`Mesh`、`Graphics` 等不能再生育子级。 ¥Only `Containers` can have children. This means that `Sprite`, `Mesh`, `Graphics` etc can no longer have children. 要复制旧行为,你可以创建 `Container` 并向其添加叶节点。 ¥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` 替换为 `Application.canvas` ¥`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` 更名为 `NineSliceSprite` ¥`NineSlicePlane` renamed to `NineSliceSprite` - `SCALE_MODES` 替换为 `ScaleMode` 字符串 ¥`SCALE_MODES` replaced with `ScaleMode` strings - `SCALE_MODES.NEAREST` -> `'nearest'`, - `SCALE_MODES.LINEAR` -> `'linear'`, - `WRAP_MODES` 替换为 `WrapMode` 字符串 ¥`WRAP_MODES` replaced with `WrapMode` strings - `WRAP_MODES.CLAMP` -> `'clamp-to-edge'`, - `WRAP_MODES.REPEAT` -> `'repeat'`, - `WRAP_MODES.MIRRORED_REPEAT` -> `'mirror-repeat'`, - `DRAW_MODES` 替换为 `Topology` 字符串 ¥`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` 现在是 `container.label` ¥`container.name` is now `container.label` ## 4. 资源 {#resources} ¥ Resources - [PixiJS v8 发行说明](https://github.com/pixijs/pixijs/releases?q=v8.0.0&expanded=true) ¥[PixiJS v8 Release Notes](https://github.com/pixijs/pixijs/releases?q=v8.0.0&expanded=true) - [PixiJS Discord](https://discord.gg/CPTjeb28nH) - [PixiJS 问题](https://github.com/pixijs/pixijs/issues) ¥[PixiJS Issues](https://github.com/pixijs/pixijs/issues) --- ## 漏洞赏金计划 {#bug-bounty-program} # 漏洞赏金计划 {#bug-bounty-program} ¥Bug Bounty Program PixiJS 致力于为 Web 提供可靠、高性能的渲染引擎。为了支持这一使命,我们推出了一项 Bug 赏金计划,以奖励帮助 PixiJS 更加稳定和健壮的贡献者。 ¥PixiJS is committed to delivering a reliable, high-performance rendering engine for the web. To support that mission, we’re launching a **Bug Bounty Program** to reward contributors who help make PixiJS more stable and robust. ## 工作原理 {#how-it-works} ¥How It Works 1. 赏金标签分配 PixiJS 团队将确定符合条件的问题,并应用 `bounty` 标签以及特定的金额。 ¥**Bounty Tag Assignment** The PixiJS team will identify eligible issues and apply the **`bounty`** label along with a specific **dollar amount**. 只有带有 `bounty` 标签和金额的问题才有资格参与此计划。 ¥Only issues labeled with the `bounty` tag and a dollar amount are eligible for this program. 你可以找到所有当前带有赏金标签的问题 [此处](https://github.com/pixijs/pixijs/issues?q=is%3Aissue%20state%3Aopen%20label%3A%F0%9F%92%B0Bounty)。 ¥You can find all current bounty-tagged issues [here](https://github.com/pixijs/pixijs/issues?q=is%3Aissue%20state%3Aopen%20label%3A%F0%9F%92%B0Bounty). 2. 提交要求 要获得赏金,你必须: ¥**Submission Requirements** To claim a bounty, you must: - 提交一个可修复问题的 Pull 请求 (PR)。 ¥Submit a **Pull Request (PR)** that fixes the issue. - 在你的 PR 描述中链接此问题。 ¥Link the issue in your PR description. - 请包含一个清晰的示例或测试用例,以证明错误已得到解决。 ¥Include a clear **example or test case** demonstrating that the bug is resolved. - 遵循我们的标准 [贡献指南](https://github.com/pixijs/pixijs/blob/dev/.github/CONTRIBUTING.md)。 ¥Follow our standard [contribution guidelines](https://github.com/pixijs/pixijs/blob/dev/.github/CONTRIBUTING.md). 3. **审批流程** ¥**Approval Process** - PixiJS 团队将审核你的 PR。 ¥The PixiJS team will review your PR. - 如果你的修复程序被接受并合并到主分支,你的赏金即被批准。 ¥If your fix is accepted and merged into the main branch, your bounty is approved. 4. 合并 PR 后请求付款: ¥**Requesting Payment** Once your PR is merged: - 你可以通过我们的 [Open Collective](https://opencollective.com/pixijs) 页面提交付款请求。 ¥You can submit a payout request via our [Open Collective](https://opencollective.com/pixijs) page. - 请在你的请求中包含已合并 PR 和赏金问题的链接。 ¥Include a link to the merged PR and the bounty issue in your request. - 付款将通过 Open Collective 处理。 ¥Payments will be processed through Open Collective. ## 条款和条件 {#terms--conditions} ¥Terms & Conditions - 只有预先批准的带有 `bounty` 标签和金额的问题才有资格参与此计划。 ¥Only issues **pre-approved** with a `bounty` tag and dollar amount are eligible. - 赏金由 PixiJS 团队自行决定。我们保留拒绝不完整、引入回归或不符合项目标准的修复程序的权利。 ¥Bounties are awarded **at the PixiJS team's discretion**. We reserve the right to reject fixes that are incomplete, introduce regressions, or do not meet project standards. - 你可以提交未带有赏金标签的问题的修复,但这些修复不符合获得经济奖励的资格。 ¥You may submit fixes for issues without a bounty tag, but they will not be eligible for financial rewards. - 多个贡献者可以为同一赏金提交 PR,但只有被合并的 PR 才有资格获得付款。 ¥Multiple contributors can submit PRs for the same bounty, but only the PR that gets merged is eligible for payment. - 赏金金额是固定的,不可协商。 ¥The bounty amount is fixed and non-negotiable. - 滥用、发送垃圾信息或提交低质量内容可能会导致被排除在计划之外。 ¥Abuse, spamming, or low-quality submissions may result in exclusion from the program. ## 赞助赏金 {#sponsoring-bounties} ¥Sponsoring Bounties 如果你是正在开发项目的开发者或公司,并且希望赞助一次性赏金,请联系 Matt Karl [@bigtimebuddy](https://github.com/bigtimebuddy) ([hello@mattkarl.com](mailto:hello@mattkarl.com)) 安排细节。 ¥If you are a developer or company working on a project and would like to sponsor a one-off bounty, please contact **Matt Karl** [@bigtimebuddy](https://github.com/bigtimebuddy) at **[hello@mattkarl.com](mailto:hello@mattkarl.com)** to arrange the details. 赞助商可以直接向我们的 [Open Collective](https://opencollective.com/pixijs) 进行一次性捐赠,以资助赏金计划。 ¥Sponsors can make one-time donations directly to our [Open Collective](https://opencollective.com/pixijs) to fund the bounty. 我们恳请赞助商在赏金金额上额外增加 10%,以支付 Open Collective 的处理费用。 ¥We kindly request that sponsors add an additional **10%** to the bounty amount to cover Open Collective's processing fees. ## **查找赏金问题** {#finding-bounty-issues} ¥**Finding Bounty Issues** 你可以在我们的 GitHub 代码库中轻松找到 [符合条件的赏金问题](https://github.com/pixijs/pixijs/issues?q=is%3Aissue%20state%3Aopen%20label%3A%F0%9F%92%B0Bounty)。 ¥You can easily find [eligible bounty issues](https://github.com/pixijs/pixijs/issues?q=is%3Aissue%20state%3Aopen%20label%3A%F0%9F%92%B0Bounty) on our GitHub repository. 这使你可以将贡献重点放在有经济回报的任务上。 ¥This allows you to focus your contributions on tasks that have a financial reward. ## 我们为何这么做 {#why-were-doing-this} ¥Why We're Doing This 我们相信开源和社区协作的力量。我们的漏洞赏金计划旨在: ¥We believe in the power of open source and community collaboration. Our bug bounty program is designed to: - 鼓励贡献者解决重要且有影响力的问题。 ¥Encourage contributors to tackle important, impactful issues. - 我们理解调试和修复复杂问题所涉及的艰苦工作。 ¥Recognize the hard work involved in debugging and fixing complex problems. - 请知悉 PixiJS 核心团队规模较小,并且经常专注于其他关键任务,你的贡献有助于更快地解决问题。 ¥Acknowledge that the PixiJS core team is small and often focused on other critical tasks, your contributions help get issues resolved faster. - 让 PixiJS 更好地服务于每个人。 ¥Make PixiJS even better for everyone. ## 有疑问? {#questions} ¥Questions? 欢迎在我们的 [GitHub 讨论区](https://github.com/pixijs/pixijs/discussions) 上提问或加入我们的 [Discord 社区](https://discord.gg/QrnxmQUPGV)。 ¥Feel free to ask questions on our [GitHub Discussions](https://github.com/pixijs/pixijs/discussions) or join our [community Discord](https://discord.gg/QrnxmQUPGV). --- ## 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} ¥Culler Plugin `CullerPlugin` 会自动跳过场景中屏幕外对象的渲染。它通过使用渲染器的屏幕边界来确定容器(以及可选的子容器)是否与视图相交来实现此目的。如果没有处理,它们将被剔除,从而减少渲染和更新开销。 ¥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 默认不启用此插件。你必须使用 `extensions` 系统手动注册。 ¥PixiJS does not enable this plugin by default. You must manually register it using the `extensions` system. ## 何时应该使用它? {#when-should-you-use-it} ¥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} ¥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); ``` ### 启用 Culler 插件 {#enabling-the-culler-plugin} ¥Enabling the Culler Plugin 要在应用中启用自动剔除: ¥To enable automatic culling in your application: ```ts import { extensions, CullerPlugin } from 'pixi.js'; extensions.add(CullerPlugin); ``` 这将覆盖 `Application` 实例上的默认 `render()` 方法,以便在渲染之前调用 `Culler.shared.cull()`: ¥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} ¥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} ¥Optional: Define a Custom Cull Area 你可以定义一个 `cullArea` 来覆盖默认的边界检查(使用全局边界): ¥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. --- ## 使用 `Culler` 手动剔除 {#manual-culling-with-culler} ¥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 参考 {#api-reference} ¥API Reference - [CullerPlugin](https://pixijs.download/release/docs/app.CullerPlugin.html) --- ## 应用 {#application} # 应用 {#application} ¥Application `Application` 类提供了一个现代化的、可扩展的入口点,用于在 PixiJS 中设置渲染。它抽象了渲染器设置和代码更新等常见任务,并旨在通过异步初始化支持 WebGL 和 WebGPU。 ¥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 创建应用需要两个步骤:构造一个实例,然后使用 `.init()` 异步初始化它: ¥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} ¥ApplicationOptions Reference `Application` 的 `.init()` 方法接受一个 `Partial` 对象,该对象具有以下配置选项: ¥The `.init()` method of `Application` accepts a `Partial` object with the following configuration options: | 选项 | 类型 | 默认 | 描述 | | ------------------------ | ----------------------------------- | ----------- | ------------------------------------------------------------------------------- | | `autoStart` | `boolean` | `true` | 初始化后是否立即开始渲染。如果共享 ticker 已在运行,设置为 `false` 不会停止它。 | | `resizeTo` | `Window \| HTMLElement` | — | 用于自动调整渲染器大小以匹配的元素。 | | `sharedTicker` | `boolean` | `false` | 如果是 `true`,则使用共享的 ticker 实例;否则,将创建一个私有的 ticker。 | | `preference` | `'webgl' \| 'webgpu'` | `webgl` | 首选渲染器类型。 | | `useBackBuffer` | `boolean` | `false` | (仅限 WebGL)在需要时使用后台缓冲区。 | | `forceFallbackAdapter` | `boolean` | `false` | (仅限 WebGPU)强制使用回退适配器。 | | `powerPreference` | `'high-performance' \| 'low-power'` | `undefined` | GPU 功率偏好提示(WebGL 和 WebGPU)。 | | `antialias` | `boolean` | — | 启用抗锯齿。可能会影响性能。 | | `autoDensity` | `boolean` | — | 根据 `resolution` 调整画布大小。仅适用于 `HTMLCanvasElement`。 | | `background` | `ColorSource` | — | `backgroundColor` 的别名。 | | `backgroundAlpha` | `number` | `1` | 背景的 Alpha 透明度(0 = 透明,1 = 不透明)。 | | `backgroundColor` | `ColorSource` | `'black'` | 用于清除画布的颜色。接受十六进制、CSS 颜色或数组。 | | `canvas` | `ICanvas` | — | 一个自定义画布实例(可选)。 | | `clearBeforeRender` | `boolean` | `true` | 渲染器是否应在每一帧清除画布。 | | `context` | `WebGL2RenderingContext \| null` | `null` | 用户提供的渲染上下文 (WebGL)。 | | `depth` | `boolean` | — | 在主视图中启用深度缓冲区。对于 WebGL,始终使用 `true`。 | | `height` | `number` | `600` | 渲染器的初始高度(以像素为单位)。 | | `width` | `number` | `800` | 渲染器的初始宽度(以像素为单位)。 | | `hello` | `boolean` | `false` | 将渲染器信息和版本记录到控制台。 | | `multiView` | `boolean` | `false` | 启用多画布渲染。 | | `preferWebGLVersion` | `1 \| 2` | `2` | 首选 WebGL 版本。 | | `premultipliedAlpha` | `boolean` | `true` | 假设 alpha 值在颜色缓冲区中预乘。 | | `preserveDrawingBuffer` | `boolean` | `false` | 在帧间保留缓冲区。`toDataURL` 所需。 | | `resolution` | `number` | 1 | 渲染器的分辨率。 | | `skipExtensionImports` | `boolean` | `false` | 防止自动导入默认的 PixiJS 扩展。 | | `textureGCActive` | `boolean` | `true` | 启用 GPU 纹理的垃圾回收。 | | `textureGCCheckCountMax` | `number` | `600` | GC 运行(纹理)之间的帧间隔。 | | `textureGCMaxIdle` | `number` | `3600` | 销毁纹理前的最大空闲帧数。 | | `textureGCAMaxIdle` | `number` | — | (似乎未记录;内部 GC 控制的占位符。) | ### 根据渲染器类型自定义应用选项 {#customizing-application-options-per-renderer-type} ¥Customizing Application Options Per Renderer Type 你还可以使用 `WebGLOptions` 或 `WebGPUOptions` 接口根据渲染器类型覆盖属性。例如: ¥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} ¥Built-In Plugins PixiJS 包含: ¥PixiJS includes: - ✅ Ticker 插件 — 每帧更新 → [指南](./ticker-plugin.md) ¥✅ **Ticker Plugin** — Updates every frame → [Guide](./ticker-plugin.md) - ✅ Resize 插件 — 调整渲染器/​​画布的大小 → [指南](./resize-plugin.md) ¥✅ **Resize Plugin** — Resizes renderer/canvas → [Guide](./resize-plugin.md) - ➕ 可选:剔除器插件 - 剔除超出框架范围的对象 → [指南](./culler-plugin.md) ¥➕ **Optional: Culler Plugin** - Culls objects that are out of frame → [Guide](./culler-plugin.md) --- ## 创建自定义应用插件 {#creating-a-custom-application-plugin} ¥Creating a Custom Application Plugin 你可以为 `Application` 类创建自定义插件。插件必须实现 `ApplicationPlugin` 接口,其中包含 `init()` 和 `destroy()` 方法。你还可以指定 `extension` 类型,对于应用插件,即 `ExtensionType.Application`。 ¥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. 调用这两个函数时,都将 `this` 设置为 `Application` 实例,例如 `this.renderer` 或 `this.stage` 可用。 ¥Both functions are called with `this` set as the `Application` instance e.g `this.renderer` or `this.stage` is available. `init()` 方法在应用初始化时调用,并传递 `application.init` 调用中的选项;`destroy()` 方法在应用销毁时调用。 ¥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} ¥Adding Types 如果你使用 TypeScript,或者正在提供插件供他人使用,你可以扩展 `ApplicationOptions` 接口以包含你的自定义插件选项。 ¥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 参考 {#api-reference} ¥API Reference - [概述](https://pixijs.download/release/docs/app.html) ¥[Overview](https://pixijs.download/release/docs/app.html) - [应用](https://pixijs.download/release/docs/app.Application.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 插件 {#resize-plugin} # Resize 插件 {#resize-plugin} ¥Resize Plugin `ResizePlugin` 为 PixiJS 应用提供了自动调整大小的功能。启用后,它会监听窗口或元素的大小调整事件,并相应地调整应用渲染器的大小。 ¥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 默认情况下,PixiJS 会在初始化 `Application` 时添加此插件,但如果你使用自定义设置,也可以手动注册。 ¥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} ¥Usage ```ts import { Application } from 'pixi.js'; const app = new Application(); await app.init({ width: 800, height: 600, resizeTo: window, }); ``` ### 默认行为 {#default-behavior} ¥Default Behavior - 使用未覆盖的 `Application.init()` 时,会自动安装 `ResizePlugin`: ¥When using `Application.init()` with no overrides, the `ResizePlugin` is installed automatically: - 设置 `resizeTo` 后,渲染器会自动调整以匹配目标(`window` 或 `HTMLElement`)的尺寸。 ¥When `resizeTo` is set, the renderer automatically adjusts to match the dimensions of the target (`window` or `HTMLElement`). - 使用 `requestAnimationFrame` 限制调整大小,以防止在快速调整大小事件期间出现性能问题。 ¥Resizing is throttled using `requestAnimationFrame` to prevent performance issues during rapid resize events. - 你可以使用 `app.resize()` 手动触发调整大小,或使用 `app.cancelResize()` 取消预定的调整大小。 ¥You can trigger a resize manually with `app.resize()` or cancel a scheduled resize with `app.cancelResize()`. ### 手动注册 {#manual-registration} ¥Manual Registration 如果你手动管理扩展: ¥If you're managing extensions manually: ```ts import { extensions, ResizePlugin } from 'pixi.js'; extensions.add(ResizePlugin); ``` ### 自定义调整目标大小 {#custom-resize-target} ¥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 参考 {#api-reference} ¥API Reference - [`ResizePlugin`](https://pixijs.download/release/docs/app.ResizePlugin.html) --- ## Ticker 插件 {#ticker-plugin} # Ticker 插件 {#ticker-plugin} ¥Ticker Plugin `TickerPlugin` 为你的 PixiJS `Application` 提供了内置更新循环。此循环以固定的节奏(默认情况下,每个动画帧调用一次)调用 `.render()`,并与 PixiJS 的 `Ticker` 系统集成,以精确控制基于帧的更新。 ¥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 会在你初始化 `Application` 时自动包含此插件,但你也可以选择退出并手动添加。 ¥PixiJS includes this plugin automatically when you initialize an `Application`, but you can also opt out and add it manually. ## 用法 {#usage} ¥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} ¥Default Behavior 除非禁用,否则会自动包含 `TickerPlugin`: ¥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} ¥Manual Registration 如果你自行管理扩展: ¥If you're managing extensions yourself: ```ts import { extensions, TickerPlugin } from 'pixi.js'; extensions.add(TickerPlugin); ``` # 共享 vs 自定义 Ticker {#shared-vs-custom-ticker} ¥Shared vs Custom Ticker 该插件支持两种模式: ¥The plugin supports two modes: | 选项 | 描述 | | --------------------- | ------------------------------------ | | `sharedTicker: true` | 使用 `Ticker.shared`,所有应用共享。 | | `sharedTicker: false` | 创建一个作用域为应用的私有代码实例。 | ### 行为差异 {#behavior-differences} ¥Behavior Differences - 如果使用共享 ticker,其他代码可能也会注册更新,因此执行顺序可能会有所不同。 ¥If using a **shared ticker**, other code may also be registering updates, so the order of execution can vary. - 如果使用自定义 ticker,你可以完全控制时间和更新顺序。 ¥If using a **custom ticker**, you get complete control over timing and update order. --- ## 生命周期控制 {#lifecycle-control} ¥Lifecycle Control 你可以手动停止和启动 ticker: ¥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 参考 {#api-reference} ¥API Reference - [TickerPlugin](https://pixijs.download/release/docs/app.TickerPlugin.html) - [股票行情指示器](https://pixijs.download/release/docs/ticker.Ticker.html) ¥[Ticker](https://pixijs.download/release/docs/ticker.Ticker.html) --- ## 后台加载器 {#background-loader} # 后台加载器 {#background-loader} ¥Background Loader PixiJS 提供了一个后台加载器,允许你在应用运行时在后台加载资源。这对于加载大型资源或多个资源而不阻塞主线程非常有用。这可以帮助提升应用的响应速度,减少初始加载时间,并可能避免向用户显示多个加载屏幕。 ¥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. ## 加载 Bundle {#loading-bundles} ¥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://pixi.nodejs.cn/assets/flowerTop.png', }, ], }, { name: 'game-screen', assets: [ { alias: 'eggHead', src: 'https://pixi.nodejs.cn/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} ¥Loading Individual Assets 你还可以使用 `Assets.backgroundLoad()` 方法在后台加载单个资源。这对于加载不属于 bundle 的资源或在初始加载后加载其他资源非常有用。 ¥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://pixi.nodejs.cn/assets/flowerTop.png', }); // Load another asset in the background Assets.backgroundLoad({ alias: 'eggHead', src: 'https://pixi.nodejs.cn/assets/eggHead.png', }); ``` ## API 参考 {#api-reference} ¥API Reference - [资源](https://pixijs.download/release/docs/assets.Assets.html) ¥[Assets](https://pixijs.download/release/docs/assets.Assets.html) - [BackgroundLoader](https://pixijs.download/release/docs/assets.BackgroundLoader.html) --- ## 压缩纹理 {#compressed-textures} # 压缩纹理 {#compressed-textures} ¥Compressed Textures 压缩纹理可显著减少内存占用和 GPU 上传时间,尤其是在移动设备或低端硬件上。PixiJS 支持多种压缩纹理格式,但在使用它们之前必须配置相应的加载器。 ¥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} ¥Supported Compressed Texture Formats PixiJS 内置支持多种广泛使用的压缩纹理格式: ¥PixiJS provides built-in support for several widely-used compressed texture formats: | 格式 | 文件扩展名 | 描述 | | -------- | ---------- | --------------------------------------------- | | **DDS** | `.dds` | DirectDraw Surface 格式,支持 DXT 变体 (S3TC) | | **KTX** | `.ktx` | Khronos 格式,支持 ETC 和其他方案 | | **KTX2** | `.ktx2` | 支持 Basis Universal 和超压缩格式的现代容器 | | **基础** | `.basis` | 高度压缩格式,可转码为多种 GPU 格式 | ## 注册加载器 {#registering-loaders} ¥Registering Loaders PixiJS 不会自动包含压缩纹理支持。要使用这些格式,你必须在加载任何资源之前明确导入必要的加载器: ¥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 信息 你只需要导入你正在使用的格式的加载器。这些导入必须在调用 `Assets.load` 之前运行。 ¥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} ¥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 将根据用户设备,使用正确的加载器和 GPU 兼容的转码路径解析并上传纹理。 ¥PixiJS will parse and upload the texture using the correct loader and GPU-compatible transcoding path based on the user's device. --- ## 与 AssetPack 集成 {#integration-with-assetpack} ¥Integration with AssetPack [**AssetPack**](https://pixijs.io/assetpack) 支持在构建步骤中自动生成压缩纹理变体。你可以: ¥[**AssetPack**](https://pixijs.io/assetpack) supports automatic generation of compressed texture variants during the build step. You can: - 将 `.png` 或 `.jpg` 文件转换为 `.basis`、`.ktx2` 或 `.dds` 格式。 ¥Convert `.png` or `.jpg` files into `.basis`, `.ktx2`, or `.dds` formats. - 在清单文件中使用相同的别名或通配符模式引用压缩文件。 ¥Reference compressed files in your manifest using the same aliases or wildcard patterns. - 使用相同的清单和加载工作流程 - PixiJS 将根据设备解析并加载最佳可用变体。 ¥Use the **same manifest and loading workflow** — PixiJS will resolve and load the best available variant based on the device. ### 示例 {#example} ¥Example 你的清单可能包含: ¥Your manifest might include: ```json { "bundles": [ { "name": "scene", "assets": [ { "alias": "bg", "src": ["assets/bg.ktx2", "assets/bg.basis", "assets/bg.png"] } ] } ] } ``` 如果设备支持,PixiJS 将首先尝试加载 `bg.ktx2` 或 `bg.basis`,并根据需要回退到 `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} ¥Assets PixiJS 拥有 `Assets` 单例,用于简化资源加载。它采用现代设计,基于 Promise,支持缓存感知,并且高度可扩展 - 使其成为所有 PixiJS 资源管理的一站式解决方案! ¥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} ¥Key Capabilities - 通过 Promises 或 async/await 异步加载资源。 ¥**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} ¥Supported File Types | 类型 | 扩展 | 加载器 | | -------- | ---------------------------------------------------------------- | --------------------------------- | | 纹理 | `.png`, `.jpg`, `.gif`, `.webp`, `.avif`, `.svg` | `loadTextures`, `loadSvg` | | 视频纹理 | `.mp4`, `.m4v`, `.webm`, `.ogg`, `.ogv`, `.h264`, `.avi`, `.mov` | `loadVideoTextures` | | 精灵表 | `.json` | `spritesheetAsset` | | 位图字体 | `.fnt`, `.xml`, `.txt` | `loadBitmapFont` | | Web 字体 | `.ttf`, `.otf`, `.woff`, `.woff2` | `loadWebFont` | | JSON | `.json` | `loadJson` | | 文本 | `.txt` | `loadTxt` | | 压缩纹理 | `.basis`, `.dds`, `.ktx`, `.ktx2` | `loadBasis`, `loadDDS`, `loadKTX` | > 需要更多功能?添加自定义解析器! > > ¥Need more? Add custom parsers! --- ## 入门 {#getting-started} ¥Getting started ### 加载资源 {#loading-assets} ¥Loading Assets 使用 PixiJS 加载资源非常简单,只需调用 `Assets.load()` 并传入资源的 URL 即可。此函数返回一个 `Promise`,该 `Promise` 解析为已加载的资源 - 无论是纹理、字体、JSON 还是其他受支持的格式。 ¥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. 你可以提供绝对 URL(例如来自 CDN): ¥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 通常会根据文件扩展名自动确定如何加载资源,并缓存结果以避免重复下载。 ¥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} ¥Repeated Loads Are Safe `Assets` 通过 URL 或别名进行缓存。对相同资源的请求返回相同的纹理。 ¥`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} ¥Asset Aliases 你还可以使用别名来引用资源,而不是使用其完整的 URL。这提供了一种更便捷的资源管理方式,尤其是在 URL 较长或复杂的情况下。 ¥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'); ``` 所有 Asset API 都支持别名,包括 `Assets.load()`、`Assets.get()` 和 `Assets.unload()`。 ¥All Asset APIs support aliases, including `Assets.load()`, `Assets.get()`, and `Assets.unload()`. 定义资源有更复杂的方法,你可以在 [解析器](./resolver.md) 部分阅读相关内容。 ¥There is more complex ways of defining assets and you can read about them in the [Resolver](./resolver.md) section. ### 检索已加载的资源 {#retrieving-loaded-assets} ¥Retrieving Loaded Assets 你还可以使用 `Assets.get()` 检索已加载的资源: ¥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} ¥Unloading Assets 要卸载资源,你可以使用 `Assets.unload()`。这将从缓存中移除资源并释放内存。请注意,如果你在卸载资源后尝试访问它,则需要重新加载。 ¥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} ¥Customizing Asset Loading 你可以通过向 `Assets.init()` 方法提供选项来自定义资源加载过程。这允许你设置资源加载方式的首选项,指定资源的基本路径等等。 ¥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({...}); ``` | 选项 | 类型 | 描述 | | --------------------- | ------------------------- | ----------------------------------------------------- | | `basePath` | `string` | 前缀应用于所有相对资源路径(例如 CDN)。 | | `defaultSearchParams` | `string` | 一个默认 URL 参数字符串,用于附加到所有已加载的资源。 | | `skipDetections` | `boolean` | 跳过资源的环境检测解析器。 | | `manifest` | `Manifest` | 一个命名资源包及其内容的描述符。 | | `preferences` | `AssetPreferences` | 指定每个加载器的首选项 | | `bundleIdentifier` | `BundleIdentifierOptions` | 高级 - 覆盖 bundlesId 的生成方式。 | --- ## 高级用法 {#advanced-usage} ¥Advanced Usage `Assets` API 中提供了一些高级功能,可以帮助你更有效地管理资源。你可以在其余文档中阅读有关这些功能的更多信息: ¥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: - [解析资源](./resolver.md) ¥[Resolving Assets](./resolver.md) - [Manifests & Bundles(推荐)](./manifest.md) ¥[Manifests & Bundles (Recommended)](./manifest.md) - [背景加载](./background-loader.md) ¥[Background Loading](./background-loader.md) - [压缩纹理](./compressed-textures.md) ¥[Compressed Textures](./compressed-textures.md) --- ## API 参考 {#api-reference} ¥API Reference - [概述](https://pixijs.download/release/docs/assets.html) ¥[Overview](https://pixijs.download/release/docs/assets.html) - [资源](https://pixijs.download/release/docs/assets.Assets.html) ¥[Assets](https://pixijs.download/release/docs/assets.Assets.html) --- ## 清单和 Bundle {#manifests--bundles} # 清单和 Bundle {#manifests--bundles} ¥Manifests & Bundles PixiJS 通过 Manifest 和 Bundles 提供结构化且可扩展的资源管理方法。这是在 PixiJS 应用中管理资源的推荐方法,尤其是对于大型项目或需要根据上下文或用户交互动态加载资源的项目。本指南解释了它们是什么、如何使用它们,以及如何使用 [AssetPack](https://github.com/pixijs/AssetPack)(一个旨在自动化清单和包创建的工具)高效地生成它们。 ¥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} ¥What Is a Manifest? Manifest 是一个描述符对象,用于定义你的资源加载策略。它列出了所有 bundles,每个 bundles 都包含按名称和别名分组的资源。此结构允许基于应用上下文(例如加载屏幕资源、特定于关卡的内容等)延迟加载资源。 ¥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} ¥Initializing With a Manifest 要使用清单初始化 PixiJS 资源处理: ¥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'); ``` --- ## 什么是 Bundle? {#what-is-a-bundle} ¥What Is a Bundle? Bundle 是一组由共享名称标识的资源。Bundles 可以在清单文件中预定义,也可以在运行时动态注册。 ¥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. ### 动态添加 Bundle {#adding-a-bundle-dynamically} ¥Adding a Bundle Dynamically 此方法对于需要动态定义 bundle 的场景非常有用: ¥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'); ``` --- ## 推荐工具:AssetPack {#recommended-tool-assetpack} ¥Recommended Tool: AssetPack 手动管理清单和包很容易出错。[**AssetPack**](https://pixijs.io/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} ¥Key Benefits - 按目录或模式组织资源 ¥Organizes assets by directory or pattern - 支持 PixiJS 清单格式的输出 ¥Supports output in PixiJS manifest format - 减少样板代码和手动错误的风险 ¥Reduces boilerplate and risk of manual mistakes 你可以将 AssetPack 集成到构建管道中,以生成清单文件并使用 `Assets.init({ manifest })` 加载它。 ¥You can integrate AssetPack into your build pipeline to generate the manifest file and load it using `Assets.init({ manifest })`. --- ## 解析器 {#resolver} # 解析器 {#resolver} ¥Resolver 在 PixiJS 中,资源管理以 `UnresolvedAsset` 和 `ResolvedAsset` 的概念为中心。该系统旨在支持多格式资源、条件加载以及基于平台功能(例如 WebP 支持、设备分辨率或性能限制)的运行时优化。 ¥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). 开发者无需指定固定的 URL,而是描述可以加载哪些资源 - PixiJS 会动态选择最佳选项。 ¥Rather than specifying a fixed URL, developers describe what assets _could_ be loaded — and PixiJS selects the best option dynamically. ## 解析器生命周期 {#resolver-lifecycle} ¥Resolver Lifecycle 分辨率过程包含四个关键步骤: ¥The resolution process involves four key steps: 1. 未解析的资源创建:使用字符串或对象定义的资源在内部被规范化为 `UnresolvedAsset` 实例。这些包括别名、通配符路径、解析器提示和自定义数据等元数据。 ¥**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. 源扩展 `UnresolvedAsset` 的 `src` 字段可以是字符串或字符串数​​组。PixiJS 会将任何通配符模式(例如 `myAsset@{1,2}x.{png,webp}`)扩展为具体的候选 URL 列表。 ¥**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. 最佳匹配选择:PixiJS 会评估所有候选 URL,并使用平台感知启发式算法来选择最合适的源。因素包括支持的格式(例如 WebP 与 PNG)、设备像素比以及自定义配置(例如首选格式)。 ¥**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 输出结果为 `ResolvedAsset`,包含特定 URL 和所有必需的元数据,可传递给相关解析器并加载到内存中。 ¥**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} ¥Using Unresolved Assets `UnresolvedAsset` 是 PixiJS 中用于定义资源的主要结构。它允许你指定源 URL、别名以及加载所需的任何其他数据。它们更复杂,但也更强大。 ¥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. | 字段 | 类型 | 描述 | | -------------------- | -------------------- | --------------------------------------------------------------------- | | `alias` | `string \| string[]` | 用于稍后引用此资源的一个或多个别名。 | | `src` | `string \| string[]` | 一个或多个资源候选路径。支持通配符。 | | `loadParser`(可选) | `string` | 一个用于处理资源(例如 `'loadTextures'`、`'loadJson'`)的专用解析器。 | | `data`(可选) | `any` | 传递给加载器的额外数据。这会根据解析器类型而有所不同。 | ## 示例 {#examples} ¥Examples ### 加载单个资源 {#loading-a-single-asset} ¥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} ¥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} ¥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 将根据运行时功能选择最佳匹配(例如,如果支持,则选择 WebP;如果在高分辨率显示器上,则选择 2x)。 ¥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} ¥Related Tools and Features - 资源包:如果你管理大型资源集,[AssetPack](https://pixijs.io/assetpack) 可以使用 glob 模式生成优化的清单,并自动输出 `UnresolvedAsset` 结构。 ¥**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. - 资源清单和资源包:使用 [清单和包](./manifest.md) 预定义未解析的资源组,并通过 `Assets.loadBundle` 加载它们。 ¥**Asset Manifests & Bundles**: Use [manifests and bundles](./manifest.md) to predefine groups of unresolved assets and load them via `Assets.loadBundle`. --- ## SVG {#svgs} # SVG {#svgs} ### 概述 {#overview} ¥Overview PixiJS 为渲染 SVG 提供强大的支持,允许开发者将可缩放矢量图形无缝集成到他们的项目中。本指南探讨了在 PixiJS 中使用 SVG 的不同方法,涵盖实时渲染、性能优化和潜在陷阱。 ¥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. --- ### 为什么使用 SVG? {#why-use-svgs} ¥Why Use SVGs? 与 PNG 等光栅图片相比,SVG 有几个优势: ¥SVGs have several advantages over raster images like PNGs: ✅ 文件大小更小 - SVG 可以比 PNG 小得多,尤其是对于大而简单的形状。高分辨率 PNG 可能有几兆字节,而等效 SVG 可能只有几千字节。 ¥✅ **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. ✅ 可扩展性 - SVG 可以缩放而不会损失质量,非常适合响应式应用和 UI 元素。 ¥✅ **Scalability** – SVGs scale without losing quality, making them perfect for responsive applications and UI elements. ✅ 渲染后可编辑 - 与纹理不同,通过 Graphics 渲染的 SVG 可以动态修改(例如,更改描边颜色、修改形状)。 ¥✅ **Editable After Rendering** – Unlike textures, SVGs rendered via Graphics can be modified dynamically (e.g., changing stroke colors, modifying shapes). ✅ 适用于简单图形 - 如果图形由基本形状和路径组成,则可以将 SVG 高效地渲染为矢量图形。 ¥✅ **Efficient for Simple Graphics** – If the graphic consists of basic shapes and paths, SVGs can be rendered efficiently as vector graphics. 但是,解析 SVG 的计算成本也很高,尤其是对于具有许多路径或效果的复杂插图。 ¥However, SVGs can also be computationally expensive to parse, particularly for intricate illustrations with many paths or effects. --- ### 在 PixiJS 中渲染 SVG 的方法 {#ways-to-render-svgs-in-pixijs} ¥Ways to Render SVGs in PixiJS PixiJS 提供两种主要的 SVG 渲染方式: ¥PixiJS offers two primary ways to render SVGs: 1. 作为纹理 - 将 SVG 转换为纹理以渲染为精灵。 ¥**As a Texture** – Converts the SVG into a texture for rendering as a sprite. 2. 作为图形对象 - 解析 SVG 并将其渲染为矢量几何图形。 ¥**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. 将 SVG 渲染为纹理 {#rendering-svgs-as-textures} ¥ Rendering SVGs as Textures ### 概述 {#overview-1} ¥Overview SVG 可以作为纹理加载并在 Sprite 中使用。此方法高效,但不保留矢量图形的可扩展性。 ¥SVGs can be loaded as textures and used within Sprites. This method is efficient but does not retain the scalability of vector graphics. ### 示例 {#example} ¥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} ¥Scaling Textures 在将 SVG 作为纹理加载时,你可以指定分辨率来控制其大小:这确实会增加内存使用量,但保真度更高。 ¥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} ¥Pros & Cons ✅ 渲染速度快(渲染为四边形,而不是几何体)✅ 适合静态图片✅ 支持分辨率缩放以实现精确大小✅ 非常适合不需要清晰矢量缩放的复杂 SVG(例如,具有固定尺寸的 UI 组件)❌ 缩放不干净(缩放可能会导致像素化)❌ 灵活性较差(无法动态修改形状)❌ 纹理大小限制纹理最多只能为 4096x4096 像素,因此如果你需要渲染更大的 SVG,则需要使用 Graphics 方法。 ¥✅ **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} ¥Best Use Cases - 背景图片 ¥Background images - 装饰元素 ¥Decorative elements - 不需要缩放的性能关键型应用 ¥Performance-critical applications where scaling isn’t needed - 不需要清晰矢量缩放的复杂 SVG(例如,固定大小的 UI 组件) ¥Complex SVGs that do not require crisp vector scaling (e.g., fixed-size UI components) --- ## 2. 将 SVG 渲染为图形 {#rendering-svgs-as-graphics} ¥ Rendering SVGs as Graphics ### 概述 {#overview-2} ¥Overview PixiJS 可以使用 `Graphics` 类将 SVG 渲染为真正的可缩放矢量图形。 ¥PixiJS can render SVGs as real scalable vector graphics using the `Graphics` class. ### 示例 {#example-1} ¥Example ```ts const graphics = new Graphics().svg(''); ``` 如果你想多次使用同一个 SVG,则可以使用 `GraphicsContext` 在多个图形对象之间共享已解析的 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); ``` ### 将 SVG 加载为图形 {#loading-svgs-as-graphics} ¥Loading SVGs as Graphics 你可以使用 PixiJS 的 `Assets.load` 方法加载 SVG 文件,而不是直接传递 SVG 字符串。这将返回一个 `GraphicsContext` 对象,可用于高效地创建多个 `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); ``` 由于它是通过 `Assets.load` 加载的,因此它将被缓存和重用,就像纹理一样。 ¥Since it's loaded via `Assets.load`, it will be cached and reused, much like a texture. ### 优点和缺点 {#pros--cons-1} ¥Pros & Cons ✅ 保留矢量可扩展性(缩放时无像素化)✅ 渲染后可修改(更改颜色、笔触等)✅ 适用于简单图形✅ 如果 SVG 结构不变,则渲染速度快(无需重新解析)❌ 解析成本更高(复杂的 SVG 渲染速度可能很慢)❌ 不适合静态图片 ¥✅ **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-1} ¥Best Use Cases - 需要调整大小的图标和 UI 元素 ¥Icons and UI elements that need resizing - 当玩家放大时需要保持清晰的游戏世界 ¥A game world that needs to remain crisp as a player zooms in - 需要动态修改 SVG 的交互式图形 ¥Interactive graphics where modifying the SVG dynamically is necessary --- ## SVG 渲染注意事项 {#svg-rendering-considerations} ¥SVG Rendering Considerations ### 支持的功能 {#supported-features} ¥Supported Features PixiJS 支持大多数可以在 Canvas 2D 上下文中渲染的 SVG 功能。以下是常见 SVG 功能及其兼容性的列表: ¥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: | 特性 | 支持 | | ------------------------------ | ---- | | 基本形状(矩形、圆形、路径等) | ✅ | | 渐变 | ✅ | | 描边和填充样式 | ✅ | | 文本元素 | ❌ | | 滤镜(模糊、阴影等) | ❌ | | 剪切路径 | ✅ | | 图案 | ❌ | | 复杂路径和曲线 | ✅ | ### 性能注意事项 {#performance-considerations} ¥Performance Considerations - 复杂 SVG:大型或复杂的 SVG 可能会因解析成本高而减慢渲染启动速度。使用 `GraphicsContext` 缓存和重用已解析的数据。 ¥**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. - 矢量与纹理:如果性能是一个问题,请考虑使用 SVG 作为纹理,而不是将它们渲染为几何图形。但是,请记住,纹理会占用更多内存。 ¥**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. - 实时渲染:避免动态渲染复杂的 SVG。尽可能预加载并重用它们。 ¥**Real-Time Rendering:** Avoid rendering complex SVGs dynamically. Preload and reuse them wherever possible. --- ## 最佳实践和陷阱 {#best-practices--gotchas} ¥Best Practices & Gotchas ### 最佳实践 {#best-practices} ¥Best Practices ✅ 将 Graphics 用于可扩展和动态 SVG ✅ 将 Textures 用于性能敏感型应用✅ 使用 `GraphicsContext` 避免冗余解析✅ 使用纹理时考虑使用 `resolution` 来平衡质量和内存 ¥✅ **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} ¥Gotchas ⚠ 大型 SVG 解析速度可能很慢 - 在 PixiJS 中使用 SVG 之前,请对其进行优化。⚠ 基于纹理的 SVG 无法干净地缩放 - 必要时请使用更高的分辨率。⚠ 并非所有 SVG 功能都受支持 - 复杂的过滤器和文本元素可能无法按预期工作。 ¥⚠ **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. --- 通过了解 PixiJS 如何处理 SVG,开发者可以做出明智的决定,确定何时使用 `Graphics.svg()`、`GraphicsContext` 或 SVG 纹理,平衡特定用例的质量和性能。 ¥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} ¥Renderers PixiJS 渲染器负责使用 WebGL/WebGL2 或 WebGPU 将场景绘制到画布上。这些渲染器是高性能 GPU 加速引擎,由模块化系统组成,可管理从纹理上传到渲染管线的所有内容。 ¥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. 所有 PixiJS 渲染器都继承自一个通用基类,该基类提供一致的方法,例如 `.render()`、`.resize()` 和 `.clear()`,以及用于管理画布、纹理 GC、事件等的共享系统。 ¥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 Types | 渲染器 | 描述 | 状态 | | ---------------- | --------------------------------------------------------- | ----------- | | `WebGLRenderer` | 使用 WebGL/WebGL2 的默认渲染器。支持良好且稳定。 | ✅ 推荐 | | `WebGPURenderer` | 使用 WebGPU 的现代 GPU 渲染器。性能更佳,仍在不断完善中。 | 🚧 实验性 | | `CanvasRenderer` | 使用 2D 画布的后备渲染器。 | ❌ 即将推出 | :::info 信息 WebGPU 渲染器功能齐全,但是,浏览器实现的不一致可能会导致意外行为。建议在生产环境中使用 WebGL 渲染器。 ¥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} ¥Creating a Renderer 你可以使用 `autoDetectRenderer()` 创建最适合你环境的渲染器: ¥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} ¥Rendering a Scene 要渲染场景,你可以使用 `render()` 方法。这将将指定的容器绘制到屏幕或纹理上: ¥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} ¥Resizing the Renderer 要调整渲染器的大小,请使用 `resize()` 方法。这将调整画布大小并更新分辨率: ¥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} ¥Generating Textures 你可以使用 `generateTexture()` 方法从容器生成纹理。这对于从动态内容创建纹理非常有用: ¥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} ¥Resetting State 要重置渲染器的状态,请使用 `resetState()` 方法。这在将 PixiJS 与其他库(如 Three.js)混合使用时非常有用: ¥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); ``` 更多详情,请参阅我们关于 [将 PixiJS 与 Three.js 混合使用](../../third-party/mixing-three-and-pixi.mdx) 的完整指南。 ¥See our full guide on [mixing PixiJS with Three.js](../../third-party/mixing-three-and-pixi.mdx) for more details. --- ## API 参考 {#api-reference} ¥API Reference - [概述](https://pixijs.download/release/docs/rendering.html) ¥[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} ¥Cache As Texture ### 在 PixiJS 中使用 `cacheAsTexture` {#using-cacheastexture-in-pixijs} ¥Using `cacheAsTexture` in PixiJS PixiJS 中的 `cacheAsTexture` 函数是优化应用渲染的强大工具。通过将容器及其子项渲染为纹理,`cacheAsTexture` 可以显著提高静态或不经常更新的容器的性能。让我们探索如何有效地使用它,以及它的好处和注意事项。 ¥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[注意] `cacheAsTexture` 是 PixiJS v8 中与之前的 `cacheAsBitmap` 功能相同的功能。如果你从 v7 或更早版本迁移,只需在代码中将 `cacheAsBitmap` 替换为 `cacheAsTexture`。 ¥`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. ::: --- ### 什么是 `cacheAsTexture`? {#what-is-cacheastexture} ¥What Is `cacheAsTexture`? 设置 `container.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} ¥Basic Usage 这是一个演示如何使用 `cacheAsTexture` 的示例: ¥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://pixi.nodejs.cn/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(); })(); ``` 在此示例中,`container` 及其子项被渲染为单个纹理,从而减少了绘制场景时的渲染开销。 ¥In this example, the `container` and its children are rendered to a single texture, reducing the rendering overhead when the scene is drawn. 使用示例 [此处](../../../../examples/basic/cache-as-texture.mdx)。 ¥Play around with the example [here](../../../../examples/basic/cache-as-texture.mdx). ### 高级用法 {#advanced-usage} ¥Advanced Usage 你可以传递与纹理源选项非常相似的配置对象,而不是使用 true 启用 cacheAsTexture。 ¥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` 是纹理的分辨率。默认情况下,这与你的渲染器或应用相同。 ¥`resolution` is the resolution of the texture. By default this is the same as you renderer or application. - `antialias` 是用于纹理的抗锯齿模式。与分辨率非常相似,这默认为渲染器或应用抗锯齿模式。 ¥`antialias` is the antialias mode to use for the texture. Much like the resolution this defaults to the renderer or application antialias mode. --- ### `cacheAsTexture` 的优势 {#benefits-of-cacheastexture} ¥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} ¥Advanced Details - 内存权衡:每个缓存的纹理都需要 GPU 内存。使用 `cacheAsTexture` 会牺牲渲染速度以换取增加的内存使用量。 ¥**Memory Tradeoff**: Each cached texture requires GPU memory. Using `cacheAsTexture` trades rendering speed for increased memory usage. - GPU 限制:如果你的容器太大(例如,超过 4096x4096 像素),纹理可能无法缓存,具体取决于 GPU 限制。 ¥**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} ¥How It Works Internally 在底层,`cacheAsTexture` 将容器转换为渲染组并将其渲染为纹理。它使用与过滤器相同的纹理缓存机制: ¥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; ``` 一旦纹理被缓存,通过 `updateCacheTexture()` 更新它是高效的,并且会产生最小的开销。它与正常渲染容器一样快。 ¥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} ¥Best Practices #### DO: {#do} - 用于静态内容:将 `cacheAsTexture` 应用于元素不经常更改的容器,例如具有静态装饰的 UI 面板。 ¥**Use for Static Content**: Apply `cacheAsTexture` to containers with elements that don't change frequently, such as a UI panel with static decorations. - 性能优势:使用 `cacheAsTexture` 将复杂容器渲染为单个纹理,从而减少每帧单独处理每个子元素的开销。这对于包含昂贵效果(例如过滤器)的容器特别有用。 ¥**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. - 抗锯齿切换:将抗锯齿设置为 false 可以稍微提高性能,但纹理在其子项边缘周围可能看起来更像素化。 ¥**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: {#dont} - 应用于非常大的容器:避免在过大的容器上使用 `cacheAsTexture`(例如,超过 4096x4096 像素),因为它们可能会因 GPU 限制而无法缓存。而是将它们拆分成更小的容器。 ¥**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. - 过度使用动态内容:在容器上频繁打开/关闭 `cacheAsTexture`,因为这会导致不断重新缓存,从而抵消其好处。最好在一次缓存时将其作为纹理,然后使用 `updateCacheTexture` 来更新它。 ¥**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. - 应用于稀疏内容:不要将 `cacheAsTexture` 用于元素很少或内容稀疏的容器,因为性能改进将微不足道。 ¥**Apply to Sparse Content**: Do not use `cacheAsTexture` for containers with very few elements or sparse content, as the performance improvement will be negligible. - 忽略内存影响:注意 GPU 内存使用情况。每个缓存的纹理都会消耗内存,因此过度使用 `cacheAsTexture` 会导致资源限制。 ¥**Ignore Memory Impact**: Be cautious of GPU memory usage. Each cached texture consumes memory, so overusing `cacheAsTexture` can lead to resource constraints. --- ### 陷阱 {#gotchas} ¥Gotchas - 渲染取决于场景可见性:缓存仅在渲染包含场景时更新。在设置 `cacheAsTexture` 之后但在渲染场景之前修改布局将反映在缓存中。 ¥**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. - 容器渲染时没有变换:缓存的项目以其实际大小渲染,忽略缩放等变换。例如,缩小 50% 的项目,其纹理将以 100% 大小缓存,然后按场景缩小。 ¥**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. - 缓存和过滤器:过滤器可能无法按照预期与 `cacheAsTexture` 一起运行。要缓存滤镜效果,请将项目封装在父容器中,并将 `cacheAsTexture` 应用于父容器。 ¥**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. - 重复使用纹理:如果你想基于容器创建新的纹理,最好使用 `const texture = renderer.generateTexture(container)` 并在你的对象之间共享它! ¥**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! 通过战略性地理解和应用 `cacheAsTexture`,你可以显著提高 PixiJS 项目的渲染性能。祝你编码愉快! ¥By understanding and applying `cacheAsTexture` strategically, you can significantly enhance the rendering performance of your PixiJS projects. Happy coding! --- ## 容器 {#container} # 容器 {#container} ¥Container `Container` 类是 PixiJS 场景图形系统的基础。容器充当场景对象组,允许你构建复杂的层级结构、组织渲染图层,并对对象组应用变换或效果。 ¥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} ¥What Is a Container? `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} ¥Managing Children PixiJS 提供了一个强大的 API,用于在容器中添加、移除、重新排序和交换子元素: ¥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); ``` 要在将子对象移动到其他容器时保持其世界变换,请使用 `reparentChild` 或 `reparentChildAt`: ¥To keep a child’s world transform while moving it to another container, use `reparentChild` or `reparentChildAt`: ```ts otherContainer.reparentChild(child); ``` ### 事件 {#events} ¥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} ¥Finding Children 容器支持使用辅助方法通过 `label` 搜索子项: ¥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" ``` 设置 `deep = true` 以递归搜索所有后代。 ¥Set `deep = true` to search recursively through all descendants. ```ts container.getChildByLabel('ui', true); ``` ### 排序子元素 {#sorting-children} ¥Sorting Children 使用 `zIndex` 和 `sortableChildren` 控制容器内的渲染顺序: ¥Use `zIndex` and `sortableChildren` to control render order within a container: ```ts child1.zIndex = 1; child2.zIndex = 10; container.sortableChildren = true; ``` 如果需要,请调用 `sortChildren()` 手动重新排序: ¥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} ¥Optimizing with Render Groups 可以通过设置 `isRenderGroup = true` 或调用 `enableRenderGroup()` 将容器提升为渲染组。 ¥Containers can be promoted to **render groups** by setting `isRenderGroup = true` or calling `enableRenderGroup()`. 将渲染组用于 UI 层、粒子系统或大型移动子树。更多详情,请参阅 [渲染组指南](../../../concepts/render-groups.md)。 ¥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} ¥Cache as Texture PixiJS 中的 `cacheAsTexture` 函数是优化应用渲染的强大工具。通过将容器及其子项渲染为纹理,`cacheAsTexture` 可以显著提高静态或不经常更新的容器的性能。 ¥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. 设置 `container.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. :::info[注意] `cacheAsTexture` 是 PixiJS v8 中与之前的 `cacheAsBitmap` 功能相同的功能。如果你从 v7 或更早版本迁移,只需在代码中将 `cacheAsBitmap` 替换为 `cacheAsTexture`。 ¥`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); ``` 有关更高级的用法,包括设置缓存选项和处理动态内容,请参阅 [缓存为纹理指南](./cache-as-texture.md)。 ¥For more advanced usage, including setting cache options and handling dynamic content, refer to the [Cache as Texture guide](./cache-as-texture.md). --- ## API 参考 {#api-reference} ¥API Reference - [容器](https://pixijs.download/release/docs/scene.Container.html) ¥[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} ¥Graphics Fill 如果你是图形新手,请在此处查看 [图形指南](../graphics)。本指南更深入地探讨了图形的特定方面:如何填充它们!PixiJS 中的 `fill()` 方法特别强大,使你能够用颜色、纹理或渐变填充形状。无论你是在设计游戏、UI 组件还是创意工具,掌握 `fill()` 方法对于创建具有视觉吸引力和动态的图形都至关重要。本指南探讨了使用 `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 注意 此处讨论的 `fillStyles` 也可以应用于 Text 对象! ¥The `fillStyles` discussed here can also be applied to Text objects! ::: ## 基本颜色填充 {#basic-color-fills} ¥Basic Color Fills 创建 `Graphics` 对象时,你可以使用 `fill()` 方法轻松地用颜色填充它。这是一个简单的例子: ¥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 ``` ![alt text](/assets/guides/components/image.png) 这将创建一个红色矩形。PixiJS 支持 `fill()` 方法的多种颜色格式。开发者可以根据自己的需求选择格式。例如,CSS 颜色字符串易于使用且易读,十六进制字符串紧凑且广泛用于设计工具,数字对于编程使用而言非常高效。数组和颜色对象提供精确的控制,使其成为高级图形的理想选择。 ¥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 颜色字符串(例如 'red'、'blue') ¥CSS color strings (e.g., 'red', 'blue') - 十六进制字符串(例如 '#ff0000') ¥Hexadecimal strings (e.g., '#ff0000') - 数字(例如 `0xff0000`) ¥Numbers (e.g., `0xff0000`) - 数组(例如 `[255, 0, 0]`) ¥Arrays (e.g., `[255, 0, 0]`) - 用于精确颜色控制的颜色对象 ¥Color objects for precise color control ### 示例: {#examples} ¥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} ¥Fill with a Style Object 对于更高级的填充,你可以使用 `FillStyle` 对象。这允许进行额外的自定义,例如设置不透明度: ¥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 }); ``` ![alt text](/assets/guides/components/image-1.png) ## 使用纹理填充 {#fill-with-textures} ¥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); ``` ![alt text](/assets/guides/components/image-2.png) ### 局部与全局纹理空间 {#local-vs-global-texture-space} ¥Local vs. Global Texture Space 纹理可以应用于两个坐标空间: ¥Textures can be applied in two coordinate spaces: - 本地空间(默认):纹理坐标相对于形状的尺寸和位置进行映射。纹理坐标使用标准化坐标系,其中 (0,0) 表示形状的左上角,(1,1) 表示形状的右下角,而不管其实际像素尺寸如何。例如,如果你有一个 300x200 像素的纹理填充 100x100 的形状,则纹理将缩放以精确适合这些 100x100 像素。纹理的左上角 (0,0) 将与形状的左上角对齐,纹理的右下角 (1,1) 将与形状的右下角对齐,根据需要拉伸或压缩纹理。 ¥**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! }); ``` ![alt text](/assets/guides/components/image-13.png) - 全局空间:设置 `textureSpace: 'global'` 以使纹理相对于 Graphics 对象的坐标系定位和缩放。尽管名称如此,但这并不是真正的 "global" - 纹理相对于 Graphics 对象本身保持固定,即使对象移动或缩放,纹理仍保持其位置。查看下面图片如何跨越所有形状(在同一图形中): ¥**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', }); ``` ![alt text](/assets/guides/components/image-11.png) ### 使用矩阵和纹理 {#using-matrices-with-textures} ¥Using Matrices with Textures 要修改纹理坐标,你可以应用变换矩阵,这是一种用于缩放、旋转或平移纹理的数学工具。如果你不熟悉变换矩阵,它们可以精确控制纹理的渲染方式,你可以探索有关它们的更多信息 [此处](https://learnwebgl.brown37.net/10_surface_properties/texture_mapping_transforms.html#:~:text=Overview%C2%B6,by%2D4%20transformation%20matrix)。 ¥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 }); ``` ![alt text](/assets/guides/components/image-4.png) ### 纹理陷阱 {#texture-gotchas} ¥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. 两个纹理的力量:纹理应为 2 的幂维数,以便在 WebGL1 中正确平铺(WebGL2 和 WebGPU 都可以)。 ¥**Power of Two Textures**: Textures should be power-of-two dimensions for proper tiling in WebGL1 (WebGL2 and WebGPU are fine). ## 使用渐变填充 {#fill-with-gradients} ¥Fill with Gradients PixiJS 支持线性和径向渐变,可以使用 `FillGradient` 类创建。渐变对于为形状和文本添加视觉深度和动态样式特别有用。 ¥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 线性渐变沿直线创建平滑的颜色过渡。这是一个简单的线性渐变的示例: ¥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); ``` ![alt text](/assets/guides/components/image-5.png) 你可以使用以下属性控制渐变方向: ¥You can control the gradient direction with the following properties: - `start {x, y}`:这些定义了渐变的起点。例如,在线性渐变中,这是第一个颜色停止点的位置。这些值通常以相对坐标 (0 到 1) 表示,其中 `0` 表示形状的左/上边缘,`1` 表示形状的右/下边缘。 ¥`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}`:这些定义了渐变的结束点。与 `start {x, y}` 类似,这些值指定最后一个颜色停止点在形状的局部坐标系中的位置。 ¥`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. 使用这些属性,你可以创建各种渐变效果,例如水平、垂直或对角线过渡。例如,将 `start` 设置为 `{x: 0, y: 0}` 并将 `end` 设置为 `{x: 1, y: 1}` 将导致从形状的左上角到右下角的对角渐变。 ¥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' }, ], }); ``` ![alt text](/assets/guides/components/image-6.png) ### 径向渐变 {#radial-gradients} ¥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); ``` ![alt text](/assets/guides/components/image-7.png) 你可以使用以下属性控制渐变的形状和大小: ¥You can control the gradient's shape and size using the following properties: - `center {x, y}`:这些定义了渐变开始的内圆的中心。通常,这些值以相对坐标(0 到 1)表示,其中 `0.5` 代表形状的中心。 ¥`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`:内圆的半径。这决定了渐变的起点的大小。 ¥`innerRadius`: The radius of the inner circle. This determines the size of the gradient's starting point. - `outerCenter {x, y}`:这些定义了渐变结束的外圆的中心。与 `center {x, y}` 一样,这些值也是相对坐标。 ¥`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`:外圆的半径。这决定了渐变的结束点的大小。 ¥`outerRadius`: The radius of the outer circle. This determines the size of the gradient's ending point. 通过调整这些属性,你可以创建各种效果,例如小而集中的渐变或大而膨胀的效果。例如,设置较小的 `r0` 和较大的 `r1` 将创建一个渐变,该渐变直到达到内圆半径才开始过渡。 ¥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); ``` ![alt text](/assets/guides/components/image-8.png) ### 渐变陷阱 {#gradient-gotchas} ¥Gradient Gotcha's 1. 内存管理:当不再需要渐变时,使用 `fillGradient.destroy()` 释放资源。 ¥**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} ¥Combining Textures and Colors 你可以将纹理或渐变与色调和 alpha 相结合,以实现更复杂且更具视觉吸引力的效果。这允许你在纹理或渐变的顶部叠加颜色,并使用 alpha 值调整其透明度。 ¥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, }); ``` ![alt text](/assets/guides/components/image-10.png) ```ts const obj = new Graphics().rect(0, 0, 100, 100).fill({ texture: texture, color: 'yellow', alpha: 0.5, }); ``` ![alt text](/assets/guides/components/image-9.png) --- 希望本指南向你展示了使用图形(和文本!)时填充是多么简单和强大。通过掌握 `fill()` 方法,你可以解锁在 PixiJS 中创建视觉动态和引人入胜的图形的无限可能性。玩得开心! ¥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} ¥Graphics Pixel Line `pixelLine` 属性是 PixiJS 图形 API 的一个巧妙功能,允许你创建保持 1 像素粗细的线条,无论缩放或缩放级别如何。作为图形 API 的一部分,它为开发者提供了 PixiJS 为构建和描边形状提供的所有功能。此功能对于实现清晰、像素完美的视觉效果特别有用,特别是在复古风格或基于网格的游戏、技术绘图或 UI 渲染中。 ¥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); })(); ``` ## 如何使用 `pixelLine`? {#how-to-use-pixelline} ¥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); ``` 在此示例中,无论你如何变换或缩放 `Graphics` 对象,红线在屏幕上的显示厚度始终为 1 像素。 ¥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. --- ## 为什么使用 `pixelLine`? {#why-use-pixelline} ¥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} ¥ **Retro or Pixel Art Games** - 像素艺术游戏严重依赖于保持清晰、精确的视觉效果。`pixelLine` 属性可确保线条不会模糊或与其他像素元素不一致地缩放。 ¥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 和 HUD 元素** {#ui-and-hud-elements} ¥ **UI and HUD Elements** - 对于边框、分隔符或下划线等 UI 元素,一致的 1 像素厚度可提供专业、干净的外观。 ¥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} ¥ **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} ¥How it works 当 `pixelLine` 设置为 `true` 时,这是使用 WebGL 或 WebGPU 的原生线条渲染方法在后台实现的。 ¥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. 更简单的绘制过程:PixiJS 中的常规线条(当 `pixelLine` 为 `false` 时)需要额外的步骤才能绘制。PixiJS 必须确定线条的粗细,并创建一个看起来像线但实际上由三角形组成的形状。 ¥**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. 直接线条绘制:使用 `pixelLine` 时,我们可以告诉显卡 "只需从点 A 到点 B 画一条线",它知道该怎么做。这比创建和填充形状更简单、更快捷。 ¥**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. 可以将其想象成在纸上画一条线 - `pixelLine` 就像使用钢笔画一条直线,而普通线条就像必须仔细地在一个细矩形上着色。钢笔方法自然更快更简单! ¥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} ¥Caveats and Gotchas 虽然 `pixelLine` 属性非常有用,但也有一些限制和需要注意的事项: ¥While the `pixelLine` property is incredibly useful, there are some limitations and things to keep in mind: ### 1. **厚度为 1px,就是这样!** {#its-1px-thick-thats-it} ¥ **Its 1px thick, thats it!** - 线条始终为 1px 粗细,无法更改,因为它使用 GPU 来绘制线条。 ¥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} ¥ **Hardware may render differently** - 由于处理线光栅化的方式不同,不同的 GPU 和图形硬件渲染线的方式可能略有不同。例如,某些 GPU 可能会略微不同地定位线条或应用不同的抗锯齿技术。这是 GPU 线渲染的固有限制,超出了 PixiJS 的控制范围。 ¥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} ¥ **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} ¥Example: Box with Pixel-Perfect Stroke 这是一个具有像素完美描边的填充框的示例。框本身会缩放和增长,但笔触保持 1 像素宽: ¥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); ``` 在此示例中,蓝色框在缩放时会变大,但红色笔触保持 1 像素厚度,无论缩放比例如何,都能提供清晰的轮廓。 ¥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. --- ## 何时避免使用 `pixelLine` {#when-to-avoid-using-pixelline} ¥When to Avoid Using `pixelLine` - 你想要一条不是 1px 粗的线:不要使用 `pixelLine`。 ¥**You want a line that is not 1px thick:** Don't use `pixelLine`. - 你希望线条缩放:不要使用 `pixelLine` ¥**You want the line to scale:** Don't use `pixelLine` --- ## 结论 {#conclusion} ¥Conclusion 对于希望创建在转换下保持一致的清晰、像素完美的线条的开发者来说,PixiJS 工具箱中的 `pixelLine` 属性非常有用。通过了解它的优势和局限性,你可以将其合并到你的项目中,以在视觉和功能元素中获得干净、专业的结果。 ¥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) 是一款强大而灵活的工具,用于渲染矩形、圆形、星形和自定义多边形等形状。它还可以通过组合多个基元来创建复杂形状,并支持渐变、纹理和蒙版等高级功能。 ¥[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} ¥**Available Shapes** PixiJS v8 支持多种形状基元: ¥PixiJS v8 supports a variety of shape primitives: ### Basic Primitives - Line - Rectangle - Rounded Rectangle - Circle - Ellipse - Arc - Bezier / Quadratic Curves ### 高级图元 {#advanced-primitives} ¥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 支持 {#svg-support} ¥SVG Support 你还可以加载 SVG 路径数据,但由于 Pixi 性能优化的三角测量系统,复杂的孔洞几何体渲染可能不准确。 ¥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** {#graphicscontext} `GraphicsContext` 类是 PixiJS 全新图形模型的核心。它包含所有绘图命令和样式,允许多个 `Graphics` 实例重复使用相同的形状数据: ¥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 ``` 此模式在渲染重复或动画形状(例如基于帧的 SVG 交换)时特别有效: ¥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 信息 如果你在创建 `Graphics` 对象时没有显式传递 `GraphicsContext`,那么在内部,它将有自己的上下文,可通过 `myGraphics.context` 访问。 ¥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`. ::: ### 销毁 GraphicsContext {#destroying-a-graphicscontext} ¥Destroying a GraphicsContext 销毁 `GraphicsContext` 时,所有共享它的 `Graphics` 实例也将被销毁。这一点至关重要,需要牢记,因为如果不小心,可能会导致意外行为。 ¥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} ¥**Creating Holes** 使用 `.cut()` 从前一个形状中移除一个形状: ¥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} ¥**Graphics Is About Building, Not Drawing** 尽管 `.rect()` 或 `.circle()` 等函数的术语相同,但 `Graphics` 并不会立即绘制任何内容。相反,每个方法都会构建一个存储在 `GraphicsContext` 中的几何图元列表。这些叶节点随后会在对象绘制到屏幕上或在其他上下文(例如蒙版)中使用时进行渲染。 ¥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 ``` 你可以将 `Graphics` 视为蓝图构建器:它定义了要绘制的内容,但没有定义何时绘制。这就是为什么 `Graphics` 对象可以被重用、克隆、屏蔽和转换,而无需在实际渲染之前进行额外计算。 ¥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} ¥**Performance Best Practices** - 无需每帧都清除并重建图形。如果你的内容是动态的,最好交换预先构建的 `GraphicsContext` 对象,而不是重新创建它们。 ¥**Do not clear and rebuild graphics every frame**. If your content is dynamic, prefer swapping prebuilt `GraphicsContext` objects instead of recreating them. - 完成后使用 `Graphics.destroy()` 进行清理。共享上下文不会自动销毁。 ¥**Use `Graphics.destroy()`** to clean up when done. Shared contexts are not auto-destroyed. - 使用多个简单的 `Graphics` 对象而不是一个复杂的对象来维护 GPU 批处理。 ¥**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} ¥**Caveats and Gotchas** - 内存泄漏:不再需要时调用 `.destroy()`。 ¥**Memory Leaks**: Call `.destroy()` when no longer needed. - SVG 和孔洞:并非所有 SVG 空洞路径都能正确进行三角测量。 ¥**SVG and Holes**: Not all SVG hole paths triangulate correctly. - 改变几何形状:谨慎使用 `.clear()`。首选上下文切换。 ¥**Changing Geometry**: Use `.clear()` sparingly. Prefer swapping contexts. - 透明度和混合模式:这些适用于每个图元。如果要扁平化效果,请使用 `RenderTexture`。 ¥**Transparency and Blend Modes**: These apply per primitive. Use `RenderTexture` if you want to flatten effects. --- ## **API 参考** {#api-reference} ¥**API Reference** - [图形](https://pixijs.download/release/docs/scene.Graphics.html) ¥[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} ¥Scene Objects 在 PixiJS 中,场景对象是应用显示层次结构的构建块。它们包括容器、精灵、文本、图形和其他可绘制实体,这些实体构成了场景图 - 一个树状结构,决定了渲染的内容、渲染方式和渲染顺序。 ¥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. ## 容器 vs. 叶节点 {#containers-vs-leaf-nodes} ¥Containers vs. Leaf Nodes PixiJS 中的场景对象可以分为容器和叶节点: ¥Scene objects in PixiJS can be divided into **containers** and **leaf nodes**: ### 容器 {#containers} ¥Containers `Container` 是 v8 中所有场景对象的基类(取代了旧的 `DisplayObject`)。 ¥`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. - 示例:`Application.stage`,用户定义的组。 ¥Examples: `Application.stage`, user-defined groups. ```ts const group = new Container(); group.addChild(spriteA); group.addChild(spriteB); ``` ### 叶节点 {#leaf-nodes} ¥Leaf Nodes 叶节点是可渲染对象,不应包含子节点。在 v8 中,只有容器才可以有子节点。 ¥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` 尝试向叶节点添加子节点不会导致运行时错误,但是,你可能会遇到意外的渲染行为。因此,如果需要嵌套,请将叶节点封装在 `Container` 中。 ¥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`. **v8 之前(v8 中无效):** ¥**Before v8 (invalid in v8):** ```ts const sprite = new Sprite(); sprite.addChild(anotherSprite); // ❌ Invalid in v8 ``` **v8 方法:** ¥**v8 approach:** ```ts const group = new Container(); group.addChild(sprite); group.addChild(anotherSprite); // ✅ Valid ``` ## 变换 {#transforms} ¥Transforms PixiJS 中的所有场景对象都具有多个属性,用于控制其位置、旋转、缩放和 Alpha 值。这些属性由子对象继承,允许你轻松地将变换应用于对象组。 ¥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. | 属性 | 描述 | | ------------ | --------------------------------------------------------------------------------------------------- | | **position** | X 和 Y 位置以像素为单位给出,并更改对象相对于其父对象的位置,也可以直接用作 `object.x` / `object.y` | | **rotation** | 旋转以弧度指定,并顺时针旋转对象 (0.0 - 2 \* Math.PI) | | **angle** | 角度是旋转的别名,以度而不是弧度指定 (0.0 - 360.0) | | **pivot** | 对象旋转的点(以像素为单位) - 还设置子对象的原点 | | **alpha** | 不透明度从 0.0(完全透明)到 1.0(完全不透明),由子级继承 | | **scale** | 比例指定为百分比,1.0 为 100% 或实际大小,并且可以为 x 和 y 轴独立设置 | | **skew** | Skew 与 CSS skew() 函数类似,在 x 和 y 方向上变换对象,并以弧度指定 | | **锚点?** | 锚点是基于百分比的精灵位置和旋转偏移量。这与 `pivot` 属性不同,后者是基于像素的偏移量。 | ### **锚点 vs Pivot** {#anchor-vs-pivot} ¥**Anchor vs Pivot** 一些叶节点具有一个名为 `anchor` 的附加属性,它是节点位置和旋转的基于百分比的偏移量。这与 `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 信息 设置枢轴或锚点会在视觉上移动节点。这与 CSS 不同,在 CSS 中,更改 `transform-origin` 不会影响元素的位置。 ¥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} ¥**Anchor** - 仅适用于 `Sprite` ¥Available only on `Sprite` - 以规范化值 `(0.0 to 1.0)` 定义 ¥Defined in normalized values `(0.0 to 1.0)` - `(0, 0)` 位于左上角,`(0.5, 0.5)` 位于中心 ¥`(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} ¥**Pivot** - 适用于所有 `Container` ¥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} ¥Measuring Bounds PixiJS 中有两种类型的边界: ¥There are two types of bounds in PixiJS: - 局部边界表示对象在其自身坐标空间中的尺寸。使用 `getLocalBounds()`。 ¥**Local bounds** represent the object’s dimensions in its own coordinate space. Use `getLocalBounds()`. - 全局边界表示对象在世界坐标系中的边界框。使用 `getBounds()`。 ¥**Global bounds** represent the object's bounding box in world coordinates. Use `getBounds()`. ```ts const local = container.getLocalBounds(); const global = container.getBounds(); ``` 如果性能至关重要,你还可以提供自定义 `boundsArea` 来完全避免对每个子组件进行测量。 ¥If performance is critical you can also provide a custom `boundsArea` to avoid per-child measurement entirely. ### 更改大小 {#changing-size} ¥Changing size 要更改容器的大小,可以使用 `width` 和 `height` 属性。这将缩放容器以适应指定的尺寸: ¥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; ``` 单独设置 `width` 和 `height` 可能是一项开销很大的操作,因为它需要重新计算容器及其子节点的边界。为避免这种情况,你可以使用 `setSize()` 同时设置两个属性: ¥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 } ``` 此方法比分别设置 `width` 和 `height` 更高效,因为它只需要一次边界计算。 ¥This method is more efficient than setting `width` and `height` separately, as it only requires one bounds calculation. ## 遮罩场景对象 {#masking-scene-objects} ¥Masking Scene Objects PixiJS 支持遮罩功能,允许你根据场景对象的形状限制其可见区域。这对于创建诸如裁剪、显示或隐藏场景部分等效果非常有用。 ¥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} ¥Types of Masks - 基于图形的蒙版:使用 `Graphics` 对象定义形状。 ¥**Graphics-based masks**: Use a `Graphics` object to define the shape. - 基于精灵的遮罩:使用 `Sprite` 或其他可渲染对象。 ¥**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} ¥Inverse Masks 要创建反向掩码,你可以使用 `setMask` 属性并将其 `inverse` 选项设置为 `true`。这将渲染遮罩之外的所有内容。 ¥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} ¥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. - 对于高级混合,请使用 Alpha 蒙版或滤镜(将在后续指南中介绍)。 ¥For advanced blending, use **alpha masks** or **filters** (covered in later guides). ## 过滤器 {#filters} ¥Filters 容器对象的另一个常见用途是作为过滤内容的宿主。滤镜是一项仅限 WebGL/WebGPU 的高级功能,允许 PixiJS 执行每像素效果,例如模糊和位移。通过在容器上设置过滤器,容器所包含的屏幕区域将在渲染容器的内容后由过滤器处理。 ¥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. ::: 以下是 PixiJS 中默认可用的过滤器列表。然而,有一个带有 [更多过滤器](https://github.com/pixijs/filters) 的社区存储库。 ¥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). | 筛选 | 描述 | | ------------------ | ---------------------------------------------------------------- | | AlphaFilter | 与设置 `alpha` 属性类似,但展平 Container 而不是单独应用于子项。 | | BlurFilter | 应用模糊效果 | | ColorMatrixFilter | 颜色矩阵是应用更复杂的色调或颜色变换(例如棕褐色调)的灵活方法。 | | DisplacementFilter | 置换贴图创建视觉偏移像素,例如创建波浪水效果。 | | NoiseFilter | 创建随机噪声(例如颗粒效果)。 | 在底层,我们提供的每个开箱即用的过滤器都是用 glsl(用于 WebGL)和 wgsl(用于 WebGPU)编写的。这意味着所有过滤器都应该在两个渲染器上工作。 ¥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} ¥Tinting 你可以通过设置 `tint` 属性来为任何场景对象着色。它会修改渲染像素的颜色,类似于在对象上叠加色调。 ¥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 ``` 除非子对象指定自己的 `tint`,否则 `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. `0xFFFFFF` 值禁用着色。 ¥A value of `0xFFFFFF` disables tinting. ```ts const sprite = new Sprite(texture); sprite.tint = 0x00ff00; // Green tint sprite.tint = 0xffffff; // No tint ``` PixiJS 支持多种颜色格式,更多信息请参阅 [颜色文档](../color.md)。 ¥PixiJS supports a variety of color formats and you can find more information from the [Color documentation](../color.md). ## 混合模式 {#blend-modes} ¥Blend Modes 混合模式决定了重叠对象的颜色如何组合。PixiJS 支持多种混合模式,包括: ¥Blend modes determine how colors of overlapping objects are combined. PixiJS supports a variety of blend modes, including: - `normal`:默认混合模式。 ¥`normal`: Default blend mode. - `add`:添加源像素和目标像素的颜色。 ¥`add`: Adds the colors of the source and destination pixels. - `multiply`:将源像素和目标像素的颜色相乘。 ¥`multiply`: Multiplies the colors of the source and destination pixels. - `screen`:反转颜色,相乘,然后再次反转。 ¥`screen`: Inverts the colors, multiplies them, and inverts again. 我们还支持更多高级混合模式,例如 `subtract`、`difference` 和 `overlay`。你可以在 [混合模式文档](../filters.md#advanced-blend-modes) 中找到完整的混合模式列表。 ¥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} ¥Interaction PixiJS 提供了一个强大的交互系统,允许你处理用户输入事件,例如点击/悬停。要在场景对象上启用交互,只需将其 `interactive` 属性设置为 `true` 即可。 ¥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); }); ``` 我们提供了关于 [互动](../events.md) 的详细指南,涵盖如何设置和管理交互,包括命中测试、指针事件等。我们强烈建议你查看一下。 ¥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. ## 使用 `onRender` {#using-onrender} ¥Using `onRender` `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; }; ``` 注意:在 PixiJS v8 中,这取代了 v7 中常见的覆盖 `updateTransform` 的模式,该模式不再每帧运行。`onRender` 函数已注册到容器所属的渲染组。 ¥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 参考 {#api-reference} ¥API Reference - [概述](https://pixijs.download/release/docs/scene.html) ¥[Overview](https://pixijs.download/release/docs/scene.html) - [容器](https://pixijs.download/release/docs/scene.Container.html) ¥[Container](https://pixijs.download/release/docs/scene.Container.html) - [ParticleContainer](https://pixijs.download/release/docs/scene.ParticleContainer.html) - [精灵](https://pixijs.download/release/docs/scene.Sprite.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) - [图形](https://pixijs.download/release/docs/scene.Graphics.html) ¥[Graphics](https://pixijs.download/release/docs/scene.Graphics.html) - [网格](https://pixijs.download/release/docs/scene.Mesh.html) ¥[Mesh](https://pixijs.download/release/docs/scene.Mesh.html) - [文本](https://pixijs.download/release/docs/scene.Text.html) ¥[Text](https://pixijs.download/release/docs/scene.Text.html) - [位图文本](https://pixijs.download/release/docs/scene.BitmapText.html) ¥[Bitmap Text](https://pixijs.download/release/docs/scene.BitmapText.html) - [HTMLText](https://pixijs.download/release/docs/scene.HTMLText.html) --- ## 网格 {#mesh} # 网格 {#mesh} ¥Mesh PixiJS v8 提供了强大的 `Mesh` 系统,可以完全控制几何体、UV、索引、着色器以及 WebGL/WebGPU 状态。网格非常适合自定义渲染效果、高级失真、透视操作或性能调优的渲染管线。 ¥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} ¥**What Is a Mesh?** 网格是一个底层渲染基元,由以下部分组成: ¥A mesh is a low-level rendering primitive composed of: - 几何图形:顶点位置、UV、索引和其他属性 ¥**Geometry**: Vertex positions, UVs, indices, and other attributes - 着色器:定义几何体渲染方式的 GPU 程序 ¥**Shader**: A GPU program that defines how the geometry is rendered - 状态:GPU 状态配置(例如混合、深度、模板) ¥**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** {#meshgeometry} PixiJS 中的所有网格均使用 `MeshGeometry` 类构建。此类允许你定义顶点位置、UV 坐标以及描述网格形状和纹理映射的索引。 ¥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} ¥Built-in Mesh Types ### MeshSimple {#meshsimple} 一个基于 `Mesh` 的最小封装器,可直接接受顶点、UV 和索引数组。适用于快速静态或动态网格。 ¥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]), }); ``` - 使用 `autoUpdate = true` 逐帧更新几何体。 ¥Use `autoUpdate = true` to update geometry per frame. - 访问 `mesh.vertices` 以读取/写入数据。 ¥Access `mesh.vertices` to read/write data. ### MeshRope {#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` 重复纹理;`0` 拉伸纹理。 ¥`textureScale > 0` repeats texture; `0` stretches it. - `autoUpdate = true` 每帧都会重新评估几何体。 ¥`autoUpdate = true` re-evaluates geometry each frame. ### MeshPlane {#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, }); ``` - 当 `autoResize = true` 时,纹理更新时会自动调整大小。 ¥Automatically resizes on texture update when `autoResize = true`. ### PerspectiveMesh {#perspectivemesh} 一个特殊的 `MeshPlane` 子类,通过变换 UV 来应用透视校正。 ¥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, }); ``` - 通过 `setCorners(...)` 设置角点坐标。 ¥Set corner coordinates via `setCorners(...)`. - 非常适合在 2D 中模拟 3D 投影。 ¥Ideal for emulating 3D projection in 2D. --- ## **API 参考** {#api-reference} ¥**API Reference** - [网格](https://pixijs.download/release/docs/scene.Mesh.html) ¥[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) - [着色器](https://pixijs.download/release/docs/rendering.Shader.html) ¥[Shader](https://pixijs.download/release/docs/rendering.Shader.html) - [质地](https://pixijs.download/release/docs/rendering.Texture.html) ¥[Texture](https://pixijs.download/release/docs/rendering.Texture.html) --- ## 九宫格精灵 {#nineslice-sprite} # 九宫格精灵 {#nineslice-sprite} ¥NineSlice Sprite `NineSliceSprite` 是 `Sprite` 的一种特殊类型,允许在保留角和边的同时调整纹理大小。它对于构建可扩展的 UI 元素(例如按钮、面板或带有圆角或装饰边框的窗口)特别有用。 ¥`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); ``` 你也可以只传递一个纹理,切片值将恢复为默认值或从纹理的 `defaultBorders` 推断出来。 ¥You can also pass just a texture, and the slice values will fall back to defaults or be inferred from the texture’s `defaultBorders`. ## **NineSlice 的工作原理** {#how-nineslice-works} ¥**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} ¥**Width and Height Behavior** 在 `NineSliceSprite` 上设置 `.width` 和 `.height` 会更新几何顶点,而不是纹理 UV。这允许纹理根据切片区域正确重复或拉伸。这也意味着 `width` 和 `height` 属性与 `scale` 属性不同。 ¥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} ¥**Original Width and Height** 如果你需要知道九宫格的原始大小,可以通过 `originalWidth` 和 `originalHeight` 属性访问。这些值在创建 `NineSliceSprite` 时设置,表示在应用任何缩放或调整大小之前纹理的尺寸。 ¥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} ¥**Dynamic Updates** 你可以在运行时更改切片尺寸或大小: ¥You can change slice dimensions or size at runtime: ```ts nineSlice.leftWidth = 20; nineSlice.topHeight = 25; ``` 每个 setter 都会触发几何更新以反映更改。 ¥Each setter triggers a geometry update to reflect the changes. --- ## **API 参考** {#api-reference} ¥**API Reference** - [NineSliceSprite](https://pixijs.download/release/docs/scene.NineSliceSprite.html) --- ## 粒子容器 {#particle-container} # 粒子容器 {#particle-container} ¥Particle Container PixiJS v8 通过 `ParticleContainer` 和 `Particle` 类引入了高性能粒子系统。该系统专为渲染大量轻量级视觉效果(例如火花、气泡、兔子或爆炸)而设计,通过去除所有不必要的开销来提供原始速度。 ¥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** Particle API 稳定但处于实验阶段。它的界面可能会在未来的 PixiJS 版本中改进。我们欢迎你提供反馈,以指导其开发。 ¥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); ``` ## **为什么使用 ParticleContainer?** {#why-use-particlecontainer} ¥**Why Use ParticleContainer?** - 极致性能:以高 FPS 渲染数十万甚至数百万个粒子。 ¥**Extreme performance**: Render hundreds of thousands or even millions of particles with high FPS. - 轻量级设计:粒子比 `Sprite` 更高效,缺少子级、事件或过滤器等额外功能。 ¥**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). ### **性能提示:静态 vs. 动态** {#performance-tip-static-vs-dynamic} ¥**Performance Tip: Static vs. Dynamic** - 动态属性每帧都会上传到 GPU。 ¥**Dynamic properties** are uploaded to the GPU every frame. - 静态属性仅在调用 `update()` 时上传。 ¥**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(); ``` ## **限制和 API 差异** {#limitations-and-api-differences} ¥**Limitations and API Differences** `ParticleContainer` 的设计注重速度和简洁性。因此,它不支持完整的 `Container` API: ¥`ParticleContainer` is designed for speed and simplicity. As such, it doesn't support the full `Container` API: ### ❌ 不可用: {#-not-available} ¥❌ Not Available: - `addChild()`, `removeChild()` - `getChildAt()`, `setChildIndex()` - `swapChildren()`, `reparentChild()` ### ✅ 替代用法: {#-use-instead} ¥✅ Use Instead: - `addParticle(particle)` - `removeParticle(particle)` - `removeParticles(beginIndex, endIndex)` - `addParticleAt(particle, index)` - `removeParticleAt(index)` 这些方法操作 `.particleChildren` 数组并正确维护内部 GPU 缓冲区。 ¥These methods operate on the `.particleChildren` array and maintain the internal GPU buffers correctly. ## **创建粒子** {#creating-a-particle} ¥**Creating a Particle** `Particle` 支持关键显示属性,并且比 `Sprite` 效率更高。 ¥A `Particle` supports key display properties, and is far more efficient than `Sprite`. ### **粒子示例** {#particle-example} ¥**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 参考** {#api-reference} ¥**API Reference** - [ParticleContainer](https://pixijs.download/release/docs/scene.ParticleContainer.html) - [粒子](https://pixijs.download/release/docs/scene.Particle.html) ¥[Particle](https://pixijs.download/release/docs/scene.Particle.html) --- ## 精灵 {#sprite} # 精灵 {#sprite} ¥Sprite 精灵是 PixiJS 中的基础视觉元素。它们代表要在屏幕上显示的单个图片。每个 [精灵](https://pixijs.download/release/docs/scene.Sprite.html) 包含一个要绘制的 [质地](https://pixijs.download/release/docs/rendering.Texture.html),以及在场景图中运行所需的所有转换和显示状态。 ¥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} ¥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; ``` ## **缩放 vs 宽度/高度** {#scale-vs-widthheight} ¥**Scale vs Width/Height** 精灵从 `Container` 继承了 `scale`,允许基于百分比调整大小: ¥Sprites inherit `scale` from `Container`, allowing for percentage-based resizing: ```ts sprite.scale.set(2); // Double the size ``` 精灵还具有 `width` 和 `height` 属性,可根据纹理尺寸方便地为 `scale` 设置大小: ¥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 参考 {#api-reference} ¥API Reference - [精灵](https://pixijs.download/release/docs/scene.Sprite.html) ¥[Sprite](https://pixijs.download/release/docs/scene.Sprite.html) - [质地](https://pixijs.download/release/docs/rendering.Texture.html) ¥[Texture](https://pixijs.download/release/docs/rendering.Texture.html) - [资源](https://pixijs.download/release/docs/assets.Assets.html) ¥[Assets](https://pixijs.download/release/docs/assets.Assets.html) --- ## 位图文本 {#bitmap-text} # 位图文本 {#bitmap-text} ¥Bitmap Text `BitmapText` 是 PixiJS 中一款高性能的文本渲染解决方案。与将每个字符串栅格化为新纹理的 `Text` 类不同,`BitmapText` 从预先生成的纹理图集中绘制字符。这种设计允许你以最小的开销渲染数以万计的文本对象。 ¥`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', }, }); ``` ## **为什么使用 `BitmapText`?** {#why-use-bitmaptext} ¥**Why Use `BitmapText`?** - ✅ 快速渲染:非常适合 HUD、计分器、计时器等。 ¥✅ **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. - ✅ 支持 MSDF/SDF 字体:清晰缩放,无模糊。 ¥✅ **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} ¥**How to Load and Use Bitmap Fonts** ### 字体加载 {#font-loading} ¥Font Loading PixiJS 支持 AngelCode BMFont 格式以及与 MSDF 兼容的 `.fnt` 和 `.xml` 文件。你可以使用 `Assets` API 加载这些文件。 ¥PixiJS supports AngelCode BMFont format and MSDF-compatible `.fnt` and `.xml` files. You can load these files using the `Assets` API. 加载完成后,你可以使用 `fontFamily` 属性创建一个包含已加载字体的 `BitmapText` 实例。 ¥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 和 SDF 字体 {#msdf-and-sdf-fonts} ¥MSDF and SDF Fonts PixiJS 支持 MSDF(多通道有符号距离场)和 SDF 格式,以实现清晰、分辨率无关的文本。这些字体在任何大小和比例下都保持清晰。 ¥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. 你可以使用 [AssetPack](https://pixijs.io/assetpack/) 等工具生成 MSDF/SDF 字体,这些工具可以接收 `.ttf` 或 `.otf` 字体并生成支持 MSDF/SDF 的位图字体图集。 ¥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. 使用 MSDF/SDF 字体与使用常规位图字体类似,只需加载相应的字体文件即可: ¥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} ¥**Limitations and Caveats** ### ❌ 无法更新分辨率 {#-cannot-update-resolution} ¥❌ Cannot Update Resolution `BitmapText.resolution` 不可变。它必须由 `BitmapFont` 处理 ¥`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} ¥⚠️ Large Character Sets Not Practical 位图字体受纹理大小限制。CJK 或富含表情符号的集合可能需要过多的内存。使用 `Text` 或 `HTMLText` 进行动态国际化或表情符号支持。 ¥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 参考** {#api-reference} ¥**API Reference** - [BitmapText](https://pixijs.download/release/docs/scene.BitmapText.html) - [BitmapFont](https://pixijs.download/release/docs/text.BitmapFont.html) - [资源](https://pixijs.download/release/docs/assets.Assets.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} ¥Text (Canvas) PixiJS 中的 `Text` 类允许你将样式化的动态字符串渲染为场景中的显示对象。在底层,PixiJS 使用浏览器的 Canvas 文本 API 对文本进行栅格化,然后将其转换为纹理。这使得 `Text` 对象的行为类似于精灵:它们可以高效地移动、旋转、缩放、遮罩和渲染。 ¥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} ¥Text Styling `TextStyle` 类允许你自定义文本的外观。你可以设置以下属性: ¥The `TextStyle` class allows you to customize the appearance of your text. You can set properties like: - `fontFamily` - `fontSize` - `fontWeight` - `fill`(颜色) ¥`fill` (color) - `align` - `stroke`(轮廓) ¥`stroke` (outline) 更多详情,请参阅 [TextStyle](./style.md) 指南。 ¥See the guide on [TextStyle](./style.md) for more details. ## **动态更改文本** {#changing-text-dynamically} ¥**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} ¥Text Resolution `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. 但是,你可以独立于渲染器设置文本分辨率,以获得更清晰的文本,尤其是在高 DPI 显示屏上。 ¥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} ¥Font Loading PixiJS 支持通过 `Assets` API 加载自定义字体。它支持多种常见的字体格式: ¥PixiJS supports loading custom fonts via the `Assets` API. It supports many of the common font formats: - `woff` - `woff2` - `ttf` - `otf` 建议使用 `woff2` 以获得最佳性能和压缩率。 ¥It is recommended to use `woff2` for the best performance and compression. ```js await Assets.load({ src: 'my-font.woff2', data: {}, }); ``` 以下是加载字体时可以传入 `data` 对象的属性列表: ¥Below is a list of properties you can pass in the `data` object when loading a font: | 属性 | 描述 | | ------------------- | -------------------------------------- | | **family** | 字体系列名称。 | | **display** | FontFace 接口的 display 属性。 | | **featureSettings** | FontFace 接口的 featureSettings 属性。 | | **stretch** | FontFace 接口的 stretch 属性。 | | **style** | FontFace 接口的 style 属性。 | | **unicodeRange** | FontFace 接口的 unicodeRange 属性。 | | **variant** | FontFace 接口的 variant 属性。 | | **weights** | FontFace 接口的 weights 属性。 | --- ## API 参考 {#api-reference} ¥API Reference - [文本](https://pixijs.download/release/docs/scene.Text.html) ¥[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 文本 {#html-text} # HTML 文本 {#html-text} ¥HTML Text `HTMLText` 允许将样式化、格式化的 HTML 字符串作为 PixiJS 场景图的一部分进行渲染。它使用 SVG `` 将浏览器原生 HTML 嵌入到你的 WebGL 画布中。 ¥`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); ``` ## **为什么使用 `HTMLText`?** {#why-use-htmltext} ¥**Why Use `HTMLText`?** - ✅ 支持内联标签,例如 `、`、`` 等。 ¥✅ Supports inline tags like `, `, ``, etc. - ✅ 兼容表情符号、Unicode 和 RTL 文本 ¥✅ Compatible with emojis, Unicode, and RTL text - ✅ 通过 CSS 进行细粒度布局控制 ¥✅ Fine-grained layout control via CSS - ✅ 基于标签的样式覆盖(`、` 等) ¥✅ Tag-based style overrides (`, `, etc.) ## **异步渲染行为** {#async-rendering-behavior} ¥**Async Rendering Behavior** HTML 文本使用 SVG `` 在画布内绘制 HTML。结果: ¥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. ## **HTML 文本样式** {#styling-htmltext} ¥**Styling HTMLText** `HTMLTextStyle` 扩展了 `TextStyle`,并添加了以下内容: ¥`HTMLTextStyle` extends `TextStyle` and adds: - 通过 `tagStyles` 实现基于 HTML 的标签样式 ¥**HTML-aware tag-based styles** via `tagStyles` - 通过 `cssOverrides` 支持 CSS 覆盖 ¥**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 覆盖** {#css-overrides} ¥**CSS Overrides** 你可以使用 `cssOverrides` 属性将 CSS 样式应用于文本。这允许你设置 `text-shadow`、`text-decoration` 等属性。 ¥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 参考** {#api-reference} ¥**API Reference** - [HTMLText](https://pixijs.download/release/docs/scene.HTMLText.html) - [HTMLTextStyle](https://pixijs.download/release/docs/text.HTMLTextStyle.html) --- ## 文本 {#text} # 文本 {#text} ¥Text 文本在游戏和应用中至关重要,PixiJS 提供了三种不同的系统来满足不同的需求: ¥Text is essential in games and applications, and PixiJS provides three different systems to cover different needs: - `Text`:高质量、样式化的光栅文本 ¥**`Text`**: High-quality, styled raster text - `BitmapText`:超快、GPU 优化的位图字体 ¥**`BitmapText`**: Ultra-fast, GPU-optimized bitmap fonts - `HTMLText`:Pixi 场景中格式丰富的 HTML ¥**`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`:带有样式的富动态文本 {#text-rich-dynamic-text-with-styles} ¥`Text`: Rich Dynamic Text with Styles `Text` 类使用浏览器的原生文本引擎进行渲染,然后将结果转换为纹理。这允许: ¥The `Text` class renders using the browser's native text engine, and then converts the result into a texture. This allows for: - 完全类似 CSS 的字体控制 ¥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`:高性能字形渲染 {#bitmaptext-high-performance-glyph-rendering} ¥`BitmapText`: High-Performance Glyph Rendering `BitmapText` 使用预先烘焙的位图字体图片作为字形,完全绕过字体光栅化。这给出了: ¥`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 要使用 `BitmapText`,你必须首先通过以下方式注册位图字体: ¥To use `BitmapText`, you must first register a bitmap font via: - `BitmapFont.from(...)` 可即时创建,或者 ¥`BitmapFont.from(...)` to create on the fly, or - 如果使用第三方 BMFont 或 AngelCode 导出,则使用 `Assets.load(...)` ¥`Assets.load(...)` if using a 3rd-party BMFont or AngelCode export --- ## `HTMLText`:场景内 HTML 样式 {#htmltext-styled-html-inside-the-scene} ¥`HTMLText`: Styled HTML Inside the Scene `HTMLText` 允许你在 PixiJS 场景中渲染真实的 HTML 标记。这允许: ¥`HTMLText` lets you render actual HTML markup in your PixiJS scene. This allows: - `、`、`` 样式格式 ¥`, `, `` style formatting - 精细布局和文本流 ¥Fine layout and text flow - 表情符号、RTL、链接等 ¥Emoji, RTL, links, and more 在以下情况下使用: ¥**Use it when**: - 你需要复杂的 HTML 样式标记 ¥You want complex HTML-style markup - 静态或半动态内容 ¥Static or semi-dynamic content - 你的用户期望 "document-like" 布局 ¥Your users expect "document-like" layout 避免以下情况: ¥**Avoid when**: - 你需要像素级完美性能 ¥You need pixel-perfect performance - 你正在渲染数百个文本块 ¥You're rendering hundreds of text blocks - 你需要 GPU 文本效果 ¥You need GPU text effects ## 后续步骤 {#next-steps} ¥Next Steps 每种文本类型都有相应的指南,其中详细介绍了设置、字体加载、样式选项和限制: ¥Each text type has a corresponding guide that covers setup, font loading, style options, and limitations in more detail: - [文本指南 →](./canvas.md) ¥[Text Guide →](./canvas.md) - [位图文本指南 →](./bitmap.md) ¥[BitmapText Guide →](./bitmap.md) - [HTML 文本指南 →](./html.md) ¥[HTMLText Guide →](./html.md) --- ## API 参考 {#api-reference} ¥API Reference - [文本](https://pixijs.download/release/docs/scene.Text.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) - [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) --- ## SplitText 和 SplitBitmapText # SplitText 和 SplitBitmapText {#splittext--splitbitmaptext} ¥SplitText & SplitBitmapText `SplitText` 和 `SplitBitmapText` 类允许你将字符串拆分为单独的行、单词和字符(每个都是独立的显示对象),从而解锁丰富的逐段动画和高级文本布局效果。 ¥The `SplitText` and `SplitBitmapText` classes let you break a string into individual lines, words, and characters—each as its own display object—unlocking rich, per-segment animations and advanced text layout effects. 这些类的工作方式与常规 `Text` 或 `BitmapText` 相同,但可以对文本的每个部分进行细粒度的控制。 ¥These classes work just like regular `Text` or `BitmapText`, but provide fine-grained control over every part of your text. :::warning 警告 实验性:这些功能是新功能,可能会在未来版本中改进。 ¥**Experimental:** These features are new and may evolve in future versions. ::: --- ## 什么是 SplitText 和 SplitBitmapText? {#what-are-splittext--splitbitmaptext} ¥What Are SplitText & SplitBitmapText? `SplitText` 和 `SplitBitmapText` 均扩展了 PixiJS 容器,为字符串的每一行、每个单词和每个字符生成嵌套的显示对象。 ¥Both `SplitText` and `SplitBitmapText` extend PixiJS containers, generating nested display objects for each line, word, and character of your string. 区别在于底层文本渲染: ¥The difference is in the underlying text rendering: | 类 | 基本类型 | 最适合 | | ----------------- | ------------ | -------------- | | `SplitText` | `Text` | 样式丰富的文本 | | `SplitBitmapText` | `BitmapText` | 高性能动态文本 | **适合:** ¥**Perfect for:** - 逐字符或逐词动画 ¥Per-character or per-word animations - 基于行的入口或出口效果 ¥Line-based entrance or exit effects - 交互式文本元素 ¥Interactive text elements - 复杂的动画排版 ¥Complex animated typography --- ## 基本用法 {#basic-usage} ¥Basic Usage ### SplitText 示例 {#splittext-example} ¥SplitText Example ```ts import { SplitText } from 'pixi.js'; const text = new SplitText({ text: 'Hello World', style: { fontSize: 32, fill: 0xffffff }, // Optional: Anchor points (0-1 range) lineAnchor: 0.5, // Center lines wordAnchor: { x: 0, y: 0.5 }, // Left-center words charAnchor: { x: 0.5, y: 1 }, // Bottom-center characters autoSplit: true, }); app.stage.addChild(text); ``` ### SplitBitmapText 示例 {#splitbitmaptext-example} ¥SplitBitmapText Example ```ts import { SplitBitmapText, BitmapFont } from 'pixi.js'; // Ensure your bitmap font is installed BitmapFont.install({ name: 'Game Font', style: { fontFamily: 'Arial', fontSize: 32 }, }); const text = new SplitBitmapText({ text: 'High Performance', style: { fontFamily: 'Game Font', fontSize: 32 }, autoSplit: true, }); app.stage.addChild(text); ``` --- ## 访问片段 {#accessing-segments} ¥Accessing Segments 这两个类都提供了便捷的片段数组: ¥Both classes provide convenient segment arrays: ```ts console.log(text.lines); // Array of line containers console.log(text.words); // Array of word containers console.log(text.chars); // Array of character display objects ``` 每一行都包含一个单词,每个单词都包含一个字符。 ¥Each line contains its words, and each word contains its characters. --- ## 锚点说明 {#anchor-points-explained} ¥Anchor Points Explained 分段锚点控制旋转或缩放等变换的原点。 ¥Segment anchors control the origin for transformations like rotation or scaling. 标准化范围:`0`(起始)至 `1`(结束) ¥Normalized range: `0` (start) to `1` (end) | 锚点 | 含义 | | --------- | ------ | | `0,0` | 左上角 | | `0.5,0.5` | 居中 | | `1,1` | 右下角 | **示例:** ¥**Example:** ```ts const text = new SplitText({ text: 'Animate Me', lineAnchor: { x: 1, y: 0 }, // Top-right lines wordAnchor: 0.5, // Center words charAnchor: { x: 0, y: 1 }, // Bottom-left characters }); ``` --- ## 动画示例(使用 GSAP) {#animation-example-with-gsap} ¥Animation Example (with GSAP) ```ts import { gsap } from 'gsap'; const text = new SplitBitmapText({ text: 'Split and Animate', style: { fontFamily: 'Game Font', fontSize: 48 }, }); app.stage.addChild(text); // Animate characters one by one text.chars.forEach((char, i) => { gsap.from(char, { alpha: 0, delay: i * 0.05, }); }); // Animate words with scaling text.words.forEach((word, i) => { gsap.to(word.scale, { x: 1.2, y: 1.2, yoyo: true, repeat: -1, delay: i * 0.2, }); }); ``` --- ## 基于现有文本创建 {#creating-from-existing-text} ¥Creating from Existing Text 将现有文本对象转换为分段版本: ¥Convert existing text objects into segmented versions: ```ts import { Text, SplitText, BitmapText, SplitBitmapText } from 'pixi.js'; const basicText = new Text({ text: 'Standard Text', style: { fontSize: 32 }, }); const splitText = SplitText.from(basicText); const bitmapText = new BitmapText({ text: 'Bitmap Example', style: { fontFamily: 'Game Font', fontSize: 32 }, }); const splitBitmap = SplitBitmapText.from(bitmapText); ``` --- ## 配置选项 {#configuration-options} ¥Configuration Options 两个类的共享选项: ¥Shared options for both classes: | 选项 | 描述 | 默认 | | ------------ | ------------------------------------ | ------ | | `text` | 要渲染和拆分的字符串内容 | 必需 | | `style` | 文本样式配置(因文本类型而异) | `{}` | | `autoSplit` | 文本或样式更改时自动更新片段 | `true` | | `lineAnchor` | 行容器锚点(`number` 或 `{x, y}`) | `0` | | `wordAnchor` | 单词容器锚点(`number` 或 `{x, y}`) | `0` | | `charAnchor` | 字符对象锚点(`number` 或 `{x, y}`) | `0` | --- ## 全局默认值 {#global-defaults} ¥Global Defaults 更改每个类的全局默认值: ¥Change global defaults for each class: ```ts SplitText.defaultOptions = { lineAnchor: 0.5, wordAnchor: { x: 0, y: 0.5 }, charAnchor: { x: 0.5, y: 1 }, }; SplitBitmapText.defaultOptions = { autoSplit: false, }; ``` --- ## 限制 {#limitations} ¥Limitations ⚠️ 字符间距:将文本拆分为单个对象会移除浏览器或字体字距调整。与标准 `Text` 相比,间距可能会略有不同。 ¥⚠️ **Character Spacing:** Splitting text into individual objects removes browser or font kerning. Expect slight differences in spacing compared to standard `Text`. --- ## 性能说明 {#performance-notes} ¥Performance Notes 拆分文本会创建额外的显示对象。对于简单的静态文本,常规 `Text` 对象效率更高。在你需要时使用 `SplitText`: ¥Splitting text creates additional display objects. For simple static text, a regular `Text` object is more efficient. Use `SplitText` when you need: - 逐句段动画 ¥Per-segment animations - 交互式或响应式文本效果 ¥Interactive or responsive text effects - 复杂的布局 ¥Complex layouts [此处](./index.md) 中概述的相同性能限制也适用于这些类。 ¥The same performance limitations outlined [here](./index.md) apply for these classes as well. --- ## API 参考 {#api-reference} ¥API Reference - [文本](https://pixijs.download/release/docs/scene.Text.html) ¥[Text](https://pixijs.download/release/docs/scene.Text.html) - [TextStyle](https://pixijs.download/release/docs/text.TextStyle.html) - [BitmapFont](https://pixijs.download/release/docs/text.BitmapFont.html) - [SplitText](https://pixijs.download/release/docs/text.SplitText.html) - [SplitBitmapText](https://pixijs.download/release/docs/text.SplitBitmapText.html) --- ## 文本样式 {#text-style} # 文本样式 {#text-style} ¥Text Style `TextStyle` 类封装了文本的所有视觉样式属性。你可以定义颜色、字体系列、描边、阴影、对齐方式、行距、自动换行等等。 ¥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. `TextStyle` 实例可以在多个 `Text` 对象之间复用,从而使代码更简洁,并提高内存效率。 ¥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} ¥Fill and Stroke 填充和描边的使用与 `Graphics` 类相同。你可以在 [图形填充](../graphics/graphics-fill.md) 部分找到更多详细信息。 ¥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://pixi.nodejs.cn/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} ¥Drop Shadow 在 v8 中,`dropShadow` 及其属性现在是对象。要更新阴影,你可以直接在 `dropShadow` 对象上设置属性。 ¥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 参考** {#api-reference} ¥**API Reference** - [TextStyle](https://pixijs.download/release/docs/text.TextStyle.html) - [文本](https://pixijs.download/release/docs/scene.Text.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} ¥Tiling Sprite `TilingSprite` 是一种高性能方法,用于在矩形区域内渲染重复纹理。它不会拉伸纹理,而是重复(平铺)纹理以填充给定空间,这使其成为背景、视差效果、地形和 UI 面板的理想选择。 ¥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); ``` ## 什么是 TilingSprite? {#what-is-a-tilingsprite} ¥What is a TilingSprite? - 它在定义的区域内重复绘制纹理。 ¥It draws a texture repeatedly across a defined area. - 除非你调整 `tileScale`,否则纹理默认不会缩放。 ¥The texture is not scaled by default unless you adjust `tileScale`. - 精灵的整体 `width` 和 `height` 决定了图块填充的区域大小,与纹理的原始大小无关。 ¥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} ¥Key Properties | 属性 | 描述 | | ---------------------- | ----------------------------------------------- | | `texture` | 正在重复的纹理 | | `tilePosition` | `ObservablePoint` 控制平铺图案的偏移量 | | `tileScale` | `ObservablePoint` 控制每个平铺图的缩放比例 | | `tileRotation` | 控制图块图案旋转的数字 | | `width` / `height` | 图块填充区域的大小 | | `anchor` | 调整 TilingSprite 的原点 | | `applyAnchorToTexture` | 如果 `true` 为 ,则锚点会影响平铺图案的起始点。 | | `clampMargin` | 调整边距以避免边缘伪影(默认值:`0.5`) | ### 宽度和高度 vs 缩放比例 {#width--height-vs-scale} ¥Width & Height vs Scale 与 `Sprite` 不同,在 `TilingSprite` 中设置 `width` 和 `height` 会直接更改可见的平铺区域。它不会影响图块的比例。 ¥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 ``` 要缩放图块图案本身,请使用 `tileScale`: ¥To scale the tile pattern itself, use `tileScale`: ```ts // Makes each tile appear larger tilingSprite.tileScale.set(2, 2); ``` ### 锚点和 applyAnchorToTexture {#anchor-and-applyanchortotexture} ¥Anchor and applyAnchorToTexture - `anchor` 设置用于定位 TilingSprite 的枢轴/原点。 ¥`anchor` sets the pivot/origin point for positioning the TilingSprite. - 如果 `applyAnchorToTexture` 为 `true`,则锚点还会影响平铺图案的起始位置。 ¥If `applyAnchorToTexture` is `true`, the anchor also affects where the tile pattern begins. - 默认情况下,无论锚点如何,图块图案都从本地空间的 (0, 0) 处开始。 ¥By default, the tile pattern starts at (0, 0) in local space regardless of anchor. --- ## API 参考 {#api-reference} ¥API Reference - [TilingSprite](https://pixijs.download/release/docs/scene.TilingSprite.html) - [质地](https://pixijs.download/release/docs/rendering.Texture.html) ¥[Texture](https://pixijs.download/release/docs/rendering.Texture.html) --- ## LLM 文档 {#documentation-for-llms} # LLM 文档 {#documentation-for-llms} ¥Documentation for LLMs PixiJS 支持 [`llms.txt`](https://llmstxt.org/) 约定,使文档可供大型语言模型 (LLM) 及其使用的应用访问。 ¥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} ¥Available Files 我们提供多个不同压缩级别的文档文件,以适应各种上下文窗口大小: ¥We provide several documentation files at different compression levels to accommodate various context window sizes: - [`/llms.txt`](https://pixi.nodejs.cn/llms.txt) - 可用文档文件索引 ¥[`/llms.txt`](https://pixi.nodejs.cn/llms.txt) - An index of available documentation files - [`/llms-full.txt`](https://pixi.nodejs.cn/llms-full.txt) - 完整的 PixiJS API 文档,包含所有类、方法和示例 ¥[`/llms-full.txt`](https://pixi.nodejs.cn/llms-full.txt) - Complete PixiJS API documentation including all classes, methods, and examples - [`/llms-medium.txt`](https://pixi.nodejs.cn/llms-medium.txt) - 针对中等上下文窗口优化的压缩文档 ¥[`/llms-medium.txt`](https://pixi.nodejs.cn/llms-medium.txt) - Compressed documentation optimized for medium context windows 这些文件每天从我们的 TypeScript 定义文件和文档源自动生成和更新。 ¥These files are automatically generated and updated daily from our TypeScript definition files and documentation sources. --- ## 赞助 PixiJS {#sponsor-pixijs} # 赞助 PixiJS {#sponsor-pixijs} ¥Sponsor PixiJS PixiJS 是一个采用 MIT 许可的开源项目,完全免费使用。它受到全球公司和开发者的信赖,为 Web 上的高性能图形提供支持。维护项目、改进功能集以及支持其不断增长的生态系统所需的巨大努力,只有通过我们赞助商的资金支持才能实现。 ¥PixiJS is an MIT-licensed open source project and completely free to use. It's trusted by companies and developers around the world to power high-performance graphics on the web. The enormous effort required to maintain the project, evolve its feature set, and support its growing ecosystem is only made possible through the financial support of our sponsors. --- ## 如何赞助 {#how-to-sponsor} ¥How to Sponsor 你可以通过 [GitHub 赞助商](https://github.com/sponsors/pixijs) 或 [OpenCollective](https://opencollective.com/pixijs) 赞助 PixiJS。欢迎一次性或每月定期捐款。定期赞助的赞助商将根据其 [赞助等级](#sponsorship-tiers) 获得徽标展示和其他福利。 ¥You can sponsor PixiJS through [GitHub Sponsors](https://github.com/sponsors/pixijs) or [OpenCollective](https://opencollective.com/pixijs). Both one-time and monthly recurring contributions are welcome. Sponsors with recurring support are eligible for logo placements and other benefits based on their [sponsorship tier](#sponsorship-tiers). --- ## 企业赞助 PixiJS {#sponsoring-pixijs-as-a-business} ¥Sponsoring PixiJS as a Business 支持 PixiJS 不仅对开源有益,而且对商业发展也有好处。无论你是开发游戏、创意工具还是数据可视化,赞助 PixiJS 都能为你提供: ¥Supporting PixiJS isn’t just good for open source—it’s good business. Whether you're building games, creative tools, or data visualizations, sponsoring PixiJS gives you: - 在我们的网站、文档、展示和发布帖子中提高可见度和品牌认知度。 ¥**Visibility and brand recognition** across our website, documentation, showcase, and release posts. - 直接投资于你所依赖的工具,帮助确保持续更新以及健康、维护良好的代码库。 ¥**Direct investment in the tools you rely on**, helping ensure continued updates and a healthy, well-maintained codebase. - 通过支持对你的产品最重要的功能和改进来帮助制定路线图。 ¥**Help shape the roadmap** by supporting the features and improvements that matter most to your product. 赞助也是吸引开发者人才的绝佳方式。通过为社区驱动的项目做出贡献,你的品牌展现了对高质量工程和开放协作的承诺。 ¥Sponsorship is also an excellent way to attract developer talent. By contributing to a community-driven project, your brand demonstrates a commitment to quality engineering and open collaboration. 如果你的产品或服务依赖于 PixiJS,赞助有助于确保其长期稳定性,并让你在功能和修复的优先级排序方面拥有发言权。 ¥If your product or service depends on PixiJS, sponsoring helps ensure its long-term stability—and gives you a voice in prioritizing features and fixes. --- ## 个人赞助 PixiJS {#sponsoring-pixijs-as-an-individual} ¥Sponsoring PixiJS as an Individual 如果你在个人项目中使用 PixiJS 感到愉快,请考虑捐赠以回馈社区。即使是小额的贡献也能有所帮助,并且是有意义的支持标志! ¥If you’ve enjoyed using PixiJS in your personal projects, consider donating as a way to give back. Even small contributions help and are a meaningful sign of support! 更好的是,鼓励你的雇主成为我们的商业赞助商。这具有更大的影响力,并有助于确保 PixiJS 继续以惠及所有人的方式发展。 ¥Even better, encourage your employer to become a business sponsor. This has a far greater impact and helps ensure PixiJS continues to grow in ways that benefit everyone. --- ## 赞助等级 {#sponsorship-tiers} ¥Sponsorship Tiers 我们提供分级赞助,为合作伙伴提供宝贵的曝光度和收益,以回报他们的支持: ¥We offer tiered sponsorships to give our partners valuable exposure and benefits in return for their support: | 等级 | 每月 | 优势 | | ------------ | ----- | ----------------------------------------------------------------------------------------------------------------------------- | | **青铜级** | $100 | 在我们的网站上放置徽标并链接到你的网站 | | **白银级** | $250 | 铜牌会员权益 在我们的 [发布博客文章](https://pixi.nodejs.cn/blog/8.10.0) 中展示徽标 展示区中 1 个赞助链接(始终显示在顶部!) | | **黄金级** | $500 | 银级福利 徽标显示在我们网站侧边栏的所有文档页面上 徽标显示在 GitHub README 中 | | **黄金++级** | $1000 | 黄金级优势 展示区中 2 个赞助商链接(始终显示在顶部!) 优先修复错误 | | **白金级** | $2000 | 黄金++级优势 在我们网站上最显眼的徽标位置 最高优先级修复错误 帮助我们制定下一步的工作! | # 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, 1); // Inside * const centerStroke = rect.strokeContains(150, 100, 4, 0.5); // Centered * const outerStroke = rect.strokeContains(150, 100, 4, 0); // 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 (1 = inner, 0.5 = centered, 0 = 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 { } 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; originX: number; originY: 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 origin point around which the container rotates and scales. * Unlike pivot, changing origin will not move the container's position. * @example * ```ts * new Container({ origin: new Point(100, 100) }); // Rotate around point (100,100) * new Container({ origin: 50 }); // Rotate around point (50, 50) * new Container({ origin: { x: 150, y: 150 } }); // Rotate around point (150, 150) * ``` */ origin?: 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: * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
PropertyDescription
[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 * * // Rotate around center with origin * container.origin.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 * * // Rotate around center with origin * sprite.origin.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 | string); /** * @experimental * The origin point around which the container rotates and scales without affecting its position. * Unlike pivot, changing the origin will not move the container's position. * @example * ```ts * // Rotate around center point * container.origin.set(container.width / 2, container.height / 2); * container.rotation = Math.PI; // Rotates around center * * // Reset origin * container.origin.set(0, 0); * ``` */ get origin(): ObservablePoint; set origin(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 `