前端开发
PixiJS v7 升级到 v8…
适用于从 PixiJS v7 升级到 v8,或升级后诊断 v7 代码破坏性变更错误的项目。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
PixiJS v7 升级到 v8 时按破特定
解决思路
- 安装单一 `pixi.js` 包,并按 `imports → Application init → Graphics → Text → events → shaders/filters → cleanup` 的顺序移植。
- 迁移后按快速示例验证:`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);`
- 初始化:使用异步 `app.init()`:`const app = new Application(); await app.init({ width: 800, height: 600 }); document.body.appendChild(app.canvas);`
- 初始化:不要向 `new Application({...})` 传 options 并同步使用。
- 初始化:用 `app.canvas` 取代 `app.view`;`app.view` 会发出弃用警告。
- 初始化:Application 类型参数使用 `new Application<Renderer<HTMLCanvasElement>>()`,不要用 `new Application<HTMLCanvasElement>()`。
- 导入:从单一包导入核心 API,例如 `import { Sprite, Application, Assets, Graphics } from 'pixi.js';`
- 导入:不要从任何已弃用的 v7 core `@pixi/*` 子包导入;补充包如 `@pixi/sound` 仍有效并可继续使用。
- 导入:弃用的 `@pixi/*` 包(任何版本都不要用):`@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`。
- 导入:自定义构建时设置 `skipExtensionImports: true` 并只导入所需扩展:`import 'pixi.js/graphics'; import 'pixi.js/text'; import 'pixi.js/events'; import { Application } from 'pixi.js'; await app.init({ skipExtensionImports: true });`
- 导入:`manageImports: false` 仍被接受但自 8.1.6 起弃用;优先使用 `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`。
- 导入:社区滤镜使用 `import { AdjustmentFilter } from 'pixi-filters/adjustment'`,不要使用 `@pixi/filter-adjustment`。
- Graphics API:使用 shape-then-fill:`const g = new Graphics().rect(50, 50, 100, 100).fill(0xff0000);`;不要 `beginFill(0xff0000).drawRect(50, 50, 100, 100).endFill()`。
- Graphics API:重命名形状方法:`drawRect` -> `rect`;`drawCircle` -> `circle`;`drawEllipse` -> `ellipse`;`drawPolygon` -> `poly`;`drawRoundedRect` -> `roundRect`;`drawStar` -> `star`;`drawRegularPolygon` -> `regularPoly`;`drawRoundedPolygon` -> `roundPoly`;`drawRoundedShape` -> `roundShape`;`drawChamferRect` -> `chamferRect`;`drawFilletRect` -> `filletRect`。
- Graphics API:用 `fill` 取代 `beginFill`/`beginTextureFill`:`graphics.rect(0, 0, 100, 100).fill({ texture: Texture.WHITE, alpha: 0.5, color: 0xff0000 });`;不要 `beginFill(color, alpha)` 或 `beginTextureFill({ texture, alpha, color })`。
- Graphics API:用 `stroke` 取代 `lineStyle`:`graphics.rect(0, 0, 100, 100).fill('blue').stroke({ width: 2, color: 'white' });`;不要 `lineStyle(2, 'white')` 或 `lineTextureStyle({ texture, width, color })`。
- Graphics API:孔洞使用 `cut()`:`graphics.rect(0, 0, 100, 100).fill(0x00ff00).circle(50, 50, 20).cut();`;不要 `beginHole()` / `endHole()`。
- Graphics API:用 `GraphicsContext` 取代 `GraphicsGeometry`:`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)`。
- Text:构造函数使用 options 对象:`new Text({ text: 'Hello', style: { fontSize: 24 } });`、`new BitmapText({ text: 'Hello', style: { fontFamily: 'MyFont' } });`、`new HTMLText({ text: '<b>Hello</b>', style: { fontSize: 24 } });`;不要位置参数 `new Text('Hello', { fontSize: 24 })`。
- Text:加载位图字体前必须 `import 'pixi.js/text-bitmap'`,然后再 `Assets.load('font.fnt')`。
- Sprites/Mesh:`Texture.from` 不再加载 URL;必须先 `await Assets.load('image.png')`,再 `Texture.from('image.png')`。
- Sprites/Mesh:用 `NineSliceSprite` 取代 `NineSlicePlane`:`const ns = new NineSliceSprite({ texture, leftWidth: 10, topHeight: 10, rightWidth: 10, bottomHeight: 10 });`
- Sprites/Mesh:Mesh 重命名:`SimpleMesh` -> `MeshSimple`,`SimplePlane` -> `MeshPlane`,`SimpleRope` -> `MeshRope`;它们都使用 options objects。
- Sprites/Mesh:`MeshGeometry` 使用 options:`const geom = new MeshGeometry({ positions: vertices, uvs, indices, topology: 'triangle-list' });`;不要 `new MeshGeometry(vertices, uvs, indices)`。
- Sprites/Mesh:`ParticleContainer` 使用 `Particle`:`const container = new ParticleContainer({ boundsArea: new Rectangle(0, 0, 800, 600) }); const particle = new Particle(texture); container.addParticle(particle);`;不要 `container.addChild(new Sprite(texture))`。
- Events:用 `eventMode` 取代 `interactive`:`sprite.eventMode = 'static'; sprite.cursor = 'pointer'; sprite.on('pointertap', () => { /* handle */ });`
- Events:`sprite.interactive = true;` 仍可作为 `eventMode = 'static'` 的别名工作,但优先使用显式 `eventMode`。
- Events:默认 `eventMode` 是 `'passive'`(无事件);必须显式设置为 `'static'` 或 `'dynamic'`。
- Events:Ticker 回调使用 `app.ticker.add((ticker) => { bunny.rotation += ticker.deltaTime; });`;不要 `app.ticker.add((dt) => { bunny.rotation += dt; })`,因为 `dt` 是 `Ticker` 对象而非数字,会强制转成 `NaN` 并静默破坏旋转。
- Events:`updateTransform` 已移除;改为在 constructor 中使用 `this.onRender = this._onRender.bind(this)`。
- Shaders:`Shader.from` 使用 options:`const shader = Shader.from({ gl: { vertex: vertexSrc, fragment: fragmentSrc }, resources: { myUniforms: new UniformGroup({ uTime: { value: 0, type: 'f32' } }) } });`;不要 `Shader.from(vertex, fragment, uniforms)`。
- Shaders:Filter 构造函数使用:`const filter = new Filter({ glProgram: GlProgram.from({ fragment, vertex }), resources: { filterUniforms: { uTime: { value: 0, type: 'f32' } } } });`;不要 `new Filter(vertex, fragment, { uTime: 0 })`。
- Shaders:Uniforms 必须包含类型:`new UniformGroup({ uTime: { value: 1, type: 'f32' } })`;不要 `new UniformGroup({ uTime: 1 })`。
- Shaders:纹理是资源不是 uniforms;作为顶层资源条目传入(`texture.source`、`texture.style`),不要放进 UniformGroup。
- Textures:Sprite 不再自动检测 texture UV 变化;修改 texture 的 frame 后,先调用 `texture.update()` 重新计算 UV,再调用 `sprite.onViewUpdate()` 刷新 sprite,顺序必须如此;更新 source data(例如视频纹理)仍自动。示例:`texture.frame.width = texture.frame.width / 2; texture.update(); sprite.onViewUpdate();`
- Textures:Mipmaps:`BaseTexture.mipmap` 重命名为 `autoGenerateMipmaps`。
- Textures:对 RenderTextures 必须手动更新 mipmaps:`const rt = RenderTexture.create({ width: 100, height: 100, autoGenerateMipmaps: true }); renderer.render({ target: rt, container: scene }); rt.source.updateMipmaps();`
- Adapters:用 `DOMAdapter` 取代 `settings.ADAPTER`:`import { DOMAdapter, WebWorkerAdapter } from 'pixi.js'; DOMAdapter.set(WebWorkerAdapter); DOMAdapter.get().createCanvas();`;不要 `settings.ADAPTER = WebWorkerAdapter; settings.ADAPTER.createCanvas();`。
- Adapters:内置 adapters 有 `BrowserAdapter`(默认)和 `WebWorkerAdapter`(用于 web workers)。
- Other:`DisplayObject` 已移除;`Container` 是基类;`class MyObj extends DisplayObject` 会失败,应改为 `class MyObj extends Container`。
- Other:叶子节点不能有子节点;`Sprite`、`Graphics`、`Mesh`、`Text` 是叶子节点,需要子节点时包在 `Container` 中。
- Other:重命名属性:`container.name` -> `container.label`;`container.cacheAsBitmap = true` -> `container.cacheAsTexture(true)`;旧名仍作为带警告的弃用别名存在。
- Other:`getBounds()` 返回类型改变:现在返回 `Bounds` 对象,不是 `Rectangle`;`Bounds` 有 `.x`、`.y`、`.width`、`.height` getters,基本用法可工作;需要 `Rectangle` 实例时(例如 `.contains()`)使用 `.rectangle`。
- Other:`settings` 对象已移除;使用 `AbstractRenderer.defaultOptions.resolution = 1` 和 `DOMAdapter.set(BrowserAdapter)`。
- Other:`utils` 命名空间已移除;用 `import { isMobile } from 'pixi.js'` 替代 `utils.isMobile`。
- Other:Text parser 重命名:`TextFormat` -> `bitmapFontTextParser`;`XMLStringFormat` -> `bitmapFontXMLStringParser`;`XMLFormat` -> `bitmapFontXMLParser`。
- Other:`Assets.add`:`Assets.add({ alias: 'bunny', src: 'bunny.png' })`;不要 `Assets.add('bunny', 'bunny.png')`。
- Other:枚举常量替换为字符串:`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'`。
- Other:Culling 是手动的;设置 `cullable = true`,然后渲染前调用 `Culler.shared.cull(container, viewRect)`;或通过 `extensions.add(CullerPlugin)` 添加 `CullerPlugin`。
- 迁移前检查:dependencies 中没有弃用的 v7 core `@pixi/*` 包(补充包如 `@pixi/sound` 可以)。
- 迁移前检查:所有核心 `@pixi/*` imports 已转换为 `pixi.js`。
- 迁移前检查:所有 `new Application({...})` 已转换为 `await app.init({...})`。
- 迁移前检查:所有 Graphics 代码使用 shape-then-fill 模式。
- 迁移前检查:所有构造函数使用 options 对象(Text、Mesh、NineSliceSprite 等)。
- 迁移前检查:Shader/Filter 代码使用 `{gl, resources}` 模式并带类型化 uniforms。
- 迁移前检查:ParticleContainer 代码使用 `Particle`,不是 `Sprite`。
- 迁移前检查:Ticker 回调访问 `ticker.deltaTime`,不是把第一个参数当 delta。
- 迁移前检查:事件处理使用 `eventMode` 而不是 `interactive`。
- 迁移前检查:`settings` 和 `utils` 引用已移除。
- 迁移前检查:`DisplayObject` 引用已替换为 `Container`。
- 迁移前检查:Texture UV 修改在需要处调用 `sprite.onViewUpdate()`。
- 迁移前检查:RenderTexture mipmap 代码手动调用 `source.updateMipmaps()`。
- 迁移前检查:`settings.ADAPTER` 已替换为 `DOMAdapter.set()`。
- 常见错误:不要从已弃用的 v7 core `@pixi/*` 子包导入;正确:`import { Sprite, Application } from 'pixi.js';`。
- 常见错误:不要用 `DisplayObject` 作为基类;正确:`class MyObject extends Container { ... }`。
- 常见错误:不要使用旧 `SCALE_MODES`/`WRAP_MODES`/`DRAW_MODES` 枚举;正确:`texture.source.scaleMode = 'nearest';`。
- 常见错误:不要用 `interactive = true` 代替 `eventMode`;优先 `sprite.eventMode = 'static';`;默认 `'passive'`,必须显式设置。
- 常见错误:不要使用 `utils` 命名空间;正确:`import { isMobile } from 'pixi.js'; isMobile.any();`。
- 常见错误:不要期待 texture UV 变化自动更新 sprites;修改 `texture.frame` 后调用 `sprite.onViewUpdate()`。
- 需要时查阅 API 参考:v8 Migration Guide、v7 Migration Guide、Application、Graphics、Container 文档链接。
适用边界 · 注意事项
- 不适用于没有使用 PixiJS 或不是从 v7 升级到 v8 的项目。
- 不适用于仍停留在 PixiJS v7 且无迁移计划的项目;不要提前按 v8 API 改写。
- 如果依赖已弃用 @pixi/* 核心子包且无法替换为 pixi.js,则不能完成本迁移;补充包 @pixi/sound 可继续使用。