今更聞けないcanvasの基礎の基礎

はじめまして。新入りのnagataです。 入社式で自転車乗ってた野郎です。

先輩方から「ブログ、書いてね!」とのお達しがあったので、 日報で書いたらウケがよさげだったcanvasのことについて書いてみようと思います。

※各種サンプルはMac上のSafari4.05、Firefox3.6.3、Chrome5.0で動作を確認しています。

canvasってなんぞ?

図を書き込めるhtml要素です。 OpenGLやDirectXのような面倒な設定を書くことなく、 手軽にグラフィック描画が行えます。 ブラウザだけでローカルアプリケーションのような グラフィカル(かつ動的な)表現が行えるわけです。

とりあえずつかってみる

早速何か描いてみましょう。 こういうことは実践あるのみです。

処理にはJavascriptを使います。 canvasに描画を行うときは、canvas要素からcontextを取得して、 それに対して描画の命令をする形になります。

たとえば、単純な四角形を描く場合は、次のように書きます。

// canvas要素を取得して
var canvas = document.getElementById('canvas');
// contextを取り出して
var cc = canvas.getContext('2d');
// 描画開始!
cc.beginPath();
// 100x50の四角形を描きます
cc.fillRect(30, 30, 100, 50);

サンプル

たったこれだけ。とっても簡単です。 DirectXなんかの場合だとはじめにウィンドウを作るところから始めないといけませんが、 canvasの場合はそんなことはありません。 すでにブラウザというウィンドウがあるんですから。

変化をつけてみる

もちろん、白黒の単純な図形だけではなくて、 色をつけたり、陰をつけたり、複雑な図形を描くこともできます。

var canvas = document.getElementById('canvas');
var cc = canvas.getContext('2d');

cc.save(); // 描画パラメータの保存(初期状態=指定なし)

// 太い線
cc.beginPath();
cc.lineWidth = 5;   // 線の太さを指定
cc.lineTo(50, 120); // (50, 120)から、
cc.lineTo(250, 180); // (250, 180)まで線を引く
cc.stroke();

cc.restore(); // 初期状態に戻す
cc.save();   // 再び保存

// 陰付きの赤い矩形
cc.beginPath();
cc.fillStyle     = '#F00'; // 塗りの色を赤にセット
cc.shadowBlur   = 5;     // 陰のぼかしを5pxに
cc.shadowColor = '#000'; // 色は黒
cc.shadowOffsetX = 5;    // X方向のオフセット
cc.shadowOffsetY = 5;    // Y方向のオフセット
cc.fillRect(30, 30, 100, 50);

cc.restore();
cc.save();

// 青い円
cc.beginPath();
cc.strokeStyle = '#00F'; // 線の色を青にセット
cc.arc(200, 100, 30, 0, Math.PI * 2, false);
cc.stroke();

cc.restore();

サンプル

ちょっと長いですが、ほとんどが「どのように描画するか」の設定なので 難しいことはないはずです。

動かしてみる

せっかくJavascriptを使っているので、描画した図形を動かしてみましょう。 clerRect()を使うと指定した範囲を消すことができるので、

  1. キャンバスをクリア
  2. 新しい図形を描画

という処理を繰り返すと、図形をアニメーションさせることができます。 今回は回転処理を行うrotate()と、平行移動を行うtranslate()を使って 四角形を回転させてみます。

var FPS = function(target) {
    // FPSの計算を行うクラス詳細はソースコード参照
};

var canvas = document.getElementById('canvas');
var cc = canvas.getContext('2d');

var theta = 0.0; // 回転角
var rectWidth = 100;
var rectHeight = 50;

// 30FPSでアニメーション
var fps = new FPS(30);

var loop = function() {
    fps.check();

    cc.save();

    // キャンバスをクリア
    cc.beginPath();
    cc.clearRect(0, 0, canvas.width, canvas.height);

    cc.beginPath();

    // 回転の中心は原点なので、
    // 一度図形の中心を原点に移してから回転させて
    // 元の場所に戻す
    cc.translate(canvas.width / 2, canvas.height / 2);
    cc.rotate(theta);
    cc.translate(-rectWidth / 2, -rectHeight / 2);
    cc.fillRect(0, 0, rectWidth, rectHeight);

    cc.restore();

    cc.fillText('FPS : ' + fps.getFPS(), 10, 20);

    theta += 5 * Math.PI / 180;
    if(Math.PI * 2 < theta) {
        theta = 0;
    }

    setTimeout(loop, fps.getInterval());
};

loop();

※サンプルではぐるんぐるん回ってます

サンプル

FPSというクラスを定義して、一定時間おきにloop関数を呼び出しています。 FPSの表示にはテキストを描画するfillText()を使っています。

おまけ

「ボールが弾む動作」というものも比較的簡単に書けます。 高校物理の速度と加速度の計算を使うわけです。 アクションゲームのたぐいをつくったことがある方なら朝飯前でしょう。

サンプル

ただ弾むだけではおもしろくないので、 Firefoxの加速度を取得する機能を使ってノートPCの傾きに対応するようにしてみました。 ディスプレイを思いっきり開いてPCを振り回せば、それっぽい動きをするんじゃないかと思います。

サンプル

※バージョン3.6以降のFirefoxを、MacBookやThinkpadなどの加速度センサがついたPCで開いてみてください。

おわり

面倒な設定いらずで、手軽に使えるcanavs要素。 WebGLなどの3D描画APIも開発されているということですし、 今後使われる機会も増えるんじゃないでしょうか。

Flashに取って代わるまでは行かないまでも、 簡単なアニメーションやゲームなどは充分につくることができるのではないかと思います。

カヤックでは新しもの好きな技術者を募集しています!