PixiJS v8 迁移实战指南:从 v7 到 v8 的破坏性变更清单与代码改造手册
【免费下载链接】pixijsThe HTML5 Creation Engine: Create beautiful digital content with the fastest, most flexible 2D WebGL renderer.项目地址: https://gitcode.com/gh_mirrors/pi/pixijs
本指南基于 PixiJS 仓库中 v8 迁移 Skill(skills/pixijs-migration-v8/SKILL.md)与官方迁移文档(src/docs/migrations/v8.md),系统梳理从 v7 升级到 v8 时所有必须关注的破坏性变更:异步初始化、单一pixi.js包、Graphics 的"先造型后填充"范式、纹理/着色器体系重构等。读完本文,你将掌握一份可直接对照执行的迁移检查清单,能把存量 v7 代码逐项改写成符合 v8 规范、可在 WebGL/WebGPU 双后端下运行的新代码。
迁移前:先判断"要不要升"
v8 引入了 WebGPU 渲染后端,整体性能与架构有大幅提升,但破坏性变更同样显著。升级前先问自己一个问题:项目依赖的第三方 Pixi 生态库是否已经迁移到 v8?官方迁移文档列出的生态状态如下:
- 已迁移:Filters、Sound、Gif、Storybook、UI、Open Games;
- 迁移中:React、Spine;
- 待迁移:Pixi layers(官方倾向直接并入 v8 核心而非单独迁移)。
若你的项目重度依赖尚未迁移的库,建议暂缓升级;纯 Pixi 项目则可以直接动手。升级顺序建议为:导入语句 → Application 初始化 → Graphics → Text → 事件 → 着色器/滤镜 → 收尾清理。
快速上手:最小可运行的 v8 应用
import { Application, Graphics } from "pixi.js"; const app = new Application(); await app.init({ width: 800, height: 600 }); document.body.appendChild(app.canvas); const g = new Graphics() .rect(0, 0, 100, 100) .fill({ color: 0xff0000 }) .stroke({ width: 2, color: 0x000000 }); app.stage.addChild(g);注意与 v7 的关键差异:new Application()不再接受配置对象、必须await app.init(...);画布挂载使用app.canvas而非app.view;Graphics 采用"先画形状、再填充/描边"的链式调用。这一点在 Application 源码 中有明确佐证:构造函数中传入 options 会触发deprecation警告("Application constructor options are deprecated, please use Application.init() instead"),而init()内部通过autoDetectRenderer异步创建渲染器。
初始化:异步化与类型参数
必须 await app.init()
v8 引入 WebGPU 渲染器后,渲染器的创建变成了异步操作,init()返回 Promise。错误写法是把 options 传给构造函数并同步使用;正确写法如下:
const app = new Application(); await app.init({ width: 800, height: 600 }); document.body.appendChild(app.canvas);从 Application.init 实现 可以看到,它先autoDetectRenderer(options)异步创建渲染器,再依次执行已注册的 Application 插件(如 TickerPlugin、ResizePlugin、CullerPlugin)。这也是为什么app.ticker、app.renderer等属性只有在await init()之后才可用。
app.canvas 取代 app.view
app.view依然存在但会打印弃用警告(见 Application 源码),请统一改用app.canvas。传入自定义画布的方式也变为await app.init({ view: document.createElement('canvas') })。
泛型参数改为 Renderer 类型
v7 中new Application<HTMLCanvasElement>()在 v8 不再正确,因为泛型描述的不再是"视图类型"而是"渲染器类型",以保证app.renderer的类型推断准确:
// WebGL 或 WebGPU(自动检测) const app = new Application<Renderer<HTMLCanvasElement>>(); // 强制 WebGL const app = new Application<WebGLRenderer<HTMLCanvasElement>>(); // 强制 WebGPU const app = new Application<WebGPURenderer<HTMLCanvasElement>>();初始化参数速查
ApplicationOptions支持渲染、性能、自适应缩放等配置,常用项如下(完整定义见 Application 源码):
| 选项 | 说明 |
|---|---|
width/height | 画布宽高(像素) |
backgroundColor | 背景色,如0x1099bb |
antialias | 是否开启抗锯齿 |
resolution | 分辨率/设备像素比,常设window.devicePixelRatio |
preference | 渲染后端:'webgl'、'webgpu'、'canvas'或数组 |
powerPreference | GPU 电源偏好,如'high-performance' |
autoStart | 是否自动启动渲染循环 |
sharedTicker | 是否使用共享 Ticker |
resizeTo/autoDensity | 自动缩放与 DPR 适配 |
skipExtensionImports | 是否跳过默认扩展的自动导入(自定义构建用) |
导入:从 @pixi/* 子包回归单一 pixi.js 包
单一包结构
自 v5 起 PixiJS 采用多子包结构,但多版本共存容易引发内部缓存冲突。v8 回归单一包:
// v7 旧写法 import { Application } from "@pixi/app"; import { Sprite } from "@pixi/sprite"; // v8 新写法 import { Application, Sprite } from "pixi.js";以下 v7 核心子包在任何版本下都禁止再使用(补充性生态包如@pixi/sound不受影响,可继续使用):
@pixi/accessibility、@pixi/app、@pixi/assets、@pixi/compressed-textures、@pixi/core、@pixi/display、@pixi/events、@pixi/extensions、@pixi/extract、@pixi/filter-alpha、@pixi/filter-blur、@pixi/filter-color-matrix、@pixi/filter-displacement、@pixi/filter-fxaa、@pixi/filter-noise、@pixi/graphics、@pixi/mesh、@pixi/mesh-extras、@pixi/mixin-cache-as-bitmap、@pixi/mixin-get-child-by-name、@pixi/mixin-get-global-position、@pixi/particle-container、@pixi/prepare、@pixi/sprite、@pixi/sprite-animated、@pixi/sprite-tiling、@pixi/spritesheet、@pixi/text、@pixi/text-bitmap、@pixi/text-html。
自定义构建与扩展导入
v8 通过"扩展(extensions)"系统为渲染器按需装配能力。默认情况下以下扩展会被自动导入:accessibility、app、events、filters、sprite-tiling、text、text-bitmap、text-html、graphics、mesh、sprite-nine-slice。
若想完全控制包体积,可设置skipExtensionImports: true并手动按需导入:
import "pixi.js/graphics"; import "pixi.js/text"; import "pixi.js/events"; import { Application } from "pixi.js"; const app = new Application(); await app.init({ skipExtensionImports: true });从 AbstractRenderer 初始化逻辑 可以看到:skipExtensionImports === true或旧选项manageImports === false时,渲染器会跳过环境扩展加载与默认 loader 注册。注意manageImports: false自 8.1.6 起标记为@deprecated(定义见 SharedSystems.ts),一律改用skipExtensionImports: true。
即便开启默认自动导入,以下扩展也必须显式手动导入:pixi.js/advanced-blend-modes、pixi.js/unsafe-eval、pixi.js/prepare、pixi.js/math-extras、pixi.js/dds、pixi.js/ktx、pixi.js/ktx2、pixi.js/basis。
还有一个易踩的坑:pixi.js/text-bitmap会额外注册 Assets 加载能力。如果要在渲染器初始化之前加载位图字体,必须先导入它:
import "pixi.js/text-bitmap"; import { Assets, Application } from "pixi.js"; await Assets.load("my-font.fnt"); // 未导入 text-bitmap 则此步无法加载 await new Application().init();社区滤镜
@pixi/filter-*系列包在 v8 下不再维护,改为从pixi-filters子模块直接导入:
import { AdjustmentFilter } from "pixi-filters/adjustment"; // 而非 @pixi/filter-adjustmentGraphics:先造型、后填充(shape-then-fill)
Graphics 是 v8 改动最大的 API。"先 beginFill 再画形状"的旧流程被彻底反转——先画出形状,再对上一个形状执行fill/stroke/cut。
// v7 旧写法 const g = new Graphics().beginFill(0xff0000).drawRect(50, 50, 100, 100).endFill(); // v8 新写法 const g = new Graphics().rect(50, 50, 100, 100).fill(0xff0000);形状方法更名对照表
| v7 | v8 |
|---|---|
drawRect | rect |
drawCircle | circle |
drawEllipse | ellipse |
drawPolygon | poly |
drawRoundedRect | roundRect |
drawStar | star |
drawRegularPolygon | regularPoly |
drawRoundedPolygon | roundPoly |
drawRoundedShape | roundShape |
drawChamferRect | chamferRect |
drawFilletRect | filletRect |
fill 取代 beginFill / beginTextureFill
fill接受颜色或FillStyle选项对象,同时替代了beginFill与beginTextureFill:
graphics .rect(0, 0, 100, 100) .fill({ texture: Texture.WHITE, alpha: 0.5, color: 0xff0000 });stroke 取代 lineStyle / lineTextureStyle
graphics.rect(0, 0, 100, 100).fill("blue").stroke({ width: 2, color: "white" }); // 纹理描边 graphics .rect(0, 0, 100, 100) .stroke({ texture: Texture.WHITE, width: 10, color: 0xff0000 });lineStyle(2, 'white')、lineTextureStyle({...})均告废弃。
镂空用 cut()
beginHole()/endHole()被cut()取代,同样作用于前一个形状:
graphics.rect(0, 0, 100, 100).fill(0x00ff00).circle(50, 50, 20).cut();GraphicsContext 取代 GraphicsGeometry
v8 把绘图指令抽到独立的GraphicsContext,多个Graphics可共享同一份上下文,数据复用更高效:
const context = new GraphicsContext().rect(0, 0, 100, 100).fill(0xff0000); const g1 = new Graphics(context); const g2 = new Graphics(context);旧写法new Graphics(graphics.geometry)已失效。仓库中大量示例采用新范式,可参考 graphics_basic_shapes.ts 与 graphics_fill_stroke_gradient.ts 等示例文件的实际用法。
Text:构造器全部改为选项对象
v7 的位置参数构造(new Text('Hello', style))在 v8 一律改为单一 options 对象:
const text = new Text({ text: "Hello", style: { fontSize: 24 } }); const bmp = new BitmapText({ text: "Hello", style: { fontFamily: "MyFont" } }); const html = new HTMLText({ text: "<b>Hello</b>", style: { fontSize: 24 } });加载位图字体前必须import 'pixi.js/text-bitmap'(见上文"自定义构建"一节)。其余受影响构造器同理:BlurFilter({ blur, quality, resolution, kernelSize })、DisplacementFilter({ sprite, scale })、PlaneGeometry({ width, height, verticesX, verticesY })、TileSprite({ texture, width, height })等全部改为对象入参。
Sprites 与 Mesh
Texture.from 不再自动加载 URL
v8 中纹理不再自行管理资源加载,Texture.from只接受已加载的资源或已通过Assets.load注册的字符串:
await Assets.load("image.png"); // 必须先加载 const texture = Texture.from("image.png");NineSliceSprite 取代 NineSlicePlane
const ns = new NineSliceSprite({ texture, leftWidth: 10, topHeight: 10, rightWidth: 10, bottomHeight: 10, });Mesh 类更名 + 选项对象
SimpleMesh→MeshSimple,SimplePlane→MeshPlane,SimpleRope→MeshRope,全部使用选项对象构造;MeshGeometry由位置参数改为对象(positions、uvs、indices、topology):
const geom = new MeshGeometry({ positions: vertices, uvs, indices, topology: "triangle-list", });ParticleContainer 改用 Particle
v8 的粒子容器不再接受 Sprite 子节点,而是接收实现了IParticle接口(x、y、scaleX、scaleY、anchorX、anchorY、rotation、color、texture)的轻量Particle对象。粒子不进入场景图的children数组,而是存储在扁平列表particleChildren中,因此容器不再自算边界,需要你显式提供boundsArea:
const container = new ParticleContainer({ boundsArea: new Rectangle(0, 0, 800, 600), }); for (let i = 0; i < 100000; i++) { const particle = new Particle(texture); container.addParticle(particle); }由于省去了 Sprite 的冗余属性与事件,粒子渲染数量上限大幅提升。相关示例见 particle-container_basic.ts。
事件系统:eventMode 取代 interactive
eventMode / cursor
v8 默认eventMode为'passive'(不接收任何事件),必须显式设为'static'(可命中测试,不做 tick 检查)或'dynamic'(可命中测试且带 tick 检查)。sprite.interactive = true仍然作为eventMode = 'static'的别名可用,但推荐使用规范写法:
sprite.eventMode = "static"; sprite.cursor = "pointer"; sprite.on("pointertap", () => { /* handle */ });默认值'passive'在 EventSystem 源码 中有直接实现:EventSystem._defaultEventMode = options.eventMode ?? 'passive'。事件系统的完整行为可查阅 src/events/EventBoundary.ts 与事件相关 Skill(skills/pixijs-events/SKILL.md)。
Ticker 回调参数是 Ticker 实例
v8 中ticker.add的回调第一个参数从"增量时间数值"改为Ticker实例:
app.ticker.add((ticker) => { bunny.rotation += ticker.deltaTime; });高危陷阱:旧写法app.ticker.add((dt) => { bunny.rotation += dt; })能通过编译,但dt实际是Ticker对象,参与数值运算会被强转为NaN,导致旋转值被静默污染。
updateTransform 被移除
节点不再承载渲染逻辑,updateTransform覆写模式失效。自定义每帧逻辑请改在构造器中绑定onRender:
class MySprite extends Sprite { constructor() { super(); this.onRender = this._onRender.bind(this); } _onRender() { // do custom logic } }着色器与滤镜:{ gl, resources } 资源体系
v8 需要同时兼容 WebGL 与 WebGPU 着色器,构造方式全面重构。核心变化是:纹理不再是 uniform,而是作为顶层resources条目传入(texture.source、texture.style);uniform 必须显式声明类型。
Shader.from
const shader = Shader.from({ gl: { vertex: vertexSrc, fragment: fragmentSrc }, resources: { myUniforms: new UniformGroup({ uTime: { value: 0, type: "f32" } }), }, });同时提供gpu字段(含entryPoint与 WGSL 源码)即可实现双后端。旧写法Shader.from(vertex, fragment, uniforms)已废弃。
Filter 构造
const filter = new Filter({ glProgram: GlProgram.from({ fragment, vertex }), resources: { filterUniforms: { uTime: { value: 0, type: "f32" } } }, });旧写法new Filter(vertex, fragment, { uTime: 0 })失效。
UniformGroup 需要类型
const uniformGroup = new UniformGroup({ uTime: { value: 1, type: "f32" }, }); uniformGroup.uniforms.uTime = 100;new UniformGroup({ uTime: 1 })这种不带type的写法不再合法。仓库中的自定义着色器示例(mesh_custom_shader_geometry、filters_custom-shader_glsl)以及 skills/pixijs-custom-rendering/SKILL.md 提供了完整的双后端着色器实战参考。
纹理:TextureSource 体系与手动更新
BaseTexture → TextureSource
v7 的BaseTexture在 v8 中不复存在,取而代之的是一组职责更单一的 TextureSource(纹理源 = 纹理设置 + 上传/使用方式):
TextureSource:通用纹理源,可自由渲染或上传(主要用于 RenderTexture);ImageSource:承载 ImageBitmap / HTMLImageElement 等图像资源;CanvasSource:承载 canvas,主要用于 canvas 渲染(WebGPU);VideoSource:承载视频,自动保持 GPU 纹理与视频帧同步;BufferSource:承载任意 buffer,需保证 buffer 类型与格式兼容;CompressedSource:处理 GPU 压缩纹理格式。
手动创建纹理源的示例如下:
const image = new Image(); image.onload = function () { const source = new ImageSource({ resource: image }); const texture = new Texture({ source }); }; image.src = "myImage.png";日常使用中Assets.load返回的依然是Texture,直接使用即可。
精灵不再自动响应纹理 UV 变化
出于性能考虑(频繁换纹理时事件订阅/解绑开销不可接受),v8 的 Sprite 不再订阅纹理 UV 变更事件。若修改了纹理 frame,必须依次调用texture.update()重算 UV,再调用sprite.onViewUpdate()刷新精灵显示,两者缺一不可;更新纹理源数据(如视频纹理)则仍会自动生效:
texture.frame.width = texture.frame.width / 2; texture.update(); // 先重算纹理 UV sprite.onViewUpdate(); // 再刷新精灵显示Mipmap 手动管理
BaseTexture.mipmap更名为autoGenerateMipmaps。RenderTexture 的 mipmap 不再自动更新,需要在渲染后手动调用source.updateMipmaps():
const rt = RenderTexture.create({ width: 100, height: 100, autoGenerateMipmaps: true, }); renderer.render({ target: rt, container: scene }); rt.source.updateMipmaps();适配器:DOMAdapter 取代 settings.ADAPTER
v8 移除了全局settings对象,环境适配改用静态类DOMAdapter。内置两个适配器:BrowserAdapter(默认)与WebWorkerAdapter(Web Worker 环境):
import { DOMAdapter, WebWorkerAdapter } from "pixi.js"; DOMAdapter.set(WebWorkerAdapter); DOMAdapter.get().createCanvas();settings.ADAPTER = WebWorkerAdapter; settings.ADAPTER.createCanvas()的旧写法失效。浏览器环境适配器实现见 src/environment-browser/BrowserAdapter.ts,Web Worker 版本见 src/environment-webworker/WebWorkerAdapter.ts。
其他破坏性变更汇总
- DisplayObject 被移除:
Container成为所有显示对象的基类,class MyObj extends DisplayObject编译失败; - 叶子节点不能有子节点:
Sprite、Graphics、Mesh、Text均为叶子节点,需要子节点时用Container包裹; - 属性更名(旧名保留为带警告的弃用别名):
container.name→container.label;container.cacheAsBitmap = true→container.cacheAsTexture(true); - getBounds() 返回类型变化:现在返回
Bounds对象而非Rectangle。Bounds自带.x/.y/.width/.heightgetter,基础用法不受影响;需要Rectangle实例(如调用.contains())时改用getBounds().rectangle; - settings 对象移除:改为
AbstractRenderer.defaultOptions.resolution = 1、DOMAdapter.set(BrowserAdapter)(也可在init/autoDetectRenderer时直接传resolution、failIfMajorPerformanceCaveat等选项); - utils 命名空间移除:
import { utils } from 'pixi.js'; utils.isMobile.any()→import { isMobile } from 'pixi.js'; isMobile.any(); - 文本解析器更名:
TextFormat→bitmapFontTextParser,XMLStringFormat→bitmapFontXMLStringParser,XMLFormat→bitmapFontXMLParser; - Assets.add 签名变化:
Assets.add('bunny', 'bunny.png')→Assets.add({ alias: 'bunny', src: 'bunny.png' }); - 枚举常量替换为字符串:
| v7 | v8 |
|---|---|
SCALE_MODES.NEAREST | 'nearest' |
SCALE_MODES.LINEAR | 'linear' |
WRAP_MODES.CLAMP | 'clamp-to-edge' |
WRAP_MODES.REPEAT | 'repeat' |
WRAP_MODES.MIRRORED_REPEAT | 'mirror-repeat' |
DRAW_MODES.TRIANGLES | 'triangle-list' |
DRAW_MODES.TRIANGLE_STRIP | 'triangle-strip' |
DRAW_MODES.LINES | 'line-list' |
DRAW_MODES.LINE_STRIP | 'line-strip' |
DRAW_MODES.POINTS | 'point-list' |
- 剔除(Culling)改为手动:设置
container.cullable = true,渲染前调用Culler.shared.cull(container, viewRect);需要模拟旧自动行为时,通过extensions.add(CullerPlugin)注册插件。相关属性还包括cullArea与cullableChildren,实现见 src/culling/Culler.ts。
迁移完成度自检清单
逐项核对,全部通过即可认为迁移完成:
- 依赖中不再存在 v7 核心
@pixi/*包(补充包如@pixi/sound允许保留) - 所有核心
@pixi/*导入已改为pixi.js - 所有
new Application({...})已改为await app.init({...}) - 所有 Graphics 代码采用先造型后填充模式
- 所有构造器使用选项对象(Text、Mesh、NineSliceSprite 等)
- Shader/Filter 代码使用
{ gl, resources }模式并带类型化 uniform - ParticleContainer 使用
Particle而非Sprite - Ticker 回调通过
ticker.deltaTime取增量,而非把首个参数当数值 - 事件处理使用
eventMode而非interactive settings与utils引用已清除DisplayObject引用全部替换为Container- 纹理 UV 修改处调用了
sprite.onViewUpdate() - RenderTexture 的 mipmap 代码手动调用
source.updateMipmaps() settings.ADAPTER已替换为DOMAdapter.set()
常见错误速查
[严重] 从废弃的 v7 核心子包导入
// 错误 import { Sprite } from "@pixi/sprite"; import { Application } from "@pixi/app"; // 正确 import { Sprite, Application } from "pixi.js";[严重] 用 DisplayObject 作基类
// 错误 class MyObject extends DisplayObject { /* ... */ } // 正确 class MyObject extends Container { /* ... */ }[高] 沿用旧枚举 SCALE_MODES / WRAP_MODES / DRAW_MODES
// 错误 texture.source.scaleMode = SCALE_MODES.NEAREST; // 正确 texture.source.scaleMode = 'nearest';旧枚举可能仍作为弃用别名工作,但应全部替换为字符串值。
[高] 用 interactive = true 代替 eventMode
interactive = true依旧作为eventMode = 'static'的别名(且无弃用警告),但eventMode才是 v8 规范 API。默认值'passive'意味着不显式设置就收不到任何事件。
[高] 使用 utils 命名空间
// 错误 import { utils } from 'pixi.js'; utils.isMobile.any(); // 正确 import { isMobile } from 'pixi.js'; isMobile.any();[高] 指望纹理 UV 变化自动更新精灵
修改texture.frame后必须调用sprite.onViewUpdate();纹理源数据更新(如视频)仍自动反映。
进一步阅读
- 官方 v8 迁移文档:src/docs/migrations/v8.md(本文的完整权威依据)
- 应用初始化细节:skills/pixijs-application/SKILL.md 与 Application 源码
- Graphics 新 API:skills/pixijs-scene-graphics/SKILL.md 及 graphics_fill_stroke_gradient.ts
- 着色器改造:skills/pixijs-custom-rendering/SKILL.md 与 mesh_custom_shader_geometry
- 纹理与资源系统:skills/pixijs-assets/SKILL.md
- 销毁与性能模式:skills/pixijs-performance/SKILL.md
【免费下载链接】pixijsThe HTML5 Creation Engine: Create beautiful digital content with the fastest, most flexible 2D WebGL renderer.项目地址: https://gitcode.com/gh_mirrors/pi/pixijs
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考