【Three.js】アニメーションのあるcanvasをテクスチャにして読み込む

2016年12月15日

前にcanvasの表示ができたので、次にアニメーションの表示をしたい。

[参照] ポイントに合わせてcanvas表示

まずはcanvasアニメーションの表示

順序は
【1】canvasで作ったテクスチャをステージ置く
【1-2】テクスチャ作成
【2】canvasアニメーションを作る
【3】読み込んでアニメーション

くらいになるのではないかと思う。

【1】canvasで作ったテクスチャをステージ置く

まずいきなりココで詰まった。
addしてる気持ちでもステージになにも出てこない。。。
結論はplaneMesh.material.map.needsUpdate = true;がなかったのですが。この子大事ですね。

とりあえず順を追って。

【1-2】テクスチャ作り

今回は最終的にアニメーションでテキストでぐるぐる系作りたいのと、テキストをどう入れるのかお勉強も兼ねてこんなかんじ。
これで

の中にcanvasタグが生成されます。

//キャンバステクスチャ作り
function set_texture() {

  canvas = document.createElement('canvas');
  canvas.width = 64;
  canvas.height = 32;
  textContext = canvas.getContext('2d');
  textContext.font = "20px 'MS Pゴシック'";

  textContext.fillStyle = "rgb(200, 30, 100)";
  textContext.fillText("ぶははは", 0, 20);
  //[あとで追加]ここでテクスチャに変換->リターン
  //texture = new THREE.Texture(canvas);
  //return texture;
}

returnされたテクスチャとplaneGeometoryでMeshを作成する。
MeshBasicMaterialを作るときに[map:set_texture()]として、さっき作ったヤツがreturnで入る。

  /*  メッシュ作り */
  var geometry = new THREE.PlaneGeometry(6.4, 3.2, 10, 10);
  var material = new THREE.MeshBasicMaterial({
    map: set_texture()//ここに作ってreturnされたtexutureが入る
  });

  planeMesh = new THREE.Mesh(geometry, material);
  planeMesh.material.map.needsUpdate = true;
  scene.add(planeMesh);

なんかでた。

codepen

See the Pen canvas をテクスチャにする_1 by ziyudom (@ziyudom) on CodePen.

【2】canvasアニメーションを作る

次は今回は文字を右から左に流れてく感じのをサンプル作る。
render関数を作る。

var textX = 0;//アニメーション用テキスト位置

function render(){
  window.requestAnimationFrame(render);//グルグルまわる
  textX--;//位置を更新
  if (textX < -100) {
    textX = 100;//適当に行きすぎたらもどってきてーってやつ
  }
  //緑にする
  textContext.fillStyle = "rgb(40, 233, 100)";
  //その緑を塗る
  textContext.fillRect(0, 0, 100, 100);
  //黒にする
  textContext.fillStyle = "rgb(0, 0, 0)";
  //その黒で書く
  textContext.fillText("ぶはははは", textX, 20);

  renderer.render(scene, camera);//レンダリング更新
};
&#91;/js&#93;


アニメーション部分
canvasは一回ベタで塗り直して、改めて文字を描画する感じなので、こんな感じでやってみた。
 
&#91;js&#93;
function looprender() {
  window.requestAnimationFrame(looprender);

  textX--;
  if (textX < -100) {
    textX = 100;
  }
  
  textContext.fillStyle = "rgb(40, 233, 100)";
  textContext.fillRect(0, 0, 100, 100);
  textContext.fillStyle = "rgb(0, 0, 0)";
  textContext.fillText("ぶはははは", textX, 20);

  renderer.render(scene, camera);
}
&#91;/js&#93;

恐らく上の方に「テクスチャ」とか書いてあってアニメーションしてるはず。

<p data-height="300" data-theme-id="17145" data-slug-hash="pNQzXG" data-default-tab="js,result" data-user="ziyudom" data-embed-version="2" data-pen-title="canvas をテクスチャにする_1" class="codepen">See the Pen <a href="http://codepen.io/ziyudom/pen/pNQzXG/">canvas をテクスチャにする_1</a> by ziyudom (<a href="http://codepen.io/ziyudom">@ziyudom</a>) on <a href="http://codepen.io">CodePen</a>.</p>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>

<h3>【3】読み込んでアニメーション</h3>

次に板を作ってそこに貼り付ける。
テクスチャを作ると言っても、さっきのset_texture関数にnew THREE.Texture(canvas)で作ったやつをリターンするようにセットしたらあとはほとんどいつも通り。

[js]
//キャンバステクスチャ作り
function set_texture() {

  //テクスチャ
  canvas = document.createElement('canvas');
  canvas.width = 64;
  canvas.height = 32;
  textContext = canvas.getContext('2d');
  textContext.font = "20px 'MS Pゴシック'";

  textContext.fillStyle = "rgb(200, 30, 100)";
  textContext.fillText("札幌", 0, 20);

  $(".hoge")[0].appendChild(canvas);

//↓ここ追加した
  texture = new THREE.Texture(canvas);
  return texture;
}

メッシュ作成部分


var geometry = new THREE.PlaneGeometry(6.4, 3.2, 10, 10);
var material = new THREE.MeshBasicMaterial({
  map: set_texture(),//ここでさっき作った関数からのリターンされたテクスチャが入る。
  transparent: true,
});
planeMesh = new THREE.Mesh(geometry, material);

//ここら辺ただの調整
planeMesh.position.z = -1;
planeMesh.rotation.y = 20;
planeMesh.doubleSided = true;

scene.add(planeMesh);

こんな感じ

てかメインのステージのやつ動いてなくね?
ってなったんですが、それがplaneMesh.material.map.needsUpdateアップデート。
これをmaterialのmapで毎回trueにするっぽい。
なんでtureなんだろ。そしてなんで毎回なんだろう。
そんな疑問も素人からするとあるけど。
とりあえずここれそのMeshのmaterialをアップデートできます。

function render(){
window.requestAnimationFrame(render);
textX–;
if (textX < -100) { textX = 100; } textContext.fillStyle = "rgb(40, 233, 100)"; textContext.fillRect(0, 0, 100, 100); textContext.fillStyle = "rgb(0, 0, 0)"; textContext.fillText("ぶはははは", textX, 20); /*ここね!*/ planeMesh.material.map.needsUpdate = true; renderer.render(scene, camera); } [/js] はははははーやったー

でけた

See the Pen canvas をテクスチャにする_2 by ziyudom (@ziyudom) on CodePen.

canvasがテクスチャになるならなんでも出来る気がする

そんな気がするんだけど。
まぁそもそもそんな技術がないという事実もあるので。
焦らずゆっくりでもお勉強が必要です。