はじめに
この記事では、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に追加するのと同じように、
DisplayElement
をlayer
として生成 - そこに描画したいShapeを追加していく
- 前回記事と同様にShapeは自分で
render()
を実行する -
CanvasRenderer
でlayer
をrenderObject
する
// 画像用にあたらしい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
として用意する必要もないですし、いつもMainScene
のinit
で書いてるコードの感覚でやったあとに、自分で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を自分で描画しなくても良くなったことですね。
これは、CanvasApp
がUpdater
という、phina.jsの更新用オブジェクトで、更新してくれるからです。(_update()
)
ここまで、来ると逆に複雑なので、一番わかり易いのはDisplayScene
でのやり方だと思います。
おわりに
個人的には、DisplayScene辺りから画像化するのが、楽な印象です。
CanvasAppを使う場合は、よっぽど複雑な状態のSceneの内容を描画する場合などでしょうか。
まあ、あんまりここまで、まとめて画像化するのはやりませんけどねw
質問、要望等は遠慮なくどうぞ