PixiJS v7 のマイグレーションガイドを読んでみる



## この記事は
PixiJSの7系がリリースされて約1年くらい経つ。
v5で時が止まっていた人間がいきなりv7に移行しようとしたところ、そこそこに破壊的な変更があってつまずいた。
公式がマイグレーションガイド [v7 Migration Guide · pixijs/pixijs Wiki](https://github.com/pixijs/pixijs/wiki/v7-Migration-Guide) を出してくれているので今日はこれを読む。
あくまで個人的な備忘録であり翻訳ではない。正確性も保証しない。
原文大して長くないけど一応ね
(2023/10/11 rev33 時点)

## 概要
> ## Overview
> First and foremost, PixiJS v7 is a modernization release that reflects changes in the ecosystem since PixiJS was first published over six years ago. Browsers have gotten better, but PixiJS hasn't really taken advantage of some of the new features like fetch, Workers, modern JavaScript language syntax. This release keeps intact much of the high-level DisplayObjects (e.g., Sprite, Graphics, Mesh, etc). Aside from a few things, this release should be medium to low impact for most users.

世の中の進歩についてけてないから思い切って色々変えちゃうよ！
以前のバージョン使ってるほぼ全員が小～中程度の影響を受けるでしょう


### IEにバイバイ
> Dropping Internet Explorer
> Microsoft officially ended support for IE, so we decided to follow. It simplified many of our modernizations since IE was an outliner from Safari/Chrome/Firefox/Edge and mobile browsers. If you need support for IE, please consider using Babel or some other trans-piling tool.

そうだね


### Polyfillsの同梱やめます
> Remove Polyfills
> We removed the bundled polyfills such as requestAnimationFrame and Promise. These things are widely available in browsers now. If projects require them, developers should include the polyfills they need for backward-compatibility. Please check out polyfill.io.

IEにバイバイしたしいいでしょ



### ES5止まりだったのをES2017に対応、モジュールはES2020に
> PixiJS historically only published ES5 (no classes!). A new output standard allows us to > use ES2017 features that previously we couldn't use (e.g., String.prototype.startsWith, Array.prototype.contains, etc). Not only does it make the code more readable, but the output looks nicer as well. For modules we are outputting ES2020, which contains syntax like nullish coalescing (??). If your project needs to have backward compatibility, you can use Babel to transpile or polyfill.

古いブラウザに対応したい人はBabelなりPolyfillなりなんなり使ってね



## `InteractionManager`は複雑すぎてコアメンバーのほとんども理解してないから廃止します 代わりに`FederatedEvents`を追加したよ
> ## Replaces InteractionManager with EventSystem
> InteractionManager was getting complex and difficult to maintain. Few core team members understood the code. We decided to move to FederatedEvents, which is concise, better aligned with the DOM, and supports things like bubbling. The good news, is you shouldn't have to change code, as it is largely a drop-in replacement. We added addEventListener and removeEventListener APIs to DisplayObject which have the same DOM signature and can be used instead of on and off.

7系では`DisplayObject`に`addEventListener`と`removeEventLisner`でイベント設定できるようになったよ
`on`,`off`も引き続き使えるよ

### どんなイベントが飛んでくんの
やってみる

```js
/**
*  適当なスプライトにクリックイベントのリスナー設定するだけ
*/
var app = new PIXI.Application({
    width: window.innerWidth,
    height: window.innerHeight,
    backgroundColor: 0x2c3e50
});
document.body.appendChild(app.view);

const bunny = PIXI.Sprite.from('https://pixijs.io/examples/examples/assets/bunny.png');       

bunny.anchor.set(0.5);
bunny.x = app.renderer.width / 2;
bunny.y = app.renderer.height / 2;
bunny.scale.set(3.0);

bunny.interactive = true;
bunny.interactiveMousewheel = true;
bunny.on('pointertap', function(e) {
    console.log(e);
})
// 7系からはこれでもいける(モジュールの場合は @pixi/events のインポートが必要)
// bunny.addEventListener('pointertap', function(e) {
//     console.log(e);
// })
app.stage.addChild(bunny);

```

#### 5系は`PIXI.InteractionEvent` [PixiJS API Documentation](https://pixijs.download/v5.3.12/docs/PIXI.InteractionEvent.html))
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557296/276bb94f-3a5e-40d4-0920-024d85103fa5.png)


#### 7系は`PIXI.FederatedPointerEvent` [PixiJS API Documentation](https://pixijs.download/v7.2.4/docs/PIXI.FederatedPointerEvent.html)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557296/4870e756-6d30-22e0-00f0-7be1a572cb73.png)


まだちゃんと中身見てない
コンテナに入れて試したら数値変わるとことかあるかも


ちなみにPixiのバージョン別APIリファレンスはここから開ける
[Versions | PixiJS](https://pixijs.com/versions)



## コールバック式の`Loader`はもう古い awaitとか使いたい
> ## Replaces Loader with Assets
> Similarly, we've been wanting to remove the Loader because of its legacy approach (e.g., XMLHttpRequest). This was forked from resource-loader that has been with PixiJS for a long time. The original design inspiration for Loader was driven largely by Flash/AS3, which now seem dated. There were a few things we wanted out of a new iteration: static loading, loading with Workers, background loading, Promise-based, fewer layers of caching. Here's a quick example of how this will change:
>  ```js
> import { Loader, Sprite } from 'pixi.js';
> const loader = new Loader();
> loader.add('background', 'path/to/assets/background.jpg');
> loader.load((loader, resources) => {
>   const image = Sprite.from(resources.background.texture);
> });
> ```
> Now becomes:
> ```js
> import { Assets, Sprite } from 'pixi.js';
> 
> const texture = await Assets.load('path/to/assets/background.jpg');
> const image = Sprite.from(texture);
> ```

PIXI.Loaderが使えなくなる

[PixiJS API Documentation > PIXI.Assets](https://pixijs.download/v7.3.1/docs/PIXI.Assets.html)
めんどくさそ～～
レガシーなことに付き合うためにめんどくさいことしてたので…

`PIXI.AssetsClass`に`app.loader.resources`に相当するものはないんですか


## peerDependenciesを使うのやめます(一部はやめるのやめました)
> ## Abandon the use of peerDependencies
> ~~PixiJS heavily uses peerDependencies in the package.json within each package. This design choice has plagued Pixi with many issues. It's a breaking change to remove, so now was a good time. We have decided to completely remove peerDependencies, instead opting for nothing. This should make installing and upgrading pixi.js much easier. We are working on updating our tooling for composing a custom version with packages.~~ Edit: As of 7.2.0, we have reverted this change to keep compatibility with some module-based CDNs.

がんばってほしいです



## その他の変更
> ## Other Changes
> * Browser builds have been removed for all packages, with the exception of pixi.js and pixi.js-legacy.
> * Removes Graphics.nextRoundedRectBehavior this is now the default behavior
> * Removes Text.nextLineHeightBehavior this is now the default behavior
> * AbstractBatchRenderer and BatchPluginFactory has been removed. Either extends BatchRenderer or use setShaderGenerator on the default BatchRenderer, (e.g., renderer.plugins.batch)
> * BatchRenderer is installed by default in @pixi/core, no need to Renderer.registerPlugin('batch', BatchRenderer) anymore

なるほど


### `@pixi/core`をインポートしてたら以下のパッケージのインポートをやめろ
> ### Exports from @pixi/core 
> The @pixi/core package now depends and re-exports the following packages.
>
> * @pixi/math
> * @pixi/contants
> * @pixi/utils
> * @pixi/runner
> * @pixi/settings
> * @pixi/ticker
>
> While some packages will still work when installed directly, others will not, since by installing them alongside @pixi/core you will be effectively importing two copies of the same code.  This will lead to errors where changing settings from @pixi/settings doesn't do anything since @pixi/core has its own version of that package. It is recommended that you uninstall these from your project and use @pixi/core instead.
> ```js
> import { Rectangle } from '@pixi/math';
> import { settings } from '@pixi/settings';
> import { ALPHA_MODES } from '@pixi/constants';
> import { string2hex } from '@pixi/utils';
> ```
> Now becomes: 
> ```js
> import { Rectangle, settings, ALPHA_MODES, utils } from '@pixi/core';
> 
> const { string2hex } = utils;
> ```


微妙に関係ないけどものぐさなのでいっそ関連パッケージ全部まとめてほしかった


### `renderer.plugins.extract` と `renderer.plugins.prepare` は `renderer.extract` と `renderer.prepare` になる
> ### Extract and prepare plugins have been converted to Renderer "systems".
> 
> ```js
> renderer.plugins.extract
> renderer.plugins.prepare
>  ```
> 
> Now becomes:
> 
> ```js
> renderer.extract
> renderer.prepare
> ```


### 拡張機能使う時 `extensions.add()` とかせず単純にimportするだけでよくなったよ
> ### Extensions Self-Install
> Extensions now install themselves, so you should only need to import the class in order to use. For example, in v6:
> ```js
> import { AccessibilityManager } from '@pixi/accessibility';
> import { extensions } from '@pixi/core';
> extensions.add(AccessibilityManager);
> ```
> 
> Now becomes:
> 
> ```js
> import '@pixi/accessibility';
> ```

v6飛び越えてきちゃったから恩恵にはあずからないけどいい変更っぽい
でもしばらくは古いドキュメントに惑わされる人がいそう
APIリファレンスにはでかでかとバージョン書いといてください


### `hitTest()`はイベント関連のクラスのを使ってね
> ### Using hitTest with Events

> With the new events system, one of the common APIs that changed is `hitTest.
>
> ```js
> import {Application} from 'pixi.js';
>
> const app = new Application();
> app.renderer.plugins.interaction.hitTest({x, y});
> ```
> 
> Now becomes:
> 
> ```js
> import {Application, EventBoundary} from 'pixi.js';
> 
> const app = new Application();
> const boundary = new EventBoundary(app.stage);
> boundary.hitTest(x, y);
> ```

`app.renderer.plugins.interaction.hitTest()`が廃止なのかどうかで話は変わりそう


### 次のメソッドはasyncになりました
> ### New Async Extract Methods
> The following methods are now async and return a Promise.
> 
> * CanvasExtract.base64()
> * CanvasExtract.image()
> * Extract.base64()
> * Extract.image()
> 
> ``` js
> import {Application, EventBoundary} from 'pixi.js';
> 
> const app = new Application();
> const dataUri = app.renderer.extract.base64();
> ```
> 
> Now becomes:
> 
> ```js
> import {Application, EventBoundary} from 'pixi.js';
> 
> const app = new Application();
> const dataUri = await app.renderer.extract.base64();
> ```

なるほど


### 皆が親しみのあるDOMの動作にあわせるため、親コンテナの外に出た場合には`xxxxmove`系イベントが持続しなくなる
> ### Interactive Move Events
> Interaction events in PixiJS now behave like the DOM in v7. This was intentional to align around behavior that would be familiar with developers, but obviously impacts the behavior with pointermove, mousemove, and touchmove.
> 
> Like the DOM, move events are now local. This means that if you are outside the bounds of the object, you will not receive a move event. Generally, you should consider adding move events to the stage or parent instead of the DisplayObject itself.
> 
> Working example: [https://jsfiddle.net/bigtimebuddy/spnv4wm6/](https://jsfiddle.net/bigtimebuddy/spnv4wm6/)

困る人がいそう


### プロパティにイベントハンドラ設定するのは廃止
> ### Interactive Property Handlers are Removed
> Property-based handlers were removed from events. This was a feature of the old InteractionManager. For instance:
> 
> ```js
> sprite.pointertap = () => {
>  // handler the pointertap
> };
> ```
> 
> Now becomes:
> 
> ```js
> sprite.on('pointertap', () => {
>  // handler the pointertap
> });
> ```



### `buttonMode`プロパティは廃止になりました もし嫌なら`DisplayObject`に生やし直したらいいよ
> ### The property buttonMode was a convenience for toggling the cursor property between pointer and null. It has now been removed.
> 
> ```js
> sprite.buttonMode = true;
> ```
> 
> Now becomes:
> 
> ```js
> sprite.cursor = 'pointer';
> ```
> 
> If you would like to re-add this functionality, you can [patch DisplayObject's prototype](https://jsfiddle.net/bigtimebuddy/ygka52dr/):
> 
> ```js
> import { DisplayObject } from 'pixi.js';
> 
> Object.defineProperty(DisplayObject.prototype, 'buttonMode', {
>   get() { return this.cursor === 'pointer'; },
>   set(value) { this.cursor = value ? 'pointer' : null; },
> });
> ```


## 古いv6からのアップグレードをお考えのあなたへ
> ##If you're planning on transitioning your code from v6, it would be helpful to implement some of the more dramatic changes in v6 first before upgrading to v7:
> 
> * Update to the latest v6.5.x
> * [Switch to the Events package](https://codesandbox.io/s/pixijs-uninstall-interaction-ke6u3q) by installing @pixi/events and swapping InteractionManager.
> 
> ```js
> import { InteractionManager, extensions, Application } from 'pixi.js';
> import { EventSystem } from '@pixi/events';
> 
> // Uninstall interaction
> extensions.remove(InteractionManager);
> 
> // Create the renderer or application
> const app = new Application();
> 
> // Install events
> app.renderer.addSystem(EventSystem, 'events');
> ``` 
>
> * Switch to the Assets package by installing @pixi/assets and swapping for Loader. For more information on implementing Assets, see this guide.
> * Set Graphics.nextRoundedRectBehavior = true, this uses arcs for corner radius instead of bezier curves.
> * Set Text.nextLineHeightBehavior = true, this defaults to the DOM-like behavior for line height.

v6の中でも劇的な変更があったためv7に切り替える前に最新版v6で下準備をしよう

* まず6系の最新(v6.5.x)にアップデートしよう
* `@pixi/events` をインストールして`InteractionManager`と置き換えよう ※ちなみに`@pixi/interaction`もv7に対応していない(`npm ERR!   peer @pixi/core@"6.5.0" from @pixi/interaction@6.5.0`)のでもしpackage.jsonにいたらv7に切り替える前にアンインストールしよう


* `@pixi/assets`をインストールして`Assets`で`Loader`を置き換えよう
* 残りの2つはよくわかりません


## プラグイン対応状況

ここみて
[v7 Migration Guide > Plugin Supported · pixijs/pixijs Wiki](https://github.com/pixijs/pixijs/wiki/v7-Migration-Guide#%EF%B8%8F-plugin-supported)

個人的に`pixi-sound`と`pixi-spine`が対応していてよかったです






#### おしまい