【PixiJS 覚書】第一回 PIXI.ApplicationとPIXI.Container

##前書き
FLASH亡き後のWebにおけるリッチUIの希望の星、PixiJS。（私見）
一方、その割には何故かなかなか日本語ドキュメントが増えないねーという面もあり、ならば自身の学習内容の整理も兼ねて、要点を簡潔にまとめたものを書いてしまおうというのが本記事の主旨です。

方針は
「深さや広さは追わない。とにかく簡潔に、基本となる部分だけ抜き出す」
「なので、nodeやDOM、TypeScriptの領域には踏み込まない。**PixiJSのことだけ**を書く」
です。
後から自分が「えーとアレどうなってたっけ？」と振り返る際の取っ掛かりとなる早見表のようなものを目指します。

よって、この記事では「そもそもPixiJSって何？」などの概論は扱いません。
もしその辺が必要であれば事前に以下の記事を読んでおくことをお勧めします。

[初心者による超初心者のためのPixiJS入門](https://qiita.com/chiisanwo/items/f22caabc89ed8a6c41de)

また、PixiJSはバージョン毎にけっこう色々と変わっている部分があり、当記事執筆時点（2021/12/06）ではv6.2.0が最新バージョンとなっています。
当記事では私の個人的都合により**v5**に基づいて記述します。

##PixiJSに触れる上で手元に置いておきたい物
本題に入る前に、まずは教科書とノートになるものを用意。

(1)[PixiJS API Documentation](https://pixijs.download/dev/docs/index.html)
何はなくともまずはリファレンスです。
ちなみにこのリファレンスはあくまで「API Documentation」であり、外部からのアクセスを前提としたAPIのみが記載されているようです。
当たり前と言えば当たり前なんですが、Pixi内部のコードを追っていると、このドキュメントには記載のないメソッドが出てきてアレ？となったので、一応そういうもんだと頭の片隅に置いておきましょう。
(2)[PixiPlayground](https://pixiplayground.com/)
自身で環境構築せずともブラウザ上でPixiJSを実際に動かして動作を確認できます。
クラスやメソッドの各機能の確認には最適です。
(3)[PixiJS Examples](https://pixijs.io/examples/)
各機能がどのような物でどう見えるかのデモとサンプルコードです。
ざっくりとでもPixiの基本構造を把握してしまえば、後は自力でこのサンプルを読み解いていく方がむしろ早いかもしれません。

##ここから本題
PixiJSという大きなライブラリの全体像を一つの記事で浚うのはさすがに無理があるので、何回かに分割します。
全何回になるのかは今のところ考えていません。見切り発車バンザイ。

第一回はPixiJSがどのようにして描画オブジェクトを管理し、画面に表示しているのか、描画の基本のキを見ていきます。

以下、今回のサンプルコード。
上記のPlaygroundのデフォルトのコードを少し弄った物です。

```JavaScript:
// Create our application instance
var app = new PIXI.Application({
    width: 400,
    height: 300,
    backgroundColor: 0x1199aa
});
document.body.appendChild(app.view);

// Load the bunny texture
app.loader.add('bunny', 'https://pixijs.io/examples/examples/assets/bunny.png')
    .load(drawBunny);

function drawBunny()
{
    var bunny = new PIXI.Sprite(app.loader.resources.bunny.texture);

    // Center the sprite's anchor point
    bunny.anchor.set(0.5);

    // Move the sprite to the center of the screen
    bunny.x = app.renderer.width / 2;
    bunny.y = app.renderer.height / 2;

    app.stage.addChild(bunny);
}
```

##PIXI.Application
ではサンプルコードを順に追っていきます。

```JavaScript:
const app = new PIXI.Application({
    width: 800,
    height: 600,
    backgroundColor: 0x1099bb
});
```
PixiJSの機能の諸々はPIXI.Applicationに詰め込んであるので、まずはそれを扱えるようにインスタンス化しています。
コンストラクタの引数には各設定を記述したオブジェクトを渡しており、今回は幅、高さ、背景色だけ指定しています。
他に何が設定できるかはリファレンスを参照してください。
（[リファレンス：PIXI.Application](https://pixijs.download/dev/docs/PIXI.Application.html)）

**要点１「PixiJSはPIXI.Applicationをインスタンス化して使用する」**

##view
PIXI.Applicationをインスタンス化した次は、そのプロパティである`view`をHTMLのbody要素に`appendChild`しています。

```JavaScript:
document.body.appendChild(app.view);
```

さて、`view`が出てきました。
PIXI.Applicationは`view`他、以下のような機能をプロパティとして持っています。

|名前|機能|クラス|
|:-:|:-:|:-:|
|view|実際に画面に表示されるcanvas要素|HTMLCanvasElement|
|stage|viewに表示される描画オブジェクトのコンテナ|PIXI.Container|
|screen|viewの大きさなどの情報を持ったRectangle|PIXI.Rectangle|
|（以下は今回は<br>扱わない）|||
|ticker|描画物のupdateループを担う|PIXI.Ticker|
|loader|ファイル読み込みと管理|PIXI.Loader|
|renderer|WebGLのレンダラ|PIXI.Renderer|
|resizeTo|viewの自動リサイズの<br>基準となるHTML要素|Windowまたは<br>HTMLElement|

今回あつかうのは上の３つ、中でもview、stageが主題です。

そしてサンプルコードではその`view`をなんとHTMLドキュメントのbody要素に突っ込んでいます。
というのも、`view`の正体はHTMLCanvasElementであり、PixiJSでなんやかんやした物は結局すべてこの`view`（その正体はcanvas要素）に描画されるわけです。

**要点２「PixiJSのviewプロパティはHTMLのcanvas要素であり、PixiJSの描画物は全てこのview（canvas要素）に描き出される」**

##screen
サンプルコード内には出てきていませんが、ここで`screen`プロパティにも軽く触れておきます。
`screen`の中身はPIXI.Rectangleオブジェクトであり、Rectangleという名前の通りｘ、ｙ、width、heightなどの四角形を形作る情報を持っています。
`app.screen`は`app.view`の大きさ等の情報を管理しており、今回の場合、コンストラクタの引数として渡した「width:400, height:300」の値はここに保持されています。

##（途中の処理）
「app.loader.add() ～ app.renderer.height / 2;」までは今回の主題から外れるので概要だけ箇条書きにして端折ります。

・バニーさんの画像を非同期で読み込んで、読み込み終了次第、`drawBunny`をコール
・`drawBunny`では読み込んだ画像をスプライトとして座標の基準位置を画像中央にセット、表示位置を画面の中央とする。

`PIXI.Loader`や`PIXI.Sprite`についてはまた別途、記事を設けるつもりです。
今のところは「変数`bunny`にはバニーさんの画像がスプライトとして入っている」という点だけ認識して次に進みます。

##stage（PIXI.Container）
**今回の主題。**

```JavaScript:
    app.stage.addChild(bunny);
```
`stage`が出てきました。
PIXI.Applicationの`stage`に、バニーさんのスプライトを`addChild`しています。
`stage`は`PIXI.Container`クラスのインスタンスであり、名前の通り、PixiJSの描画物をまとめて詰め込む入れ物（コンテナ）です。
（[リファレンス：PIXI.Container](https://pixijs.download/dev/docs/PIXI.Container.html)）

この`stage`に描画したいオブジェクトを`addChild`していくことで、描画物が`view`に描画されるようになります。

**要点３「PIXI.Applicationの`stage`プロパティはPIXI.Containerクラスのインスタンスであり、この`stage`（PIXI.Containerインスタンス）に描画物を`addChild`することで`view`への描画が行われる」**

##PIXI.Containerについてもう少し（PIXI.DisplayObject）
今、「描画したいオブジェクト」「描画物」とさらっと書きましたが、これらは具体的に何でしょうか。
たとえばHTMLのimg要素（HTMLImageElement）をPixiJS上で使いたいからと`stage`に`addChild`すれば、`view`に表示されるのでしょうか？

答えはNoです。

PIXI.Containerに`addChild`できる物は「PIXI.DisplayObject」です。
（[リファレンス：PIXI.DisplayObject](https://pixijs.download/dev/docs/PIXI.DisplayObject.html)）

PIXI.DisplayObjectには様々な種類の派生クラスが用意してあり、たとえば図形を描画したければ「PIXI.Graphics」の、テキストを描画したければ「PIXI.Text」のインスタンスをそれぞれ生成して`app.stage`に`addChild`する、という具合です。

PIXI.DisplayObject継承クラスの中から特に基本的な部分をクラスツリーとして列挙してみます。

**[PIXI.DisplayObject関連クラスツリー]**（あくまで一部、詳細はリファレンス参照）
・PIXI.DisplayObject（描画物の基本クラス）
　・PIXI.Container（コンテナ）
　　・PIXI.Graphics（図形）
　　・PIXI.Sprite（スプライト）
　　　・PIXI.Text（テキスト（ベクターフォント））
　　　・PIXI.AnimatedSprite（アニメーションするスプライト）
　　・PIXI.BitmapText（テキスト（ビットマップフォント））

さて、ここで特に注目すべきなのは「PIXI.Container」が「PIXI.DisplayObject」の派生クラスであり、また、その他の描画物が「PIXI.Container」の派生クラスという点です。

つまり`stage`に更にコンテナを`addChild`したり、描画物に更に描画物を`addChild`して入れ子構造にできるわけです。
そしてそのように入れ子構造になったPIXI.DisplayObjectは、まとめて`app.view`に描画されます。

**要点４「PIXI.Containerに`addChild`できる物はPIXI.DisplayObjectである」**

**要点５「PIXI.Container自身もPIXI.DisplayObjectの派生クラスであり、また、各描画物はPIXI.Containerクラスの派生クラスである。
　　　　結果、コンテナと各描画物は入れ子構造にでき、入れ子になった描画物全てが`view`に描画される」**

##図にしましょう
少しややこしくなってきたので、ここで一度、図で整理してみましょう。
なお、サンプルコードではスプライト１個しか描画していませんが、下記の図ではコンテナの入れ子構造の一例ということで`stage`にコンテナやスプライト、テキスト等が複数addChildされています。
![pixi_sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107226/bae2d768-974b-dfc9-179b-faa231ee6b11.png)

##サンプルコードの実行結果
また、サンプルコードをPlaygroundで実行した結果も見ておきましょう。
![bunny.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107226/8212acea-cf57-4c9b-d113-f44ac62918fd.png)
400×300のviewの中央にバニーさんのスプライトが表示されていますね。

##今回のまとめ
**要点１「PixiJSはPIXI.Applicationをインスタンス化して使用する」**

**要点２「PixiJSのviewプロパティはHTMLのcanvas要素であり、PixiJSの描画物は全てこのview（canvas要素）に描き出される」**

**要点３「PIXI.Applicationの`stage`プロパティは`PIXI.Container`クラスのインスタンスであり、この`stage`（PIXI.Containerインスタンス）に描画物を`addChild`することで`view`への描画が行われる」**

**要点４「PIXI.Containerに`addChild`できる物はPIXI.DisplayObjectである」**

**要点５「PIXI.Container自身もPIXI.DisplayObjectの派生クラスであり、また、各描画物はPIXI.Containerクラスの派生クラスである。
　　　　結果、コンテナと各描画物は入れ子構造にでき、入れ子になった描画物全てが`view`に描画される」**


---
今回はここまで。

次回はPIXI.Graphicsを実際に使いながら、描画処理のパターンに慣れていきます。