忍者ブログ

Memeplexes

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

[PR]

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。


ブログでHTML5 Canvas入門一覧

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

拍手[0回]

PR

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

keyupイベント

キーボードのキーが離された時のイベントを拾ってみましょう。
<canvas id="keyUpEventDemoCanvas" width="300" height="200"></canvas>
<script src="http://nblog.cnobi.jp/v1/blog/user/118c300f2ee0ad311e5962b0167205f5/1371908340">
</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://nblog.cnobi.jp/v1/blog/user/118c300f2ee0ad311e5962b0167205f5/1371278164">
</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://nblog.cnobi.jp/v1/blog/user/118c300f2ee0ad311e5962b0167205f5/1371278220">
</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回]