关于 pixijs-rendering
面向 PixiJS 8.21 开发者的渲染技能,涵盖异步应用初始化、资源加载、场景图、动画循环和指针交互,并说明 v8 API 的用法。
主要功能
- 01异步初始化 Application
- 02使用 Assets 加载资源
- 03组织 Container 场景图
- 04通过 ticker 驱动动画
- 05配置指针事件与渲染组
适用场景
- 01启动 PixiJS v8 应用并显示画布
- 02加载纹理并构建场景对象
- 03实现帧率无关的动画
- 04处理鼠标、触控或拖动交互
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ gamedev-skills/ awesome-gamedev-agent-skills --skill pixijs-rendering安装后在 Claude Code 中输入/pixijs-rendering确认已加载。
附带文件references/assets-and-display.md
详细介绍
PixiJS 8.21 渲染
搭建并组织 PixiJS 8.21 应用:异步 Application、通过 Assets 加载资源、Container/Sprite 场景图、ticker 循环、指针事件和渲染组。固定使用 8.21 API(异步 init、统一的 Assets、eventMode)。
适用场景
- 开始开发 PixiJS v8 项目、修复空白画布、组织显示列表、加载纹理、使用 ticker 制作动画或处理指针输入时使用。
- 当
package.json依赖pixi.js(v8),且代码使用import { Application } from 'pixi.js'时使用。
不适用场景: Phaser 的场景/加载器模型 → phaser-core。3D 场景 → threejs-scene-setup。PixiJS v7 及更早版本的代码(同步 new Application({...})、Loader、beginFill/endFill)需要先迁移到 v8;本技能仅针对 v8。(v8 中 interactive = true 仍可作为 eventMode = 'static' 的别名使用,但建议显式设置 eventMode。)
核心工作流
- 创建并
awaitApplication。 在 v8 中,new Application()是空实例;需要通过await app.init({...})完成配置。将app.canvas(而非app.view)添加到 DOM。使用打包工具时,请将顶层await放入异步函数中。 - 使用
Assets加载资源。await Assets.load(url)会返回一个Texture。要加载多个资源,请注册清单/资源包并按名称加载。v7 的Loader已不存在。 - 构建场景图。 所有内容都从
app.stage(一个Container)向下派生。将相关对象分组到Container中;子对象的变换相对于父对象。绘制顺序 = 插入顺序(后插入的显示在上层)。 - 使用 ticker 制作动画。
app.ticker.add((ticker) => {...})。通过ticker.deltaTime(帧数,在 60fps 下约为 1)或ticker.deltaMS(毫秒)缩放运动,从而使速度不受帧率影响。 - 为对象启用事件,方法是设置
eventMode = 'static'(或'dynamic'),然后调用obj.on('pointerdown', ...)。联合指针事件支持鼠标、触摸和触控笔。 - 将较大的静态子树提升为渲染组(
isRenderGroup: true),以便 GPU 缓存其变换。前后进行性能分析;确认屏幕上的像素显示正常。
常用模式
1. 异步启动 Application(v8 入口点)
import { Application, Assets, Sprite } from 'pixi.js';
(async () => {
// v8: construct empty, then await init(). Config does NOT go in the constructor.
const app = new Application();
await app.init({
background: '#1099bb',
resizeTo: window, // track the window size
antialias: true,
// preference: 'webgpu', // hint only; default order tries 'webgl' first.
// // Pixi falls back if the backend is unavailable —
// // branch on app.renderer.name, don't assume it took.
});
document.body.appendChild(app.canvas); // v8 uses app.canvas, not app.view
const texture = await Assets.load('https://pixijs.com/assets/bunny.png');
const bunny = new Sprite(texture);
bunny.anchor.set(0.5);
bunny.position.set(app.screen.width / 2, app.screen.height / 2);
app.stage.addChild(bunny);
})();
2. 使用 Container 构建相对变换场景图
import { Container, Sprite } from 'pixi.js';
const world = new Container();
app.stage.addChild(world);
// Children are positioned relative to `world`; move/scale/rotate the whole group
// by transforming the parent.
for (let i = 0; i < 10; i++) {
const coin = new Sprite(coinTexture);
coin.x = i * 40;
world.addChild(coin);
}
world.position.set(100, 100);
world.scale.set(2); // every coin scales with the container
3. Ticker 循环(帧率无关)
let elapsed = 0;
app.ticker.add((ticker) => {
// deltaTime ≈ 1 at 60fps; deltaMS is milliseconds since last frame.
elapsed += ticker.deltaMS;
bunny.rotation += 0.05 * ticker.deltaTime; // smooth at any frame rate
bunny.y = app.screen.height / 2 + Math.sin(elapsed / 500) * 50;
});
4. 指针事件(联合事件)
bunny.eventMode = 'static'; // 'static' = interactive, doesn't move on its own
bunny.cursor = 'pointer'; // hover cursor; `buttonMode` was removed in v8
bunny.on('pointerdown', (event) => {
bunny.tint = 0xff0000;
// event.global is the pointer position in stage space.
});
bunny.on('pointerover', () => bunny.scale.set(1.1));
bunny.on('pointerout', () => bunny.scale.set(1.0));
拖动需要使用 globalpointermove,而不是 pointermove。在 v8 中,pointermove 仅在指针位于对象上方时触发,因此拖动时如果指针移出对象边缘,更新就会停止。globalpointermove 会在每次移动时触发:
let dragging = false;
bunny.on('pointerdown', () => { dragging = true; });
bunny.on('pointerup', () => { dragging = false; });
bunny.on('pointerupoutside', () => { dragging = false; }); // release off the object
bunny.on('globalpointermove', (event) => {
if (dragging) bunny.position.copyFrom(event.global);
});
5. 按名称加载多个资源(资源包)
import { Assets } from 'pixi.js';
await Assets.init({
manifest: {
bundles: [{
name: 'level-1',
assets: [
{ alias: 'hero', src: 'assets/hero.png' },
{ alias: 'tiles', src: 'assets/tiles.png' },
],
}],
},
});
const bundle = await Assets.loadBundle('level-1'); // { hero: Texture, tiles: Texture }
const hero = new Sprite(bundle.hero);
6. 为大型静态图层使用渲染组
// A big, rarely-changing background subtree: let the GPU cache its transforms.
const background = new Container({ isRenderGroup: true });
app.stage.addChild(background);
// Add hundreds of static tiles to `background`. Moving `background` itself stays
// cheap; constantly re-adding/removing children negates the benefit.
常见问题
- 画布为空 / “app.stage is undefined” → 你没有
await app.init(),或者在构造函数中进行了配置。在 v8 中,构造函数为空;所有选项都应传给init()。在init()Promise 兑现之前,app.renderer/app.canvas/app.screen都是undefined。 app.viewis undefined → v8 将其重命名为app.canvas。- 迁移 v7 代码 →
Loader/loader.add→Assets.load(Loader类已移除);同步的new Application({...})→ 空构造函数 + 异步init()(构造函数中的选项会被忽略,并显示弃用警告,但不会报错);beginFill()/endFill()→ 先定义形状,再调用.rect(...).fill(...)。interactive = true和app.view仍可作为已弃用的别名使用。 - Ticker 回调参数是 Ticker,而不是 delta 数值 →
app.ticker.add((dt) => { obj.rotation += dt; })可以通过编译,但dt是整个Ticker对象,因此计算结果为NaN,不会产生动画。应从参数中读取ticker.deltaTime。 - 顶层 await 导致构建错误(Vite ≤6.0.6) → 用
(async () => { ... })()包装启动代码。 - 速度会随帧率变化 → 将移动量乘以
ticker.deltaTime(在 60fps 时约为 1),或按ticker.deltaMS缩放;不要假定帧率为 60fps。deltaTime是无量纲乘数,不是毫秒。 - 点击没有反应 → 对象的
eventMode仍为'passive'(v8 的默认值:对象本身不可交互,但子对象仍可交互);将其设为'static'(对于在静止光标下移动的对象,则设为'dynamic')。 - 拖动在对象边缘处停止 → 在 v8 中,只有指针位于对象上时才会触发
pointermove;拖动或全局跟踪请使用globalpointermove。 Texture.from(url)返回空白或未定义的纹理 → 在 v8 中,它只会读取 Assets 缓存;请先执行await Assets.load(url),然后使用返回的Texture。- WebGPU 功能报错 →
preference只是提示。如果后端不可用,Pixi 会回退(先尝试 WebGL,再尝试 Canvas);使用特定后端的代码前,请根据app.renderer.name进行分支处理。 - 像素艺术的纹理看起来模糊 → 设置
texture.source.scaleMode = 'nearest'(或在加载时传入此选项)。 - 内存持续增长 →
removeChild不会释放 GPU 内存;对于不再需要的资源,请调用sprite.destroy()和Assets.unload(url)。 - 在同一标签页中销毁并重新创建应用后出现闪烁或损坏 → 使用
app.destroy({ releaseGlobalResources: true })销毁;否则,旧应用中池化的批次和纹理会泄漏到新应用中。
参考资料
- 关于纹理/资源管线(精灵表/图集、
Assets.add、后台加载、卸载),以及 Graphics/Text/TilingSprite/ParticleContainer和滤镜,请阅读references/assets-and-display.md。
相关技能
phaser-core— 功能齐全的 2D 框架(场景、物理、输入)。threejs-scene-setup— 使用 three.js 在浏览器中构建 3D 场景。prototype-fast— 快速构建可玩的灰盒原型(经常引用 PixiJS)。
评论
支持 Markdown