忍者ブログ

Memeplexes

プログラミング、3DCGとその他いろいろについて

ブログでHTML5 Canvas入門一覧

今まで書いたものをまとめます。
HTML5のCanvasを使うチュートリアルというか、入門記事です。
  1. 長方形を描画
  2. 塗りつぶしスタイル
  3. パス
  4. パスの線
  5. パスを塗りつぶす
  6. 画像
  7. テキスト
  8. クリップ
  9. コンテキストの保存とリストア
  10. クリア
  11. 座標変換
  12. ピクセル操作
  13. アニメーション
  14. マウスイベント
  15. キーボードイベント
15.アニメーション、16.マウスイベント、17.キーボードイベントはなんだかあんまりHTML5と関係がないような気もしますが、HTML+JavaScriptを扱った人がない人のために書きました。

拍手[0回]

PR

ブログでHTML5 Canvas キーボードイベント

keyupイベント

キーボードのキーが離された時のイベントを拾ってみましょう。
<canvas id="keyUpEventDemoCanvas" width="300" height="200"></canvas>
<script src="http://file.memeplex.blog.shinobi.jp/onKeyUp.js">
</script>

onKeyUp.js
    (function () {
        var canvas = document.getElementById("keyUpEventDemoCanvas");
        canvas.containsMouse = function (mousePosition) {
            var clientRect = this.getBoundingClientRect();
            return clientRect.left < mousePosition.x
                && mousePosition.x < clientRect.right
                && clientRect.top < mousePosition.y
                && mousePosition.y < clientRect.bottom;
        };
        var mousePosition = new Object();

        document.addEventListener(
            "mousemove",
            function (e) {
                mousePosition.x = e.clientX;
                mousePosition.y = e.clientY;
            }
            );

        document.addEventListener(
            "keyup",
            function (e) {
                if (canvas.containsMouse(mousePosition)) {
                    alert("key up");
                }
            });
    })();


上のcanvas(空白)の中でキーを離してみて下さい。
メッセージボックスが表示されます。

このプログラムはやや、ややこしいです(冗談ではありません)。
なぜこうなってしまったのかというと、マウスイベントとキーボードイベント両方を聴いているからです。
実は、canvasのキーボードイベントは、聴けないようなのです。
そこでcanvasではなくdocumentのキーボードイベントを聞くわけですが、そうするとページすべてでキーが押されたかどうかを聴くことになってしまいます。
ブログだとそれでは少しまずいです。
キーボードイベントを聴くキャンバスがもし2つあったら?
なんだかややこしいことになりそうですね。

そこでここでは、今マウスが上にあるキャンバスでだけ、メッセージボックスを表示するようにしています。













拍手[0回]


ブログでHTML5 Canvas マウスイベント

マウスボタンが押された時

HTML5特有の話ではありませんが、今回はマウスイベントを拾ってみましょう。
たとえばマウスボタンが押された時何かします。
<canvas id="mouseDownEventDemoCanvas" width="300" height="200"></canvas>
<script>
    (function () {
        var canvas = document.getElementById("mouseDownEventDemoCanvas");

        canvas.addEventListener(
            "mousedown",
            function (e) {
                alert("mouse down");
            });
    })();
</script>


上の空間をマウスでクリックしてみて下さい。
メッセージボックスが表示されます。

canvas.addEventListener(type, listener, useCapture)はイベントリスナーを登録するメソッドです。
あるイベントが起きた時、何をするかを登録するのです。
(例えば上の場合ではマウスのボタンが押された時、メッセージボックスを表示します。)

typeはイベント名です。"click"や"mousedown"を指定します。(前者はマウスのボタンが離された時、後者はマウスのボタンが押された時です)

listenerはイベントが起きた時実行する関数です。

useCaptureはイベントハンドラを追加するイベントフェイズです。

ちなみに、listenerの引数(上の例で言うとe)は、マウスイベントオブジェクトです。
次で詳しく説明します。


クリックされた時

次はクリックされた時に何かしてみましょう。

<canvas id="clickEventDemoCanvas" width="300" height="200"></canvas>
<script>
    (function () {
        var canvas = document.getElementById("clickEventDemoCanvas");

        canvas.addEventListener(
            "click",
            function (e) {
                var bounds = canvas.getBoundingClientRect();
                alert("X" + (e.clientX - bounds.left)+ " ,Y" + (e.clientY - bounds.top));
            });
    })();
</script>



イベントリスナーの引数eはMouseEventオブジェクトです。
次のようなプロパティがあります。

プロパティ 説明
screenX マウスポインタのスクリーン上のX座標を取得します。
screenY マウスポインタのスクリーン上のY座標を取得します。
clientX マウスポインタのDOMコンテント上のX座標を取得します。
clientY マウスポインタのDOMコンテント上のY座標を取得します。
ctrlKey イベントが起きた時、ctrlキーが押されていればtrue、そうでなければfalseを取得します。
shiftKey イベントが起きた時、shiftキーが押されていればtrue、そうでなければfalseを取得します。
altKey イベントが起きた時、altキーが押されていればtrue、そうでなければfalseを取得します。
metaKey イベントが起きた時、meta/ctrlキーが押されていればtrue、そうでなければfalseを取得します。
button イベントを起こしたマウスボタンを取得します。
buttons ユーザーが押しているマウスボタンを取得します。
relatedTarget 関連した要素を取得します。たとえばonmouseoutイベントではマウスポインタが入った要素を表します。(マウスポインタが出た要素はtargetで取得します。)







拍手[0回]


ブログでHTML5 Canvas アニメーション

window.requestAnimationFrame()メソッド

今回はアニメーションをします。
ただし、今回使うwindow.requestAnimationFrame()メソッドは、ブラウザによってはサポートされていないので注意して下さい。
ここでは、Chromeで動作確認しました。

<canvas id="drawAnimatedRectCanvas" width="300" height="300"></canvas>
<script>
    (function ()
    {
        var canvas = document.getElementById("drawAnimatedRectCanvas");
        var context = canvas.getContext("2d");
        var time = 0;

        function drawFrame()
        {
            window.requestAnimationFrame(drawFrame);
            context.clearRect(0, 0, canvas.width, canvas.height);
            time += 1.0 / 60;
            context.fillRect(0, 100 * (1 + Math.sin(time)), 100, 100);
        }

        drawFrame();
    })();
</script>

ここで使ったのは、

window.requestAnimationFrame(drawFrame);

です。
このメソッドはアニメーションを行なってくれます。
drawFrameには次に行う描画のメソッドを指定します。
そうすると、このメソッドはdrawFrameを呼び出してくれ、アニメーションになるのです。

window.setInterval()メソッド
アニメーションにはこんな方法を使うこともできます。
むしろこちらのほうがわかりやすいという人もいると思います(私がそうです)。
ただしこの方式には欠点もあるので気をつけましょう。

<canvas id="drawSetIntervalDemoCanvas" width="300" height="300"></canvas>
<script>
    (function () {
        var canvas = document.getElementById("drawSetIntervalDemoCanvas");
        var context = canvas.getContext("2d");
        var time = 0;
        var dTime = 1.0 / 60;

        window.setInterval(
            function () {
                context.clearRect(0, 0, canvas.width, canvas.height);
                time += dTime;
                context.fillRect(0, 100 * (1 + Math.sin(time)), 100, 100);
            },
            dTime * 1000
            );
    })();
</script>


window.setInterval(expression, milliseconds, language);メソッドは引数の関数を指定した間隔で呼び続けます。
絵をすこしずつ変えて描くメソッドを引数にすれば、アニメーションが描けるというわけですね。
expressionは指定した時間が立った時に呼び出される関数です。
millisecondsは時間間隔です。(単位はミリセカンド、1/1000秒です)
languageは省略可能です。LANGUAGE属性に指定可能な文字列です。"JScript"や"JavaScript"などですね。



拍手[1回]


ブログでHTML5 Canvas ピクセル操作

ここまではメソッドを使って図形を描いて来ました。
しかしピクセル単位で絵を描きたいこともあるでしょう。
ここでは、あるピクセルの色を取得し、あるピクセルに色を書き込む方法を紹介します。
<canvas id="drawInversedImageCanvas" width="300" height="200"></canvas>
<script 
    type="text/JavaScript" 
    src="http://file.memeplex.blog.shinobi.jp/drawInversedImage.js">
</script>


drawInversedImage.js
(function() {
    var canvas = document.getElementById("drawInversedImageCanvas");
    var context = canvas.getContext("2d");
    context.fillStyle = "rgb(0, 0, 255)";
    context.fillRect(0, 0, 100, 100);
    context.strokeStyle = "rgb(255, 255, 255)";
    context.strokeRect(10, 10, 80, 80);
    var imageData = context.getImageData(0, 0, 100, 100);

    for (var i = 0; i < imageData.data.length; i += 4) {
        var max = 255;
        imageData.data[i + 0] = max - imageData.data[i + 0];
        imageData.data[i + 1] = max - imageData.data[i + 1];
        imageData.data[i + 2] = max - imageData.data[i + 2];
        imageData.data[i + 3] = max;
    }

    context.putImageData(imageData, 100, 0);
})();



このプログラムは左に描いた画像を、右にコピーしています。
ただし、白と黒が反対になっています。

context.getImageData(x, y, width, height);

getImageDataはImageDataオブジェクトを返します。
つまり、指定した矩形エリアのピクセルデータを返すわけです。

xは指定するエリアの左上のx座標。
yは指定するエリアの左上のy座標。
widthは指定するエリアの横幅。
heightは指定するエリアの縦幅です。


イメージデータを作成

イメージデータを0から作り出すこともできます。
<canvas id="drawWaveCanvas" width="300" height="200"></canvas>
<script 
    type="text/JavaScript" 
    src="http://file.memeplex.blog.shinobi.jp/drawGradationManually.js">
</script>


drawGradationManually.js
(function() {
    var canvas = document.getElementById("drawGradationManuallyCanvas");
    var context = canvas.getContext("2d");
    var size = { width: 200, height: 100 };
    var imageData = context.createImageData(size.width, size.height);

    for (var x = 0; x < size.width; x++) {
        for (var y = 0; y < size.height; y++) {
            var pixelIndex = x + y * size.width;
            var dataIndex = pixelIndex * 4;
            var max = 255;
            imageData.data[dataIndex + 0] = max * x / size.width;
            imageData.data[dataIndex + 1] = max * y / size.height;
            imageData.data[dataIndex + 2] = max;
            imageData.data[dataIndex + 3] = max;
        }
    }

    context.putImageData(imageData, 0, 0);
})();



このプログラムは右に行くほど赤く、下に行くほど緑になる画像を表示します。

context.createImageData(width, height);

widthは、新しく作られるImageDataの横幅を表します。
heightは、新しく作られるImageDataの縦幅を表します。

拍手[0回]