manmanrai’s diary

新米フロントエンジニアの勉強記録ブログ

2D WebGL renderer Pixi.js v4【連載第一回】

背景

いまどき大人気の2D WebGLを作れるjsライブラリーです。日本語のチュートリアルも少ないなので(2017年4月の現時点)、英語のチュートリアル(文末にリンク貼っておきます。)を読み、単語の意味調べながら、やりながらちょっとずつ勉強の記録書きます。

このチュートリアル55chatperありますが、頑張りたいと思います。

※ 注意:全てチュートリアル通り書かないので、いっぱいオリジナルを挟みます。予めご了承くださいませ。

Start with pixi.js

まず、pixi.jsを手に入れましょう。
でもこれは練習ですし、すぐ始めたいなので、CDNで読み込みタイプを選びます。

htmlを作ります。

<!DOCTYPE html>
<html lang="ja">
<head>
   <meta charset="UTF-8">
   <title>Start with pixi.js</title>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/4.4.3/pixi.min.js"></script>
<script type="text/javascript">
    var type = "WebGL";
    if(!PIXI.utils.isWebGLSupported()){
      type = "canvas"
    }
    PIXI.utils.sayHello(type);
</script>
</body>
</html>

bodyの中身要素入れてないので、
ローカルでhtmlファイルを開くと、予想通り何にも出ません。
consoleを開いてみます。

f:id:manmanrai:20170421184645p:plain

pixi.jsが読み込まれてる証拠ですね。

詳しくコードを読むと、WebGL対応しない場合にはCanvasに切り替えてくれるみたいです。
そして、コンソールで出たものはsayHello functionが機能してることです。
今使ってるブラウザはWebGL対応するChromeなので、typeはWebGLになってます。

何かを作ってみよう

以下のコードを先ほどのscriptの中(sayHello function後)に入れます。
コメントアウトで説明を入れました。)

// 新しいレンダラー作る
var renderer = PIXI.autoDetectRenderer(256, 256);

// それをHTMLファイルに入れる
document.body.appendChild(renderer.view);

// stageという名前の容器(オプジェクト)を作る
var stage = new PIXI.Container();

// レンダラーにstageを受け入れてって伝える
renderer.render(stage);

これがベイシックなコードらしいです。
ブラウザ開くと、黒いブロックが出てきました。
要素検証で中身を確認してみると

<canvas width="256" height="256" style="touch-action: none; cursor: inherit;"></canvas>

canvasが生成されてること確認できます。

autoDetectRenderer functionのパラメーター(parameters)を説明すると、
autoDetectRenderer(width, height, {options});

実はそのcanvasに対して色んなオプションがあります。
例えばこう書きます。

var renderer = PIXI.autoDetectRenderer(
  256, 256,
  {antialias: false, transparent: false, resolution: 1}
);
  • antialias 輪郭を滑らかにする?
  • transparent 透明させる? cssで[opacity: 0; ]を書くと同じです。
  • resolution 倍率 1は1xっていう意味で、0.5入れると生成されたcanvasのサイズは半分の128x128になります。

オプションなので、付けなくて大丈夫です。
デフォルトは上に書いてるように{antialias: false, transparent: false, resolution: 1}です。

強制的にWebGLcanvasだけを生成する

autoDetectRenderer functionは自動的にWebGLを対応できるかどうか判断して書き出しますが(WebGLの方が優先度高い)、
WebGL対応しないブラウザ諦めて非表示なっても構わない時、WebGLのみの書き方はこうなります。(WebGLRenderer function使います。)

renderer = new PIXI.WebGLRenderer(256, 256);

逆にどの状態でもcanvasで良い場合はこうです。(CanvasRenderer function使います。)

renderer = new PIXI.CanvasRenderer(256, 256);

style事情

renderer.backgroundColor = 0x061639;
renderer.view.style.border = "1px dashed black";

javascriptでスタイル指定したら、

<canvas width="256" height="256" style="touch-action: none; border: 1px dashed black; cursor: inherit;"></canvas>

こんなcanvasが生成されます。

そして、コードの途中でもリサイズできます。

renderer.autoResize = true;
renderer.resize(512, 512);

ブラウザ幅いっぱいもできます。(cssでreset入れた状態で)

renderer.view.style.position = "absolute";
renderer.view.style.display = "block";
renderer.autoResize = true;
renderer.resize(window.innerWidth, window.innerHeight);

スプライトってなんだろう

// 新しいレンダラー作る
var renderer = PIXI.autoDetectRenderer(256, 256);

// それをHTMLファイルに入れる
document.body.appendChild(renderer.view);

// stageという名前の容器(オプジェクト)を作る
var stage = new PIXI.Container();

// レンダラーにstageを受け入れてって伝える
renderer.render(stage);

次は三行目の説明に入ります。

var stage = new PIXI.Container();

container(オプジェクト)の意味通り、容器です。
色んな要素を入れられる容器です。

renderer.render(stage);

それを最初のrendererに渡して、canvasに反映します。
ここの命名(stage)はただの例なので、一般的にはscene(シーン)かroot(ルート)という名前しているらしいです。

じゃあ、その容器に何を入れるのかて言うと、「スプライト」みたいです。
スプライトはコントロールできる図形(images object)です。
位置、サイズ、インタラクティブなれるように、アニメーショングラフィックの設定などコントロールできるようなものです。

スプライトを作る三つの方法

  1. 画像を使う(個別一個一個を読み込む)
  2. プロジェクト内に使いたい全部の画像(sub-image)をまとめた大き画像(tileset)を使う(複数枚の画像を一枚にまとめるってこと)
  3. JSON(texture atlas)内で大き画像(tileset)中の個々の画像(sub-image)のサイズと位置を指定する

実践編

注意点:ここから作成したhtmlをローカルを開いても機能しないため、簡易サーバーを立ち上げて続きます。

1. 画像を使って表示させよう(個別一個一個を読み込む)前編

TextureCache functionを使って、画像のパスを保存します。そして新しいスプライトを立ち上げます。

var texture = PIXI.utils.TextureCache["images/anySpriteImage.png"];
var sprite = new PIXI.Sprite(texture);

ここの"images/anySpriteImage.png"を実際のルートと画像ファイル名と入れ替えます。
しかし、ルートを指定してもまだ読み込まれてませんので、ここでloaderを呼びます。

PIXI.loader
  .add("images/anyImage.png")
  .load(setup);

function setup() {
  //画像が読み込まれた後に実行する
}

pixi.jsの開発チームが推薦する使い方:もしloaderを使用する場合には、必ずloaderで読み込んだものをスプライトとして使用すること。

var sprite = new PIXI.Sprite(
  PIXI.loader.resources["images/anyImage.png"].texture
);

そして合体してみると、こうなります。

PIXI.loader
  .add("images/anyImage.png")
  .load(setup);

function setup() {
  var sprite = new PIXI.Sprite(
    PIXI.loader.resources["images/anyImage.png"].texture
  );
}

結果はこんな感じになります。
左上にぴったり貼られます。

f:id:manmanrai:20170424105344p:plain

補足:
読み込みたい画像を追加したい場合はloader.add()を追加すれば良いです。

PIXI.loader
  .add("images/imageOne.png")
  .add("images/imageTwo.png")
  .add("images/imageThree.png")
  .load(setup);

より簡潔に書きたい場合はloader.add([])でまとめても良いです。

PIXI.loader
  .add([
    "images/imageOne.png",
    "images/imageTwo.png",
    "images/imageThree.png"
  ])
  .load(setup);

Aliases(別名)に変えてみよう

先ほどのコードを整理してみると、こうなります。

<script>
var stage = new PIXI.Container(),
    renderer = PIXI.autoDetectRenderer(256, 256);
document.body.appendChild(renderer.view);

PIXI.loader
  .add("images/cat.png")
  .load(setup);

function setup() {
  var cat = new PIXI.Sprite(PIXI.loader.resources["images/cat.png"].texture);
  stage.addChild(cat);  
  renderer.render(stage);
}
</script>

ここのPIXI.***を全部取り出して、(分かりやすい)別名を作ります。

var Container = PIXI.Container,
    autoDetectRenderer = PIXI.autoDetectRenderer,
    loader = PIXI.loader,
    resources = PIXI.loader.resources,
    Sprite = PIXI.Sprite;

そしたら、コードを書き替えたらこうなります。スッキリなイメールに。

var stage = new Container(),
    renderer = autoDetectRenderer(256, 256);
document.body.appendChild(renderer.view);

loader
  .add("images/cat.png")
  .load(setup);

function setup() {
  var cat = new Sprite(resources["images/cat.png"].texture);
  stage.addChild(cat);
  renderer.render(stage);
}

第一回は一旦ここまで。

シリーズ:2D WebGL renderer Pixi.js v4

manmanrai.hatenablog.com

参考サイト

pixi.jsの公式サイト(英語)

www.pixijs.com

参考しているチュートリアル(英語)

github.com