サイトトップ

Director Flash 書籍 業務内容 プロフィール
 

HTML5 / Flash ActionScript講座
ActionScript 3.0
プロフェッショナルガイド
ActionScript 3.0による
三次元表現ガイドブック
■Twitter: @FumioNonaka / Facebook Page: CreateJS

JaGra PROFESSIONAL SCHOOL Seminar

CreateJSでHTML5向けのJavaScriptコーディングをしよう

Date: 2012年11月8日 Technique: HTML5 and JavaScript


本稿は、2011年11月8日木曜日に同名で開かれたセミナーの概要を伝える目的で公開する。

CreateJS Suiteは、リッチでインタラクティブなコンテンツをつくるJavaScriptライブラリ群だ。各ライブラリは、予めCreateJSサイトからダウンロードしてインストールしておかなければならない。その手順については、「EaselJSで図形を描く」を参照してほしい。


01 EaselJSのアニメーション

01-01 canvas要素を定める

canvas要素をbody要素の中に書くと、透明な領域が定められ、JavaScriptで図形が描ける。widthとheight属性で幅と高さを決め、id属性を加えるとJavaScriptでcanvas要素が取出せる。

<canvas id=canvas要素名 width=幅 height=高さ>

新たなHTMLドキュメントのbody要素の中に、canvas要素を書き加える(図001)。幅と高さをそれぞれwidthとheight属性に与え、id属性も定めた(コード001)。

図001■新たなHTMLドキュメントにcanvas要素を書き加える
図001

コード001■canvas要素にid属性および幅と高さを定める
  1. <canvas id="myCanvas" width="240" height="180"></canvas>

01-02 canvas領域にJavaScriptで矩形を描く

canvas要素で定めた領域に、JavaScriptで矩形を描く。描画はcanvas要素から得られるコンテクストというオブジェクトに対して行う。まず、canvas要素をdocument.getElementById()メソッドで取する。

element = document.getElementById(エレメントID)

つぎに、コンテクストの参照を得るにはgetContext()メソッドを呼出す。このとき、2次元の描画をする2Dコンテクストが必要なので、メソッドの引数には"2d"を渡す。

context2D = canvasElement.getContext("2d")

そして、この2Dコンテクストに対して描画のためのメソッドを呼出します。塗りの矩形を描くのが、fillRect()メソッドだ。xy座標、および幅と高さの4つの引数を渡す。

2Dコンテクスト.fillRect(x座標, y座標, 幅, 高さ)

塗りの矩形を描く関数(xDraw())は、つぎのコード002のように定められる。xy座標は(10, 10)、幅100×高さ100ピクセルの正方形を描く。なお、塗り色のデフォルトは黒になる。

コード002■塗りの矩形を描く関数
  1. function xDraw() {
  2.   var canvasElement = document.getElementById("myCanvas");
  3.   var context2D = canvasElement.getContext("2d");
  4.   context2D.fillRect(10, 10, 100, 100);
  5. }

この関数をページが読込み終わったときに呼出すには、body要素のイベント属性(イベントハンドラ)onloadに設定します(コード003)。これで、canvas要素で定めた領域に矩形を描くコードができ上がりました(図002)。

コード003■関数をonloadイベント属性に定める
  1. <body onload="xDraw()">

ブラウザで確かめると、左上角座標(10, 10)の位置に幅100×高さ100ピクセルの黒い正方形が描かれる(図002)。

図002■左上角座標(10, 10)に100ピクセル四方の黒い正方形が描かれた
図002


01-03 EaselJSで星形を描く

EaselJSは表示リストを備える。その頂点のStageオブジェクトをつくらなければならない。Stageクラスのコンストラクタには、引数としてcanvas要素の参照を渡す。

new Stage(canvas要素)

そして、EaselJSライブラリのJavaScript(JS)ファイルを読込む(本稿ではHTMLドキュメントと同じ場所のlibフォルダに入れている)。まずはStageオブジェクトをつくるまでのコードは、つぎのとおりだ(行番号は、後にscript要素全体を掲げるコード004にもとづく)[*1]

  1. <script>
  2. var createjs = window;
  3. </script>
  4. <script src="lib/easeljs-0.5.0.min.js"></script>
  5. <script>
  6. var stage;
  7. function xInitialize() {
  8.   var canvasObject = document.getElementById('myCanvas');
  9.   stage = new Stage(canvasObject);
  1. }
  1. </script>

Stageオブジェクトの表示リストに、描画のためのオブジェクトをひとつ加える。Flashと同じShapeというオブジェクトがあり、描画用のメソッドが使える。Shapeオブジェクトをつくって、Container.addChild()メソッドで表示リストに加え、その座標を定めるスクリプトはつぎのとおりだ。

  1. function xInitialize() {
  1.   xDraw();
  2. }
  3. function xDraw() {
  4.   var myShape = new Shape();
  1.   stage.addChild(myShape);
  2.   myShape.x = 50;
  3.   myShape.y = 50;
  1. }

描画に用いるのはGraphicsオブジェクトで、ShapeオブジェクトのShape.graphicsプロパティから参照が得られる。描画の色を決めるメソッドは、塗りがGraphics.beginFill()、線はGraphics.beginStroke()だ。引数のカラーはHTMLと同じ文字列で渡す。星形はGraphics.drawPolyStar()メソッドで描く。Canvasに描画するには、最後にStage.update()メソッドを呼出さなければならない。

  1. function xDraw() {
  2.   var myShape = new Shape();
  3.   var myGraphics = myShape.graphics;
  1.   myGraphics.beginStroke("#0000FF");
  2.   myGraphics.beginFill("#00FFFF");
  3.   myGraphics.drawPolyStar(0, 0, 40, 5, 0.6, -90);
  4.   stage.update();
  5. }

Graphics.drawPolyStar()メソッドは、つぎのように6つの引数をとる。

Graphicsオブジェクト.drawPolyStar(x座標, y座標, 半径, 頂点数, 谷の深さ, 起点角)

第1および第2引数が中心のxy座標、第3引数は中心から頂点までの半径、そして第4引数が頂点の数になる。第5引数は谷の深さで、0以上1未満の数値で定める。デフォルト値の0を渡すと谷はなくなり、正多角形になる(図003)。第6引数はデフォルト値0では、星形がx軸の正方向つまり時計の3時の方向を起点に描かれる。y軸の負つまり時計の12時の方向から描くには、-90度を起点の角度とする。

図003■異なる谷の深さで描かれた5頂点の星形

図003左
0.8

図003中央
0.6

図003右
0

これで、中心座標(0, 0)の位置に半径40ピクセルで5頂点の星形が描かれる(図004)。script要素全体は、つぎのコード004のとおりだ。

図004■Graphics.drawPolyStar()メソッドで描かれた5頂点の星形
図004

コード004■EaselJSでCanvasに星形を描く
  1. <script>
  2. var createjs = window;
  3. </script>
  4. <script src="lib/easeljs-0.5.0.min.js"></script>
  5. <script>
  6. var stage;
  7. function xInitialize() {
  8.   var canvasObject = document.getElementById('myCanvas');
  9.   stage = new Stage(canvasObject);
  10.   xDraw();
  11. }
  12. function xDraw() {
  13.   var myShape = new Shape();
  14.   var myGraphics = myShape.graphics;
  15.   stage.addChild(myShape);
  16.   myShape.x = 50;
  17.   myShape.y = 50;
  18.   myGraphics.beginStroke("#0000FF");
  19.   myGraphics.beginFill("#00FFFF");
  20.   myGraphics.drawPolyStar(0, 0, 40, 5, 0.6, -90);
  21.   stage.update();
  22. }
  23. </script>

[*1] 最新のCreateJSのライブラリは、名前空間「createjs」が定められた。そのため、前掲コード004でも、たとえばStageインスタンスを生成するステートメント(第9行目)は、デフォルトではつぎのように書かなければならない。

  1. stage = new createjs.Stage(canvasObject);

この仕様変更は、過去のスクリプトとの互換性に問題が生じ、今の段階では学習にも不便がある。そこで、当面つぎのscript要素により互換性を保った(詳しくは「CreateJS Suiteのクラスに名前空間が設定される」参照)。

  1. <script>
  2. var createjs = window;
  3. </script>

01-04 EaselJSを使ったスクリプトによるアニメーション

EaselJSではTickerクラスが、決まった間隔でTicker.tickイベントを送る。静的メソッドTicker.addListener()でリスナーオブジェクトを登録すれば、そのオブジェクトに定めたメソッドtick()が一定間隔で呼出される。

Ticker.addListener(リスナーオブジェクト)

前掲コード004にTickerクラスによるアニメーションの仕組みを加え、Canvasに描いた星形を回したのが後に掲げるコード005だ。新たに加えたスクリプトをつぎに抜書きした。まず、インスタンスを描く関数(xDraw())にTicker.addListener()メソッドの呼出しを加えた(第18行目)。引数のリスナーはwindowオブジェクトとした。

tick()関数では、星形のShapeオブジェクトをDisplayObject.rotationプロパティで回している(第21行目)。プロパティ値の単位は度数だ。なお、この関数からShapeオブジェクトを扱えるよう、変数(myShape)は関数の外で宣言した(第2行目)。そして、tick()関数の最後には、必ずStage.update()メソッドを呼出す(第31行目)。これで、Canvasに描いた星形が回るアニメーションのできあがりだ(図005)。

  1. var myShape;
  1. function xDraw() {
      // var myShape = new Shape();
  2.   myShape = new Shape();
  1.   Ticker.addListener(window);
  2. }
  3. function tick() {
  4.   myShape.rotation += 5;
  5.   stage.update();
  6. }

図005■Canvasに描いた星形が回る
図005左 図005右

コード005■EaselJSでCanvasに描いた星形を回す
  1. var stage;
  2. var myShape;
  3. function xInitialize() {
  4.   var canvasObject = document.getElementById('myCanvas');
  5.   stage = new Stage(canvasObject);
  6.   xDraw();
  7. }
  8. function xDraw() {
  9.   myShape = new Shape();
  10.   var myGraphics = myShape.graphics;
  11.   stage.addChild(myShape);
  12.   myShape.x = 50;
  13.   myShape.y = 50;
  14.   myGraphics.beginStroke("#0000FF");
  15.   myGraphics.beginFill("#00FFFF");
  16.   myGraphics.drawPolyStar(0, 0, 40, 5, 0.6, -90);
  17.   stage.update();
  18.   Ticker.addListener(window);
  19. }
  20. function tick() {
  21.   myShape.rotation += 5;
  22.   stage.update();
  23. }

02 スプライトシートからつくるアニメーション

02-01 SpriteSheetとBitmapAnimationクラスの使い方

スプライトシートは、アニメーションの複数フレームをひとつの画像ファイルにまとめたものだ(図006左図)。そのとき、EaselJSではフレームごとの画像の大きさ(幅×高さ)をすべて揃えると扱いやすい(図006右図)[*2]。この画像ファイル(sprite_sheet.png)を、HTMLドキュメントと同じ場所のフォルダ(images)に入れておく。

図006■フレームの画像をまとめたスプライトシート
図006左
スプライトシート全体
  図006右
フレームごとの大きさを揃える

まず、SpriteSheetクラスのコンストラクタでインスタンスをつくる。そして、引数に渡すObjectインスタンスに、スプライトシートから切り出して再生するアニメーションの情報をプロパティとして与える。必要なプロパティは、imagesとframes、およびanimationsの3つだ。

imagesプロパティは配列で、スプライトシートに用いる画像ファイルのURIをエレメントに加える。framesプロパティには、切り出すイメージの幅(width)と高さ(height)、および基準点のxy座標(regXとregY)などをObjectインスタンスとして定める。animationsプロパティにはObjectインスタンスを与え、そのプロパティはアニメーションの名前で、再生するフレームの開始と終了のインデックス番号を配列に入れて定める。インデックスは0から始まる整数だ。さらに、配列エレメントとして、つぎに再生するアニメーション名とTicker.tickイベントの頻度が加えられる。

var data = {};
data.images = [画像ファイルのURI];
data.frames = {width:幅, height:高さ, regX:水平基準点, regY:垂直基準点};
data.animations = {アニメーション名:[開始フレーム, 終了フレーム, つぎのアニメーション名, Ticker.tickイベント頻度]};
var mySpriteSheet = new SpriteSheet(data);

BitmapAnimationクラスを用いたアニメーションは、Ticker.tickイベントで描かれる。配列の4つ目(インデックス3)のエレメントに頻度の整数を与えると、アニメーションがフレームごとにその回数イベントを待って進むので、再生がゆっくりになる。

つぎに、ビットマップのアニメーションは、BitmapAnimationクラスのコンストラクタにSpriteSheetオブジェクトを引数に渡してつくる。アニメーションを再生するには、BitmapAnimation.gotoAndPlay()メソッドに引数としてアニメーション名またはフレーム番号を渡して呼出す。

var animation = new BitmapAnimation(mySpriteSheet);
animation.gotoAndPlay(アニメーション名);

[*2] Flash Professional CS6では、[ライブラリ]につくったアニメーションのシンボルを右クリックすると、コンテクストメニューから[スプライトシートを生成]できる。[スプライトシートを生成]ダイアログボックスが開くと、[データ形式]の選択項目に[easeljs]があるので(図002)、書出した画像ファイルがそのまま使える。

図007■[スプライトシートを生成]ダイアログボックス
図007


02-02 スプライトシートからふたつのアニメーションをつくって再生する

スプライトシートからアニメーションをつくる。スクリプト全体は、後にコード001として掲げた。クラスSpriteSheetとBitmapAnimationのふたつからつくるスプライトシートのアニメーションは、Tickerクラスで動かす(第5および第12〜13行目)。そこで、初期化の関数(xInitialize())でStageオブジェクトをTickerクラスのリスナーに加えた(第7行目)。

  1. function xInitialize() {
  1.   Ticker.addListener(stage);
  2. }

スプライトシートは、初めの6フレーム(インデックス0から5まで)が、ペンギンの歩くアニメーションだ(図008上図)。そして、残りのフレーム(インデックス6から30まで)は、ペンギンが上から落ちてきて弾む(図008下図)。このふたつは、それぞれに別のアニメーション名をつけて扱う。

図008■ペンギンの歩きと落ちて弾むアニメーション
図008上
図008下

ファイルのパスを変数(file)に定め(第2行目)、初期設定の関数(xInitialize())からスプライトシートのアニメーション作成の関数(setAnimation())を呼出す(第6行目)。渡す引数は、ファイルのパスとアニメーションを置くxy座標だ。

スプライトシートのアニメーションをつくる関数(setAnimation())では、SpriteSheet()コンストラクタに与える引数のObjectインスタンス(data)がまずつくられる(第10行目)。

imagesプロパティの配列には、関数が引数として受取ったファイルのパス(file)をエレメントに納める(第11行目)。framesプロパティには、切り出すイメージの幅(width)と高さ(height)、および基準点のxy座標(regXとregY)をObjectで与えました(第26行目)。animationsプロパティのObjectインスタンスには、ふたつのアニメーションの名前(walkとdrop)をプロパティに定め、値の配列に再生するフレームの開始と終了のインデックス番号をエレメントに納める。ふたつ目のアニメーションには、つぎに再生するアニメーション名とTicker.tickイベントの頻度も加えた(第13行目)。

このObjectインスタンス(data)を引数にしてSpriteSheetオブジェクト(mySpriteSheet)をつくり、さらにこのオブジェクトを引数にして、BitmapAnimationのインスタンス(animation)をつくる(第14〜15行目)。BitmapAnimationインスタンスは、Stageオブジェクトの表示リストに加えた(第16行目)。

  1. var file = "images/sprite_sheet.png";
  2. function xInitialize() {
  1.   setAnimation(file, canvasObject.width / 2, canvasObject.height);
  1. }
  2. function setAnimation(file, nX, nY) {
  3.   var data = {};
  4.   data.images = [file];
  5.   data.frames = {width:102, height:282, regX:54, regY:282};
  6.   data.animations = {
        walk: [0, 5],
        drop: [6, 30, "walk", 2]
        };
  7.   var mySpriteSheet = new SpriteSheet(data);
  8.   var animation = new BitmapAnimation(mySpriteSheet);
  9.   stage.addChild(animation);
  1. }

そして、関数が引数に受取ったxy座標値(nXとnY)に、BitmapAnimationインスタンス(animation)の位置を定めた(第30〜32行目)。アニメーションを再生するため、BitmapAnimation.gotoAndPlay()メソッドにふたつ目のアニメーション名(drop)を渡して呼出す(第33行目)。

ふたつ目のアニメーションが再生し終わると、つぎに定められたひとつ目のアニメーションが繰返す。そこで、インスタンス(animation)のDisplayObject.onClickイベントにはハンドラの関数を定め、ふたつ目のアニメーションが再生されるようにした(第20〜21行目)。

  1. function setAnimation(file, nX, nY) {
  1.   animation.x = nX;
  2.   animation.y = nY;
  3.   animation.gotoAndPlay("drop");
  4.   animation.onClick = function() {
  5.     this.gotoAndPlay("drop");
  6.   }
  7. }

これで、まずペンギンが落ちて弾むアニメーション(drop)から始まり、続くアニメーション(walk)としてペンギンが歩き続ける。そして、クリックすると、またペンギンが落ちてきて、歩き続けるという繰返しになる(コード006)。

コード006■スプライトシートからふたつのアニメーションをつくって再生する
  1. var stage;
  2. var file = "images/sprite_sheet.png";
  3. function xInitialize() {
  4.   var canvasObject = document.getElementById('myCanvas');
  5.   stage = new Stage(canvasObject);
  6.   setAnimation(file, canvasObject.width / 2, canvasObject.height);
  7.   Ticker.addListener(stage);
  8. }
  9. function setAnimation(file, nX, nY) {
  10.   var data = {};
  11.   data.images = [file];
  12.   data.frames = {width:102, height:282, regX:54, regY:282};
  13.   data.animations = {
        walk: [0, 5],
        drop: [6, 30, "walk", 2]
        };
  14.   var mySpriteSheet = new SpriteSheet(data);
  15.   var animation = new BitmapAnimation(mySpriteSheet);
  16.   stage.addChild(animation);
  17.   animation.x = nX;
  18.   animation.y = nY;
  19.   animation.gotoAndPlay("drop");
  20.   animation.onClick = function() {
  21.     this.gotoAndPlay("drop");
  22.   }
  23. }

03 TweenJSを使ったトゥイーンアニメーション

03-01 Canvas上部に星形を描く

前述01-03「EaselJSで星形を描く」のコード004「EaselJSでCanvasに星形を描く」を少し整理して、つぎの抜書きのように星形の描かれたShapeインスタンスをCanvas上部中央に置く(行番号は後にscript要素全体を掲げるコード007にもとづく)。

  1. var stage;
  2. var nRadius = 40;
  3. function xInitialize() {
  4.   var canvasObject = document.getElementById('myCanvas');
  5.   stage = new Stage(canvasObject);
      // xDraw();
  6.   xDraw(canvasObject.width, canvasObject.height);
  7. }
    // function xDraw() {
  8. function xDraw(nWidth, nHeight) {
  9.   var myShape = new Shape();
  10.   var myGraphics = myShape.graphics;
  11.   stage.addChild(myShape);
  12.   myShape.x = nWidth / 2;   // 50;
  13.   myShape.y = nRadius;   // 50;
  14.   myGraphics.beginStroke("#0000FF");
  15.   myGraphics.beginFill("#00FFFF");
      // myGraphics.drawPolyStar(0, 0, 40, 5, 0.6, -90);
  16.   myGraphics.drawPolyStar(0, 0, nRadius, 5, 0.6, -90);
  17.   stage.update();
  1. }

03-02 TweenJSを使った簡単なトゥイーンアニメーション

Shapeインスタンスにトゥイーンアニメーションを加える。まず、TweenJSを使ってトゥイーンアニメーションさせるため、ライブラリのJavaScript(JS)ファイルをscript要素で読込む(第5行目)。

  1. <script src="lib/tweenjs-0.3.0.min.js"></script>

TweenJSクラスそのものは、プロパティ値を刻々と変えるだけだ。アニメーションとして表示するには、tickイベントでStage.update()メソッドを呼出して画面を描替えなければならない(第33〜35行目)。

トゥイーンを定める関数(setTween())は、インスタンスにごく簡単なアニメーションを加える。そのために用いるのが、Tween()コンストラクタTween.to()メソッドのふたつだ。

  1. Tween()コンストラクタでトゥイーンするインスタンスと基本設定を定める。
  2. Tween.to()メソッドにトゥイーンするプロパティとその最終的な値、間隔、イージングの仕方を与える。

Tween()コンストラクタには、第1引数でトゥイーンするオブジェクトを定める。また、第2引数に、必要があれば初期設定のプロパティをObjectインスタンスに納めて渡す。今回は、loopプロパティをtrueに定めて、トゥイーンを繰返す(第28行目)。

new Tween(対象オブジェクト, 初期設定Object)

そして、Tween.to()メソッドには、第1引数にトゥイーンするプロパティ値のObjectインスタンス、第2引数はその間隔、第3引数にはイージングの関数を渡す。さまざまなイージングの関数が、Easeクラスに定められています。

Tweenオブジェクト.to(プロパティ値のObject, 間隔, イージング関数)

Tween.to()メソッドの第1引数には、ふたつのプロパティyとrotationをObjectインスタンスに納めて、インスタンスを360度回しながらCanvasの下端まで垂直に動かす。また、第2引数のアニメーションの間隔は5秒(5000ミリ秒)だ。そして、第3引数のイージングとして、トゥイーンの最後にバウンドする静的メソッドEase.bounceOut()を用いた(第29行目)[*3]

  1. function xDraw(nWidth, nHeight) {
  1.   Ticker.addListener(window);
  2.   setTween(myShape, nWidth, nHeight);
  3. }
  4. function setTween(target, nWidth, nHeight) {
  5.   var myTween = new Tween(target, {loop:true});
  6.   myTween.to({y:nHeight - nRadius, rotation:360}, 5000, Ease.bounceOut);
  1. }
  2. function tick() {
  3.   stage.update();
  4. }

これで星形のインスタンスが上から回りながら落ちてきて、下で弾むトゥイーンアニメーションが繰返される(図009)。

図009■星形のインスタンスが回りながら落ちて弾む
図009上

図009中

図009下

[*3] Easeクラスに備わるさまざまなイージングの静的メソッドについては、TwweenJSのサイトに掲げられた「DEMOS」(デモ)の「SPARK TABLE」で、それぞれの値の変わり方がグラフで確かめられる(図009)。

図010■Easeクラスのイージングのメソッドによる値の変化が確かめられる「SPARK TABLE」
図010


03-03 複数のトゥイーンを組合わせる

TweenJSのトゥイーンはいくつも組合わせられる。星のShapeインスタンスが落ちて完全に弾み終わったら、1秒「ため」をつくり、その後フェードアウトしてみよう。Tweenインスタンスに定めたトゥイーンは、「キュー」というリストに納められて順に実行される。だから、アニメーションさせたい順に、トゥイーンを続けざまに加えて構わない。

トゥイーンの「ため」は、Tween.wait()メソッドに待ち時間を渡して定める。

Tween.wait(待ち時間)

以下のコード007に、1秒の待ちと、2.5秒のフェードアウトの(alphaプロパティを0にする)トゥイーンを加えた(第30〜31行目)。フェードアウトのイージングに定めたEase.circIn()メソッドは値を、始めはゆっくり、次第に速く変えていく前掲図010参照)。これでバウンドし終えたShapeインスタンスが1秒そのままで、その後2.5秒かけてフェードアウトする(図011)。

図011■バウンドし終えた星のインスタンスが1秒後にフェードアウトする
図011左   図011右

コード007■落ちてきた星形のインスタンスが弾み終えてしばらくするとフェードアウトする
  1. <script>
  2. var createjs = window;
  3. </script>
  4. <script src="lib/easeljs-0.5.0.min.js"></script>
  5. <script src="lib/tweenjs-0.3.0.min.js"></script>
  6. <script>
  7. var stage;
  8. var nRadius = 40;
  9. function xInitialize() {
  10.   var canvasObject = document.getElementById('myCanvas');
  11.   stage = new Stage(canvasObject);
  12.   xDraw(canvasObject.width, canvasObject.height);
  13. }
  14. function xDraw(nWidth, nHeight) {
  15.   var myShape = new Shape();
  16.   var myGraphics = myShape.graphics;
  17.   stage.addChild(myShape);
  18.   myShape.x = nWidth / 2;
  19.   myShape.y = nRadius;
  20.   myGraphics.beginStroke("#0000FF");
  21.   myGraphics.beginFill("#00FFFF");
  22.   myGraphics.drawPolyStar(0, 0, nRadius, 5, 0.6, -90);
  23.   stage.update();
  24.   Ticker.addListener(window);
  25.   setTween(myShape, nWidth, nHeight);
  26. }
  27. function setTween(target, nWidth, nHeight) {
  28.   var myTween = new Tween(target, {loop:true});
  29.   myTween.to({y:nHeight - nRadius, rotation:360}, 5000, Ease.bounceOut);
  30.   myTween.wait(1000);
  31.   myTween.to({alpha:0}, 2500, Ease.circIn);
  32. }
  33. function tick() {
  34.   stage.update();
  35. }
  36. </script>

04 PreloadJSで画像ファイルを読込む

04-01 外部画像ファイルを読込んでCanvasの中央に表示する

まずは、PreloadJSのプリロードなしに、外部画像ファイルを読込んでCanvasの中央に表示する(図002)。後にscript要素を掲げるコード008から抜書きして示す。

図012■外部から読込んだファイルの画像がCanvasの中央に表示される
図012

  1. var stage;
  2. var myBitmap;
  3. function xInitialize() {
  4.   var canvasObject = document.getElementById('myCanvas');
  5.   stage = new Stage(canvasObject);
      xDraw(canvasObject.width / 2, canvasObject.height / 2);
  1. }
  2. function xDraw(nX, nY) {
  1.   myBitmap = new Bitmap("images/image.png");
      var myImage = myBitmap.image;
  2.   myBitmap.x = nX - myImage.width / 2;
  3.   myBitmap.y = nY - myImage.height / 2;
  4.   stage.addChild(myBitmap);
  5.   stage.update();
  6. }

このスクリプトだけでは、画像の容量が大きかったりすると、読込みが間に合わなくて画像のサイズが正しくとれなかったり(第22〜23行目)、描画の更新(第20行目)に間に合わずに表示されないことがあり得る。


04-02 PreloadJSで外部ファイルを読込む

PreloadJSを用いて画像ファイルは先読みするには、まずscript要素にPreloadJSのライブラリを加える(第5行目)。

  1. <script src="lib/preloadjs-0.2.0.min.js"></script>

つぎに、初めに呼出される初期設定の関数(xInitialize())に手を加え、PreloadJSで外部画像ファイルを先読みする。コンストラクタメソッドPreloadJS()には、XMLHttpRequestを使うかどうかブール(論理)値で引数に渡す(第14行目)。

new PreloadJS(XMLHttpRequestの使用)

ファイルをひとつ読込み終えたかどうかは、AbstractLoader.onFileLoadイベントにハンドラの関数を設定して捉える(第15行目)。

PreloadJSオブジェクト.onFileLoad = イベントハンドラ

そして、PreloadJS.loadFile()メソッドで外部ファイルの読込みを始める(第16行目)[*4]。引数に渡す外部ファイルの情報には、画像ファイルのURLを文字列でそのまま渡せる。

PreloadJSオブジェクト.loadFile(URL)

もうひとつ、URLに加えていくつかのデータをObjectインスタンスのプロパティとして納めて渡してもよい。プロパティsrcにURL、idに読込んだデータの識別子がともに文字列で定められる(第13行目)。もうひとつ加えたdataプロパティの使い方は後に説明する。

PreloadJSオブジェクト.loadFile({src:URL, id:識別子})

初期設定の関数(xInitialize())は、つぎのようになる。

  1. function xInitialize() {
  2.   var canvasObject = document.getElementById('myCanvas');
  3.   stage = new Stage(canvasObject);
  4.   var position = new Point(canvasObject.width / 2, canvasObject.height / 2);
  5.   var file = {src:"images/image.png", id:"image", data:position}
  6.   var loader = new PreloadJS(false);
  7.   loader.onFileLoad = xDraw;
  8.   loader.loadFile(file);
      // xDraw(canvasObject.width / 2, canvasObject.height / 2);
  9. }

イベントハンドラ(xDraw())が引数に受取ったイベントオブジェクト(Objectインスタンス)のプロパティresultで、読込んだ画像の参照(image要素)が得られる(第19行目)。また、dataプロパティからは、PreloadJS.loadFile()メソッドの引数に渡したObjectインスタンス(前掲第13行目)のdataプロパティに定めた値が受取れる(第20行目)。画像の参照からBitmapインスタンスをつくり、位置座標のPointオブジェクトで求めた座標に配置し、表示リストへの追加と描画を行った(第21〜25行目)。

    // function xDraw(nX, nY) {
  1. function xDraw(eventObject) {
  2.   var myImage = eventObject.result;
  3.   var position = eventObject.data
      // myBitmap = new Bitmap("images/image.png");
      // var myImage = myBitmap.image;
  4.   myBitmap = new Bitmap(myImage);
      // myBitmap.x = nX - myBitmap.image.width / 2;
  5.   myBitmap.x = position.x - myImage.width / 2;
      // myBitmap.y = nY - myBitmap.image.height / 2;
  6.   myBitmap.y = position.y - myImage.height / 2;
  7.   stage.addChild(myBitmap);
  8.   stage.update();
  9. }

これで読込む外部ファイルの容量にかかわらず、正しく画像が描かれる。書上げたscript要素全体は、つぎのコード008のとおりだ。

コード008■PreloadJSで外部画像ファイルの読込みを待って描画する
  1. <script>
  2. var createjs = window;
  3. </script>
  4. <script src="lib/easeljs-0.5.0.min.js"></script>
  5. <script src="lib/preloadjs-0.2.0.min.js"></script>
  6. <script>
  7. var stage;
  8. var myBitmap;
  9. function xInitialize() {
  10.   var canvasObject = document.getElementById('myCanvas');
  11.   stage = new Stage(canvasObject);
  12.   var position = new Point(canvasObject.width / 2, canvasObject.height / 2);
  13.   var file = {src:"images/image.png", id:"image", data:position}
  14.   var loader = new PreloadJS(false);
  15.   loader.onFileLoad = xDraw;
  16.   loader.loadFile(file);
  17. }
  18. function xDraw(eventObject) {
  19.   var myImage = eventObject.result;
  20.   var position = eventObject.data
  21.   myBitmap = new Bitmap(myImage);
  22.   myBitmap.x = position.x - myImage.width / 2;
  23.   myBitmap.y = position.y - myImage.height / 2;
  24.   stage.addChild(myBitmap);
  25.   stage.update();
  26. }
  27. </script>

[*4] 複数のファイルをまとめて読込むには、PreloadJS.loadManifest()メソッドを用いる。複数のファイルを配列で渡せるので、呼出しは1度で済む。詳しくは、「PreloadJSで外部画像ファイルの読込みを待つ」03「PreloadJSについてもう少し深く知る」参照。


05 SoundJSでサウンドファイルを読込んで再生する

05-01 サウンドファイルを読込んで再生する

PreloadJSクラスでサウンドファイルをロードするとき、プラグインはPreloadJS.installPlugin()メソッドにより登録しておかなければならない。PreloadJS.installPlugin()メソッドの引数は、読込んだデータを扱うクラスだ。ここではSoundJSクラスを引数に定める。

PreloadJSオブジェクト.installPlugin(SoundJS)

そして、読込んだサウンドを再生するのは、静的メソッドSoundJS.play()だ。引数には、再生するサウンドのパスもしくは識別子(id)を渡す。戻り値として、ひとつひとつのサウンドを扱うSoundInstanceオブジェクトが返される。

SoundJS.play(サウンドの指定)

HTMLドキュメントと同じ場所のフォルダ(sounds)に納めたMP3サウンドファイル(music.mp3)を、読込んで再生する(コード009)。body要素でとくに見せたいイメージやパーツがなければ、Canvasは要らない。すると、script要素には、PreloadJSとSoundJSのふたつのライブラリを読込めばよい(第4〜5行目)。

初期設定の関数(initialize())は、PreloadJSインスタンス(loader)にPreloadJS.installPlugin()メソッドでプラグインを登録してから、AbstractLoader.onFileLoadイベントにハンドラ(soundLoaded())を定めたうえで、サウンドファイルを読込む(第9〜12行目)。PreloadJS.loadFile()メソッドの引数に渡すオブジェクトには、ファイルのパス(src)と併せて、識別子(id)も定めた(第12行目)。

つぎに、ファイルのロードが済んで呼出されるハンドラ(soundLoaded())は、引数に受取ったイベントオブジェクト(eventObject)からサウンドファイルの識別子(id)を取出し、SoundJS.play()メソッドに渡して呼出す。これで、サウンドの再生が始まる(第15行目)。

コード009■MP3サウンドファイルを読込んで再生する
  1. <script>
  2. var createjs = window;
  3. </script>
  4. <script src="lib/preloadjs-0.2.0.min.js"></script>
  5. <script src="lib/soundjs-0.3.0.min.js"></script>
  6. <script>
  7. var file = "sounds/music.mp3";
  8. function xInitialize() {
  9.   var loader = new PreloadJS(false);
  10.   loader.installPlugin(SoundJS);
  11.   loader.onFileLoad = soundLoaded;
  12.   loader.loadFile({src:file, id:"music"});
  13. }
  14. function soundLoaded(eventObject) {
  15.   SoundJS.play(eventObject.id);
  16. }
  17. </script>

05-02 サウンドの一時停止と再開

再生されているサウンドの一時停止とその再開には、それぞれ静的メソッドSoundJS.pause()USoundJS.resume()を呼出す。引数はいずれも、再生するサウンドを定める識別子だ(SoundJS.play()メソッドの第1引数と同じ)。前掲コード009に、サウンドの一時停止と再開のコントロールを加える。

一時停止と再生(再開)はボタンひとつで切替えることにして、body要素にinput要素のボタンを置く(図013)。そして、JavaScriptで取得するためのid属性(control)を定めておく。

図013■body要素にはinput要素のボタンを置く
図013

<body onLoad="initialize()">
<input type="button" value="準備中" id="control">
</body>

前掲コード009でサウンドを読込み終えたハンドラ(soundLoaded())に直接書いた再生のSoundJS.play()メソッドの呼出しは、つぎのように別の関数(startSound())に分ける(第16〜19行目)。書替えたスクリプト全体は、後にコードコード010として掲げる(抜書きする行番号は、このコード010にもとづく)。

  1. function soundLoaded(eventObject) {
  2.   var id = eventObject.id;
  3.   startSound(id);
  1. }
  2. function startSound(sound) {
  3.   SoundJS.play(sound);
  1. }

SoundJS.pause()SoundJS.resume()メソッドには、いずれも引数としてサウンドの識別子が要る。そこで、その値(id)は、ボタンの参照(control)に変数(sound)として定めた(第8および第14行目)。

  1. var control;
  2. function xInitialize() {
  1.   control = document.getElementById("control");
  1. }
  2. function soundLoaded(eventObject) {
  3.   var id = eventObject.id;
  1.   control.sound = id;
  2. }

サウンドを再生する関数(startSound())は、別に定めた関数(pauseNext())の呼出しにより(第18行目)、ボタン(control)のonclickイベントに一時停止の関数(pauseSound())をハンドラとして定める(第30行目)。

ボタンをクリックするとハンドラ(pauseSound())が呼出されて、SoundJS.pause()メソッドでサウンドを一時停止するとともに、ボタンのonclickイベントのハンドラを再開の関数(resumeSound())に書替える(第21〜22行目)。なお、SoundJS.pause()SoundJS.resume()メソッドを呼出すときには、前述のとおりボタンの変数(sound)に定めたサウンドの識別子を引数に用いる(第21行目)。

  1. function startSound(sound) {
  1.   pauseNext();
  2. }
  3. function pauseSound(eventObject) {
  4.   SoundJS.pause(this.sound);
  5.   control.onclick = resumeSound;
  6.   control.value = "再生";
  7. }
  1. function pauseNext() {
  2.   control.onclick = pauseSound;
  3.   control.value = "一時停止";
  4. }

サウンド再開のハンドラ(resumeSound())は、SoundJS.resume()メソッドでサウンドの続きを再生するとともに、ボタンクリックのハンドラを一時停止の関数(pauseSound())に戻す(第26〜27行目)。

  1. function resumeSound(eventObject) {
  2.   SoundJS.resume(this.sound);
  3.   pauseNext();
  4. }
  5. function pauseNext() {
  6.   control.onclick = pauseSound;
  7.   control.value = "一時停止";
  8. }

書き上げたスクリプト全体は、以下のコード010のとおりだ。サウンドの読込み・再生・一時停止の状況がわかるように、ボタンのラベルにテキストを加えてた(第9、第23および第31行目)。読込み終えたサウンドの再生が始まると、ボタンには「一時停止」と示される。クリックすれば一時停止し、表記は「再生」に変わる(図014)。

図014■サウンドの再生状況によりボタンの表記が変わる
←→

コード010■ロードしたMPSサウンドファイルを再生・一時停止・再開する
  1. var file = "sounds/music.mp3";
  2. var control;
  3. function xInitialize() {
  4.   var loader = new PreloadJS(false);
  5.   loader.installPlugin(SoundJS);
  6.   loader.onFileLoad = soundLoaded;
  7.   loader.loadFile({src:file, id:"music"});
  8.   control = document.getElementById("control");
  9.   control.value = "読込み中";
  10. }
  11. function soundLoaded(eventObject) {
  12.   var id = eventObject.id;
  13.   startSound(id);
  14.   control.sound = id;
  15. }
  16. function startSound(sound) {
  17.   SoundJS.play(sound);
  18.   pauseNext();
  19. }
  20. function pauseSound(eventObject) {
  21.   SoundJS.pause(this.sound);
  22.   control.onclick = resumeSound;
  23.   control.value = "再生";
  24. }
  25. function resumeSound(eventObject) {
  26.   SoundJS.resume(this.sound);
  27.   pauseNext();
  28. }
  29. function pauseNext() {
  30.   control.onclick = pauseSound;
  31.   control.value = "一時停止";
  32. }


作成者: 野中文雄
更新日: 2012年11月9日 注[*1]と[*4]を追加。
作成日: 2012年11月8日


Copyright © 2001-2012 Fumio Nonaka.  All rights reserved.