|
|||||||||||||||||||||||||||||||||||||||||||||||
■Twitter: @FumioNonaka / Facebook Page: CreateJS
JaGra PROFESSIONAL SCHOOL Seminar CreateJSでHTML5向けの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要素を書き加える
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■塗りの矩形を描く関数
この関数をページが読込み終わったときに呼出すには、body要素のイベント属性(イベントハンドラ)onloadに設定します(コード003)。これで、canvas要素で定めた領域に矩形を描くコードができ上がりました(図002)。 コード003■関数をonloadイベント属性に定める
ブラウザで確かめると、左上角座標(10, 10)の位置に幅100×高さ100ピクセルの黒い正方形が描かれる(図002)。 図002■左上角座標(10, 10)に100ピクセル四方の黒い正方形が描かれた 01-03 EaselJSで星形を描くEaselJSは表示リストを備える。その頂点のStageオブジェクトをつくらなければならない。Stageクラスのコンストラクタには、引数としてcanvas要素の参照を渡す。 new Stage(canvas要素) そして、EaselJSライブラリのJavaScript(JS)ファイルを読込む(本稿ではHTMLドキュメントと同じ場所のlibフォルダに入れている)。まずはStageオブジェクトをつくるまでのコードは、つぎのとおりだ(行番号は、後にscript要素全体を掲げるコード004にもとづく)[*1]。
Stageオブジェクトの表示リストに、描画のためのオブジェクトをひとつ加える。Flashと同じShapeというオブジェクトがあり、描画用のメソッドが使える。Shapeオブジェクトをつくって、Container.addChild()メソッドで表示リストに加え、その座標を定めるスクリプトはつぎのとおりだ。
描画に用いるのはGraphicsオブジェクトで、ShapeオブジェクトのShape.graphicsプロパティから参照が得られる。描画の色を決めるメソッドは、塗りがGraphics.beginFill()、線はGraphics.beginStroke()だ。引数のカラーはHTMLと同じ文字列で渡す。星形はGraphics.drawPolyStar()メソッドで描く。Canvasに描画するには、最後にStage.update()メソッドを呼出さなければならない。
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頂点の星形
これで、中心座標(0, 0)の位置に半径40ピクセルで5頂点の星形が描かれる(図004)。script要素全体は、つぎのコード004のとおりだ。 図004■Graphics.drawPolyStar()メソッドで描かれた5頂点の星形
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)。
図005■Canvasに描いた星形が回る
02 スプライトシートからつくるアニメーション02-01 SpriteSheetとBitmapAnimationクラスの使い方スプライトシートは、アニメーションの複数フレームをひとつの画像ファイルにまとめたものだ(図006左図)。そのとき、EaselJSではフレームごとの画像の大きさ(幅×高さ)をすべて揃えると扱いやすい(図006右図)[*2]。この画像ファイル(sprite_sheet.png)を、HTMLドキュメントと同じ場所のフォルダ(images)に入れておく。 図006■フレームの画像をまとめたスプライトシート
まず、SpriteSheetクラスのコンストラクタでインスタンスをつくる。そして、引数に渡すObjectインスタンスに、スプライトシートから切り出して再生するアニメーションの情報をプロパティとして与える。必要なプロパティは、imagesとframes、およびanimationsの3つだ。 imagesプロパティは配列で、スプライトシートに用いる画像ファイルのURIをエレメントに加える。framesプロパティには、切り出すイメージの幅(width)と高さ(height)、および基準点のxy座標(regXとregY)などをObjectインスタンスとして定める。animationsプロパティにはObjectインスタンスを与え、そのプロパティはアニメーションの名前で、再生するフレームの開始と終了のインデックス番号を配列に入れて定める。インデックスは0から始まる整数だ。さらに、配列エレメントとして、つぎに再生するアニメーション名とTicker.tickイベントの頻度が加えられる。 var data = {}; BitmapAnimationクラスを用いたアニメーションは、Ticker.tickイベントで描かれる。配列の4つ目(インデックス3)のエレメントに頻度の整数を与えると、アニメーションがフレームごとにその回数イベントを待って進むので、再生がゆっくりになる。 つぎに、ビットマップのアニメーションは、BitmapAnimationクラスのコンストラクタにSpriteSheetオブジェクトを引数に渡してつくる。アニメーションを再生するには、BitmapAnimation.gotoAndPlay()メソッドに引数としてアニメーション名またはフレーム番号を渡して呼出す。 var animation = new BitmapAnimation(mySpriteSheet);
02-02 スプライトシートからふたつのアニメーションをつくって再生するスプライトシートからアニメーションをつくる。スクリプト全体は、後にコード001として掲げた。クラスSpriteSheetとBitmapAnimationのふたつからつくるスプライトシートのアニメーションは、Tickerクラスで動かす(第5および第12〜13行目)。そこで、初期化の関数(xInitialize())でStageオブジェクトをTickerクラスのリスナーに加えた(第7行目)。
スプライトシートは、初めの6フレーム(インデックス0から5まで)が、ペンギンの歩くアニメーションだ(図008上図)。そして、残りのフレーム(インデックス6から30まで)は、ペンギンが上から落ちてきて弾む(図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行目)。
そして、関数が引数に受取ったxy座標値(nXとnY)に、BitmapAnimationインスタンス(animation)の位置を定めた(第30〜32行目)。アニメーションを再生するため、BitmapAnimation.gotoAndPlay()メソッドにふたつ目のアニメーション名(drop)を渡して呼出す(第33行目)。 ふたつ目のアニメーションが再生し終わると、つぎに定められたひとつ目のアニメーションが繰返す。そこで、インスタンス(animation)のDisplayObject.onClickイベントにはハンドラの関数を定め、ふたつ目のアニメーションが再生されるようにした(第20〜21行目)。
これで、まずペンギンが落ちて弾むアニメーション(drop)から始まり、続くアニメーション(walk)としてペンギンが歩き続ける。そして、クリックすると、またペンギンが落ちてきて、歩き続けるという繰返しになる(コード006)。 コード006■スプライトシートからふたつのアニメーションをつくって再生する
03 TweenJSを使ったトゥイーンアニメーション03-01 Canvas上部に星形を描く前述01-03「EaselJSで星形を描く」のコード004「EaselJSでCanvasに星形を描く」を少し整理して、つぎの抜書きのように星形の描かれたShapeインスタンスをCanvas上部中央に置く(行番号は後にscript要素全体を掲げるコード007にもとづく)。
03-02 TweenJSを使った簡単なトゥイーンアニメーションShapeインスタンスにトゥイーンアニメーションを加える。まず、TweenJSを使ってトゥイーンアニメーションさせるため、ライブラリのJavaScript(JS)ファイルをscript要素で読込む(第5行目)。
TweenJSクラスそのものは、プロパティ値を刻々と変えるだけだ。アニメーションとして表示するには、tickイベントでStage.update()メソッドを呼出して画面を描替えなければならない(第33〜35行目)。 トゥイーンを定める関数(setTween())は、インスタンスにごく簡単なアニメーションを加える。そのために用いるのが、Tween()コンストラクタと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]。
これで星形のインスタンスが上から回りながら落ちてきて、下で弾むトゥイーンアニメーションが繰返される(図009)。 図009■星形のインスタンスが回りながら落ちて弾む
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秒後にフェードアウトする
04 PreloadJSで画像ファイルを読込む04-01 外部画像ファイルを読込んでCanvasの中央に表示するまずは、PreloadJSのプリロードなしに、外部画像ファイルを読込んでCanvasの中央に表示する(図002)。後にscript要素を掲げるコード008から抜書きして示す。 図012■外部から読込んだファイルの画像がCanvasの中央に表示される
このスクリプトだけでは、画像の容量が大きかったりすると、読込みが間に合わなくて画像のサイズが正しくとれなかったり(第22〜23行目)、描画の更新(第20行目)に間に合わずに表示されないことがあり得る。 04-02 PreloadJSで外部ファイルを読込むPreloadJSを用いて画像ファイルは先読みするには、まずscript要素にPreloadJSのライブラリを加える(第5行目)。
つぎに、初めに呼出される初期設定の関数(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())は、つぎのようになる。
イベントハンドラ(xDraw())が引数に受取ったイベントオブジェクト(Objectインスタンス)のプロパティresultで、読込んだ画像の参照(image要素)が得られる(第19行目)。また、dataプロパティからは、PreloadJS.loadFile()メソッドの引数に渡したObjectインスタンス(前掲第13行目)のdataプロパティに定めた値が受取れる(第20行目)。画像の参照からBitmapインスタンスをつくり、位置座標のPointオブジェクトで求めた座標に配置し、表示リストへの追加と描画を行った(第21〜25行目)。
これで読込む外部ファイルの容量にかかわらず、正しく画像が描かれる。書上げたscript要素全体は、つぎのコード008のとおりだ。 コード008■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サウンドファイルを読込んで再生する
05-02 サウンドの一時停止と再開再生されているサウンドの一時停止とその再開には、それぞれ静的メソッドSoundJS.pause()とUSoundJS.resume()を呼出す。引数はいずれも、再生するサウンドを定める識別子だ(SoundJS.play()メソッドの第1引数と同じ)。前掲コード009に、サウンドの一時停止と再開のコントロールを加える。 一時停止と再生(再開)はボタンひとつで切替えることにして、body要素にinput要素のボタンを置く(図013)。そして、JavaScriptで取得するためのid属性(control)を定めておく。 図013■body要素にはinput要素のボタンを置く
前掲コード009でサウンドを読込み終えたハンドラ(soundLoaded())に直接書いた再生のSoundJS.play()メソッドの呼出しは、つぎのように別の関数(startSound())に分ける(第16〜19行目)。書替えたスクリプト全体は、後にコードコード010として掲げる(抜書きする行番号は、このコード010にもとづく)。
SoundJS.pause()とSoundJS.resume()メソッドには、いずれも引数としてサウンドの識別子が要る。そこで、その値(id)は、ボタンの参照(control)に変数(sound)として定めた(第8および第14行目)。
サウンドを再生する関数(startSound())は、別に定めた関数(pauseNext())の呼出しにより(第18行目)、ボタン(control)のonclickイベントに一時停止の関数(pauseSound())をハンドラとして定める(第30行目)。 ボタンをクリックするとハンドラ(pauseSound())が呼出されて、SoundJS.pause()メソッドでサウンドを一時停止するとともに、ボタンのonclickイベントのハンドラを再開の関数(resumeSound())に書替える(第21〜22行目)。なお、SoundJS.pause()やSoundJS.resume()メソッドを呼出すときには、前述のとおりボタンの変数(sound)に定めたサウンドの識別子を引数に用いる(第21行目)。
サウンド再開のハンドラ(resumeSound())は、SoundJS.resume()メソッドでサウンドの続きを再生するとともに、ボタンクリックのハンドラを一時停止の関数(pauseSound())に戻す(第26〜27行目)。
書き上げたスクリプト全体は、以下のコード010のとおりだ。サウンドの読込み・再生・一時停止の状況がわかるように、ボタンのラベルにテキストを加えてた(第9、第23および第31行目)。読込み終えたサウンドの再生が始まると、ボタンには「一時停止」と示される。クリックすれば一時停止し、表記は「再生」に変わる(図014)。 図014■サウンドの再生状況によりボタンの表記が変わる
コード010■ロードしたMPSサウンドファイルを再生・一時停止・再開する
作成者: 野中文雄 Copyright © 2001-2012 Fumio Nonaka. All rights reserved. |
|||||||||||||||||||||||||||||||||||||||||||||||