JavaScriptによるアニメーション
HTMLとJavaScript を使ったシンプルなアニメーションの例を紹介します。具体的には画面上でボールが跳ねるプログラムです。
サンプルアプリの動作:ボールが枠の中で跳ねるアニメ
このプログラムは、おおまかに以下の部分に分けることができます。
HTMLとCSS、JavaScript(キャンバスを準備する、ボールの最初の状態を決める、円を描く関数drawBall()の定義、関数animate()の定義、そして呼び出し)です。
アプリとソースコードのインポート
以下のボタンをクリックすると、Monaca Educationにプロジェクトをインポートできます。
Monaca Educationにインポートする(要ログイン)
HTMLとCSS
HTMLファイルindex.htmlでは、タグ<canvas>を使って、アニメーションを表示するためのエリア(キャンバス)を定義しています。
キャンバス要素には”myCanvas” というIDが付けてあり、JavaScriptからこのキャンバスを操作するために使用できます。以下はindex.htmlの中の、タグ<body>の内容です。
…
<body>
<canvas id="myCanvas" width="320" height="320"></canvas>
</body>
…
CSSファイル(フォルダcssの中のstyle.css)では、キャンバスの背景色を灰色に設定し、ページの中央に配置しています。
canvas {
background: #eee;
display: block;
margin: 0 auto;
}
JavaScript
JavaScriptファイルmain.js(※フォルダjsにあります)に、プログラムの本体があります。60行あまりのプログラムです。
5つに分けて説明します。
(1)キャンバスの準備をする
最初の部分では、キャンバスとその描画コンテキストを設定しています。
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
ここで言う「描画コンテキスト」は、画家が使うキャンバスと絵の具、または学校の黒板とチョークの関係にたとえることができます。
キャンバスは絵を描く先(背景やスペース)です。HTMLのキャンバスも、絵を描く先です。
一方、描画コンテキスト(※getContext(‘2d’) で取得されるオブジェクト。変数ctxに代入されている)は、そのキャンバス上に絵を描くためのツールや色(絵の具やチョーク)を表します。
つまり、ここで、プログラムの中で絵を描く先と、絵を描く道具を準備したわけです。プログラムの続きの部分で、描画コンテキスト(ctx)を使って、キャンバス上に図形を描いていきます。
(2)ボールの最初の状態を決める
続いて、ボールの初期位置(x, y)、ボールの動き(dx, dy)、そしてボールの半径(ballRadius)を定義しています。これらの変数はボールを画面上で動かすために使います。
var x = canvas.width / 2;
var y = canvas.height - 30;
var dx = 2;
var dy = -2;
var ballRadius = 10;
ボールの初期位置(x, y)は、ボールの中心の座標です。
なお、HTMLキャンバスでは、座標の原点(0, 0)は、キャンバスの左上の端にあります。キャンバスの一番上のY座標の値は0、一番下のY座標の値は「キャンバスの高さ」と同じになります。
キャンバスの幅を2で割ると、左右中央が分かります。
キャンバスの高さを2で割ると、上下中央が分かります。例のプログラムでは、画面の高さ-30としてありますから、キャンバスの高さから30引いた値になり、画面の一番下から少し(30だけ)画面中央寄りの位置になります。
ボールの動きの値は、横軸(X)方向と、縦軸(Y)方向の2つに分けて用意されています。
Xの値が正の値なら、ボールは画面右の方に移動していきます。負の値なら、画面左方向です。
Yの値が正の値なら、ボールは画面下の方に移動していきます。負の値なら、画面上方向です。
(3)円を描く関数drawBall()の定義
drawBall 関数では、キャンバス上にボールを描いています。
function drawBall() {
ctx.beginPath();
ctx.arc(x, y, ballRadius, 0, Math.PI*2);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
}
ctx.beginPath() と ctx.closePath() で描画の開始と終了を示します。その間に描きたい図形のための処理を書きます。
ctx.arc() を使って円を描いています。円は (x, y) の位置に描かれ、ballRadius でサイズ(半径)が指定されています。ctx.fillStyle でボールの色を設定し、ctx.fill() でその色でボールを塗りつぶしています。
(4)関数animate()の定義
関数animate()では、アニメーションの手順が実装されています。
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBall();
if(x + dx > canvas.width-ballRadius || x + dx < ballRadius) {
dx = -dx;
}
if(y + dy > canvas.height-ballRadius || y + dy < ballRadius) {
dy = -dy;
}
x += dx;
y += dy;
requestAnimationFrame(animate);
}
まず、ctx.clearRect() を使ってキャンバスをきれいにしています。これは初めて関数animate()が実行されるときはあまり意味がある動作ではありません。2回目以降に、「前回描いた絵を消す」という意味のある動作になります。
次に、関数drawBall()を呼び出してボールを描きます。
その後、ボールがキャンバスの端に達したかどうかをチェックし、端に達していればボールの移動方向を反転させます。符号の+、ーを入れ替えると、キャンバス上を移動する方向が逆になります(dx = -dx、dy = -dy)。
最後に、ボールの位置を更新し、requestAnimationFrame(animate) を呼び出して、次のフレーム(=次の瞬間の画面表示)で、再びこの関数(animate)が呼ばれるようにします。
以上により、ボールが動いているように見えるアニメーションが実現されます。
(5)処理を始める
ここまでのJavaScriptファイルでは、変数に値を代入し、関数を定義してきました。ここまででは、まだ、アニメーション動作を開始していません。
JavaScriptファイルの最後の、animate();で、関数animate()を呼び出し、関数の定義に従って動作が起きて、アニメーションになります。
animate();
プログラムの記述の順序と、実行の順序
JavaScriptファイルmain.jsに書いてある順序と、実際に処理が実行されるときの実行順序は異なります。次に概念図を示します。
水色の番号の順に実行されていきます。
最後の行のanimate();が、関数animate()を呼び出し、関数animate()の中からrequestAnimationFrame()が呼び出され、以後animate() -> requestAnimationFrame() -> animate() … という無限に続く繰り返しが実行されることになります。