LoginSignup
5
3

More than 5 years have passed since last update.

phina.jsのShapeを複数まとめて画像として使う

Posted at

はじめに

この記事では、phina.jsのv0.2を使用しています。
https://cdn.rawgit.com/phi-jp/phina.js/v0.2.0/build/phina.js

この記事の続編です
phina.jsのShapeを画像として使う

あと、Shapeじゃなくても、画面に描画されているもの全てを画像にする事ができます。

普通のやり方

サンプル
http://runstant.com/simiraaaa/projects/shapeToImageRenderer
クリックすると、imgタグで追加されたり、Spriteで画面に追加されたりします。
流れだけ説明すると。

  • Canvasのラッパーオブジェクトを作成
  • CanvasRendererのレンダリング対象に設定
  • Sceneに追加するのと同じように、DisplayElementlayerとして生成
  • そこに描画したいShapeを追加していく
  • 前回記事と同様にShapeは自分でrender()を実行する
  • CanvasRendererlayerrenderObjectする

// 画像用にあたらしいCanvasを作る
var canvas = phina.graphics.Canvas();
canvas.setSize(640, 960);

// CanvasRenderer を生成する
var renderer = CanvasRenderer(canvas);

// 何もないオブジェクトを生成
var layer = DisplayElement();

// 星を100個ランダムに layerに追加
(100).times(function(i){
  var star = StarShape({
    // 色をカラフルに
    fill: 'hsla(' + (i * 3.6) + ', 80%, 60%,  1)',
    x: Math.randint(0, canvas.width),
    y: Math.randint(0, canvas.height),
  }).addChildTo(layer);

  // 星自体の描画
  star.render(star.canvas);
});

// layerの中身を canvasに描画
renderer.renderObject(layer);


これでレンダリングが終わったので、画像として取得します。

最初に生成したCanvasラッパーオブジェクトのdomElementプロパティが実際のCanvasです。
canvas.domElement

あとはサンプルのように好きなようにいじってください。

Spriteとして扱うときは、生成したCanvasラッパーオブジェクトをそのまま渡してインスタンス化すれば良いです。
Sprite(canvas)

ちょっと楽なやり方

サンプル
http://runstant.com/simiraaaa/projects/shapeToImageDisplayScene

流れ

  • DisplaySceneオブジェクトをsceneとして生成
  • さっきの layerにShapeを追加していく感覚で好きなように追加していく
  • Shape自体のレンダリングも忘れずにやる
  • scene._render()を実行する

// 画像用にあたらしいDisplaySceneを作る
var scene = DisplayScene({
  width: 640,
  height: 960,
  backgroundColor: 'rgba(0, 0, 64, 0.2)',
});

// 星を100個ランダムに scene に追加
(100).times(function(i){
  var star = StarShape({
    // 色をカラフルに
    fill: 'hsla(' + (i * 3.6) + ', 80%, 60%,  1)',
    x: Math.randint(0, scene.width),
    y: Math.randint(0, scene.height),
  }).addChildTo(scene);

  // 星自体の描画
  star.render(star.canvas);
});

// sceneの内容を描画
scene._render();

これで、描画できました。
CanvasRendererを使う方法との違いは、自分でCanvasとCanvasRendererオブジェクトを生成しなくて良くなる点ですね。あとDisplayElementをlayerとして用意する必要もないですし、いつもMainSceneinitで書いてるコードの感覚でやったあとに、自分でscene._render()を呼ぶだけです。

最初のコードと同様にCanvasラッパーオブジェクトを取得する場合はscene.canvas
Canvas自体を取得するにはscene.canvas.domElementでできます。

なぜ、CanvasRendererとCanvasラッパーオブジェクトの生成を省略できたのかというと、DisplaySceneがシーンの内容を描画するために、init内で生成しているからです。
最初から準備してくれているので、あとはそこに追加して、描画メソッドを呼ぶだけできるということです。

CanvasApp を使う方法

サンプル
http://runstant.com/simiraaaa/projects/shapeToImageCanvasApp

流れ

  • CanvasAppのインスタンスを生成(append:false)
  • sceneの取得(app.currentScene)
  • Shapeを生成して、sceneに追加(Shapeを自分で描画する必要はない)
  • app._update()で追加したShapeの事前描画を一気に実行する
  • app._draw()sceneの内容を描画する

// 画像用にあたらしいCanvasAppを作る
var app = CanvasApp({
  width: 640,
  height: 960,
  // app の場合は backgroundColorを設定してもsceneのcanvasに直接反映されない
  //backgroundColor: 'rgba(0, 0, 64, 0.2)',
  // append を false にしないと bodyに自動的にcanvasが追加されてしまう!
  append: false,
});

// app のシーンを取得
var scene = app.currentScene;
scene.backgroundColor = 'rgba(0, 0, 64, 0.2)';

// 星を100個ランダムに scene に追加
(100).times(function(i){
  var star = StarShape({
    // 色をカラフルに
    fill: 'hsla(' + (i * 3.6) + ', 80%, 60%,  1)',
    x: Math.randint(0, scene.width),
    y: Math.randint(0, scene.height),
  }).addChildTo(scene);

  // 星自体の描画しなくても良い(あとでアップデートする)
  // star.render(star.canvas);
});

// app更新
app._update();
// appの中身描画
app._draw();

このあとは、DisplaySceneのやり方と同じです。
DisplaySceneでやる方法の違いは、Shapeを自分で描画しなくても良くなったことですね。
これは、CanvasAppUpdaterという、phina.jsの更新用オブジェクトで、更新してくれるからです。(_update())

ここまで、来ると逆に複雑なので、一番わかり易いのはDisplaySceneでのやり方だと思います。

おわりに

個人的には、DisplayScene辺りから画像化するのが、楽な印象です。
CanvasAppを使う場合は、よっぽど複雑な状態のSceneの内容を描画する場合などでしょうか。
まあ、あんまりここまで、まとめて画像化するのはやりませんけどねw
質問、要望等は遠慮なくどうぞ

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3