PixiJS 基础概念 #
核心架构概览 #
PixiJS 的架构设计清晰,核心组件各司其职:
text
┌─────────────────────────────────────────────────────────────┐
│ PixiJS 核心架构 │
├─────────────────────────────────────────────────────────────┤
│ │
│ Application(应用) │
│ │ │
│ ├── Renderer(渲染器) │
│ │ │ │
│ │ ├── WebGL Renderer │
│ │ └── Canvas Renderer │
│ │ │
│ ├── Stage(舞台) │
│ │ │ │
│ │ └── Container(容器) │
│ │ │ │
│ │ ├── Sprite(精灵) │
│ │ ├── Graphics(图形) │
│ │ ├── Text(文本) │
│ │ └── ... │
│ │ │
│ └── Ticker(计时器) │
│ │
└─────────────────────────────────────────────────────────────┘
Application(应用) #
Application 是 PixiJS 应用的入口点,它整合了渲染器、舞台和计时器。
创建应用 #
javascript
import { Application } from 'pixi.js';
const app = new Application();
await app.init({
width: 800,
height: 600,
backgroundColor: 0x1099bb
});
document.body.appendChild(app.canvas);
Application 属性 #
javascript
// 渲染器
app.renderer;
// 舞台(根容器)
app.stage;
// 画布元素
app.canvas;
// 屏幕尺寸
app.screen;
// 计时器
app.ticker;
// 配置选项
app.config;
Application 方法 #
javascript
// 渀染一帧
app.render();
// 销毁应用
app.destroy(removeView, options);
// 调整大小
app.renderer.resize(1024, 768);
完整示例 #
javascript
import { Application, Text } from 'pixi.js';
async function createApp() {
const app = new Application();
await app.init({
width: 800,
height: 600,
backgroundColor: 0x1099bb,
antialias: true,
resolution: window.devicePixelRatio || 1,
autoDensity: true
});
document.body.appendChild(app.canvas);
return app;
}
const app = await createApp();
console.log('渲染器类型:', app.renderer.type);
console.log('屏幕宽度:', app.screen.width);
console.log('屏幕高度:', app.screen.height);
Renderer(渲染器) #
渲染器负责将显示对象绘制到画布上。
渲染器类型 #
text
┌─────────────────────────────────────────────────────────────┐
│ 渲染器类型 │
├─────────────────────────────────────────────────────────────┤
│ │
│ WebGL Renderer │
│ ├── GPU 加速渲染 │
│ ├── 支持滤镜 │
│ ├── 支持混合模式 │
│ └── 高性能批处理 │
│ │
│ Canvas Renderer │
│ ├── CPU 渲染 │
│ ├── 兼容性好 │
│ ├── 不支持某些滤镜 │
│ └── 性能较低 │
│ │
└─────────────────────────────────────────────────────────────┘
渲染器配置 #
javascript
await app.init({
width: 800,
height: 600,
// 渲染器偏好
preference: 'webgl2', // 'webgl2', 'webgl1', 'canvas'
// 抗锯齿
antialias: true,
// 分辨率
resolution: 2,
// 电源偏好
powerPreference: 'high-performance'
});
渲染器属性 #
javascript
// 渲染器类型
app.renderer.type; // 'WEBGL' 或 'CANVAS'
// 渲染器宽度
app.renderer.width;
// 渲染器高度
app.renderer.height;
// 分辨率
app.renderer.resolution;
// 屏幕矩形
app.renderer.screen;
// 背景
app.renderer.background;
手动渲染 #
javascript
// 关闭自动渲染
await app.init({
width: 800,
height: 600,
autoStart: false
});
// 手动触发渲染
function gameLoop() {
update();
app.render();
requestAnimationFrame(gameLoop);
}
gameLoop();
Stage(舞台) #
Stage 是显示对象树的根节点,所有可见对象都必须添加到舞台或其子容器中。
Stage 结构 #
text
┌─────────────────────────────────────────────────────────────┐
│ Stage 结构 │
├─────────────────────────────────────────────────────────────┤
│ │
│ Stage (根容器) │
│ │ │
│ ├── Container (UI层) │
│ │ │ │
│ │ ├── Text │
│ │ └── Graphics │
│ │ │
│ ├── Container (游戏层) │
│ │ │ │
│ │ ├── Sprite (玩家) │
│ │ ├── Sprite (敌人) │
│ │ └── Container (粒子系统) │
│ │ │
│ └── Container (背景层) │
│ │ │
│ └── TilingSprite │
│ │
└─────────────────────────────────────────────────────────────┘
操作 Stage #
javascript
// 添加子对象
app.stage.addChild(sprite);
// 移除子对象
app.stage.removeChild(sprite);
// 移除所有子对象
app.stage.removeChildren();
// 按索引操作
app.stage.addChildAt(sprite, 0);
app.stage.removeChildAt(0);
app.stage.setChildIndex(sprite, 2);
// 查找子对象
app.stage.getChildIndex(sprite);
app.stage.getChildAt(0);
Container(容器) #
Container 是用于组织显示对象的容器,可以包含其他显示对象。
创建容器 #
javascript
import { Container } from 'pixi.js';
const container = new Container();
container.x = 100;
container.y = 100;
app.stage.addChild(container);
容器特性 #
text
┌─────────────────────────────────────────────────────────────┐
│ Container 特性 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. 变换继承 │
│ 子对象继承父容器的变换 │
│ │
│ 2. 可见性控制 │
│ 父容器隐藏时,子对象也隐藏 │
│ │
│ 3. 透明度继承 │
│ 子对象透明度与父容器相乘 │
│ │
│ 4. 层级管理 │
│ 子对象按添加顺序渲染 │
│ │
│ 5. 事件冒泡 │
│ 事件可以在容器间冒泡 │
│ │
└─────────────────────────────────────────────────────────────┘
变换继承示例 #
javascript
const parent = new Container();
parent.x = 100;
parent.y = 100;
parent.rotation = Math.PI / 4;
parent.scale.set(2, 2);
const child = new Graphics();
child.circle(0, 0, 25);
child.fill({ color: 0xff0000 });
parent.addChild(child);
app.stage.addChild(parent);
// 子对象实际位置:(100, 100)
// 子对象实际旋转:45度
// 子对象实际缩放:2倍
容器操作 #
javascript
const container = new Container();
// 添加多个子对象
container.addChild(sprite1, sprite2, sprite3);
// 遍历子对象
container.children.forEach(child => {
console.log(child);
});
// 排序(按 y 坐标)
container.children.sort((a, b) => a.y - b.y);
// 按名称查找
const found = container.getChildByName('player');
// 交换子对象顺序
container.swapChildren(sprite1, sprite2);
实用容器模式 #
javascript
// 分层容器
class LayeredStage {
constructor(app) {
this.background = new Container();
this.game = new Container();
this.ui = new Container();
app.stage.addChild(
this.background,
this.game,
this.ui
);
}
}
// 视差容器
class ParallaxLayer extends Container {
constructor(speed) {
super();
this.speed = speed;
}
update(cameraX) {
this.x = -cameraX * this.speed;
}
}
DisplayObject(显示对象) #
DisplayObject 是所有可见对象的基类。
显示对象属性 #
javascript
const sprite = PIXI.Sprite.from('player.png');
// 位置
sprite.x = 100;
sprite.y = 100;
sprite.position.set(100, 100);
// 锚点(0-1)
sprite.anchor.set(0.5, 0.5);
// 原点(像素)
sprite.pivot.set(50, 50);
// 缩放
sprite.scale.x = 2;
sprite.scale.y = 2;
sprite.scale.set(2, 2);
// 旋转(弧度)
sprite.rotation = Math.PI / 4;
// 倾斜
sprite.skew.set(0.1, 0);
// 透明度(0-1)
sprite.alpha = 0.5;
// 可见性
sprite.visible = true;
// 混合模式
sprite.blendMode = 'normal';
// 滤镜
sprite.filters = [new PIXI.BlurFilter()];
// 遮罩
sprite.mask = maskGraphics;
// 渲染组
sprite.parentGroup = myGroup;
// z 轴排序
sprite.zIndex = 10;
坐标系统 #
text
┌─────────────────────────────────────────────────────────────┐
│ 坐标系统 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 全局坐标(屏幕坐标) │
│ ┌────────────────────────────────────────┐ │
│ │ (0,0) │ │
│ │ │ │
│ │ 屏幕空间 │ │
│ │ │ │
│ │ (w,h) │ │
│ └────────────────────────────────────────┘ │
│ │
│ 本地坐标(相对于父容器) │
│ ┌────────────────────────────────────────┐ │
│ │ parent (100, 100) │ │
│ │ ┌──────────────────┐ │ │
│ │ │ (0,0) child │ │ │
│ │ │ │ │ │
│ │ └──────────────────┘ │ │
│ └────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
坐标转换 #
javascript
// 本地坐标转全局坐标
const globalPos = sprite.toGlobal({ x: 0, y: 0 });
console.log('全局坐标:', globalPos.x, globalPos.y);
// 全局坐标转本地坐标
const localPos = sprite.toLocal({ x: 100, y: 100 });
console.log('本地坐标:', localPos.x, localPos.y);
// 从一个对象转换到另一个对象
const pos = sprite1.toLocal({ x: 0, y: 0 }, sprite2);
边界框 #
javascript
// 获取边界框
const bounds = sprite.getBounds();
console.log('x:', bounds.x);
console.log('y:', bounds.y);
console.log('width:', bounds.width);
console.log('height:', bounds.height);
// 获取本地边界框
const localBounds = sprite.getLocalBounds();
Sprite(精灵) #
Sprite 是最常用的显示对象,用于显示图像。
创建精灵 #
javascript
import { Sprite } from 'pixi.js';
// 从图片路径创建
const sprite1 = Sprite.from('player.png');
// 从纹理创建
const texture = PIXI.Texture.from('player.png');
const sprite2 = new Sprite(texture);
// 从帧创建(精灵表)
const sprite3 = Sprite.from('spritesheet.json#player');
精灵属性 #
javascript
const sprite = Sprite.from('player.png');
// 锚点(旋转和缩放的中心点)
sprite.anchor.set(0.5); // 中心
sprite.anchor.set(0, 0); // 左上角
sprite.anchor.set(1, 1); // 右下角
// 纹理区域
sprite.texture = PIXI.Texture.from('other.png');
// 色调
sprite.tint = 0xff0000; // 红色调
// 翻转
sprite.scale.x = -1; // 水平翻转
AnimatedSprite(动画精灵) #
javascript
import { AnimatedSprite } from 'pixi.js';
// 从精灵表创建动画
const frames = [];
for (let i = 0; i < 8; i++) {
frames.push(PIXI.Texture.from(`walk_${i}.png`));
}
const animatedSprite = new AnimatedSprite(frames);
// 播放动画
animatedSprite.play();
// 动画速度
animatedSprite.animationSpeed = 0.1;
// 循环
animatedSprite.loop = true;
// 动画事件
animatedSprite.onComplete = () => {
console.log('动画完成');
};
Ticker(计时器) #
Ticker 是 PixiJS 的核心计时系统,用于驱动动画和游戏循环。
使用 Ticker #
javascript
// Application 自动创建 Ticker
app.ticker.add((ticker) => {
// ticker.deltaTime - 上一帧到这一帧的时间(归一化)
// ticker.deltaMS - 毫秒数
// ticker.FPS - 当前帧率
sprite.rotation += 0.01 * ticker.deltaTime;
});
Ticker 属性 #
javascript
// 当前 FPS
app.ticker.FPS;
// 帧时间(毫秒)
app.ticker.deltaMS;
// 归一化帧时间(60fps 为基准)
app.ticker.deltaTime;
// 是否暂停
app.ticker.started;
// 最小 FPS
app.ticker.minFPS = 30;
// 最大 FPS
app.ticker.maxFPS = 60;
手动控制 Ticker #
javascript
// 停止
app.ticker.stop();
// 启动
app.ticker.start();
// 移除回调
const callback = (ticker) => {
sprite.rotation += 0.01 * ticker.deltaTime;
};
app.ticker.add(callback);
app.ticker.remove(callback);
// 单次回调
app.ticker.addOnce((ticker) => {
console.log('下一帧执行');
});
独立 Ticker #
javascript
import { Ticker } from 'pixi.js';
const myTicker = new Ticker();
myTicker.add((ticker) => {
// 独立的更新循环
});
myTicker.start();
实战示例 #
创建游戏场景 #
javascript
import { Application, Container, Sprite, Text } from 'pixi.js';
class GameScene {
constructor() {
this.app = new Application();
this.layers = {};
}
async init() {
await this.app.init({
width: 800,
height: 600,
backgroundColor: 0x1099bb
});
document.body.appendChild(this.app.canvas);
this.createLayers();
this.createPlayer();
this.setupGameLoop();
}
createLayers() {
this.layers.background = new Container();
this.layers.game = new Container();
this.layers.ui = new Container();
this.app.stage.addChild(
this.layers.background,
this.layers.game,
this.layers.ui
);
}
createPlayer() {
this.player = Sprite.from('player.png');
this.player.anchor.set(0.5);
this.player.x = this.app.screen.width / 2;
this.player.y = this.app.screen.height / 2;
this.layers.game.addChild(this.player);
}
setupGameLoop() {
this.app.ticker.add((ticker) => {
this.update(ticker.deltaTime);
});
}
update(delta) {
this.player.rotation += 0.01 * delta;
}
}
const game = new GameScene();
await game.init();
粒子效果 #
javascript
import { Application, Container, Sprite, Ticker } from 'pixi.js';
class ParticleSystem {
constructor(app, options = {}) {
this.app = app;
this.container = new Container();
this.particles = [];
this.options = {
count: options.count || 100,
speed: options.speed || 2,
lifetime: options.lifetime || 60,
texture: options.texture || 'particle.png'
};
this.init();
}
init() {
for (let i = 0; i < this.options.count; i++) {
this.createParticle();
}
this.app.stage.addChild(this.container);
this.app.ticker.add((ticker) => {
this.update(ticker.deltaTime);
});
}
createParticle() {
const particle = Sprite.from(this.options.texture);
particle.anchor.set(0.5);
particle.x = this.app.screen.width / 2;
particle.y = this.app.screen.height / 2;
particle.vx = (Math.random() - 0.5) * this.options.speed;
particle.vy = (Math.random() - 0.5) * this.options.speed;
particle.life = this.options.lifetime;
this.container.addChild(particle);
this.particles.push(particle);
}
update(delta) {
for (let i = this.particles.length - 1; i >= 0; i--) {
const p = this.particles[i];
p.x += p.vx * delta;
p.y += p.vy * delta;
p.life -= delta;
p.alpha = p.life / this.options.lifetime;
if (p.life <= 0) {
this.container.removeChild(p);
this.particles.splice(i, 1);
this.createParticle();
}
}
}
}
下一步 #
掌握了基础概念后,接下来学习 图形绘制,学习如何使用 Graphics API 绘制各种形状!
最后更新:2026-03-29