HTML5 Canvas API

HTML5 の勉強。
canvas というのを試してみた。

<!DOCTYPE html>
<html>
<head>
<meta charset=UTF-8>
<title>Canvas API</title>

<!-- StyleSeet -->
<style>
body {
    background-color:#c0c0c0;
}
#cvs {
    background-color:#ffffff;
    border:#00ffff 2px solid;
}
</style>

<script>
function draw(num) {
    /* GetDC */
    var ctx = document.getElementById("cvs").getContext("2d");
    /* Clear */
    //ctx.clearRect(0, 0, 400, 200);
    /* Save the Default Setting */
    var globalAlpha = ctx.globalAlpha;
    var fillStyle = ctx.fillStyle;
    /* Branch */
    switch(num) {
    case 0:
        break;
    case 1:
        /* Rectangle */
        var x = 200;
        var y = 20;
        ctx.globalAlpha = 0.3;
        for (var i=0; i<3; i++) {
            ctx.fillRect(x, y, 150, 100);
            x += 30;
            y += 5;
        }
        break;
    case 2:
        /* Circle */
        ctx.globalAlpha = 0.3;
        /* #1 Red */
        ctx.beginPath();
        ctx.fillStyle = 'rgb(255, 0, 0)';
        ctx.arc(70, 45, 35, 0, Math.PI*2, false);
        ctx.fill();
        /* #2 Green */
        ctx.beginPath();
        ctx.fillStyle = 'rgb(0, 255, 0)';
        ctx.arc(45, 95, 35, 0, Math.PI*2, false);
        ctx.fill();
        /* #3 Blue */
        ctx.beginPath();
        ctx.fillStyle = 'rgb(0, 0, 255)';
        ctx.arc(95, 95, 35, 0, Math.PI*2, false);
        ctx.fill();
        break;
    case 3:
        /* Drop Shadow */
        var text = "homuhomu";
        ctx.font = "82px 'sans'";
        ctx.globalAlpha = 0.3;
        ctx.fillText(text, 5, 105);
        ctx.globalAlpha = 1.0;
        ctx.fillText(text, 0, 100);
        break;
    default:
        alert("Error!");
    }
    /* Write back */
    ctx.globalAlpha = globalAlpha;
    ctx.fillStyle = fillStyle;
}
</script>

</head>

<body onLoad="draw(0)">
<canvas id="cvs" width="400" height="200">canvas</canvas><br />
<input type="button" onclick="draw(1)" value="Rectangle">
<input type="button" onclick="draw(2)" value="Circle">
<input type="button" onclick="draw(3)" value="Drop Shadow">
</body>
</html>

なんだよコレ、デバイスコンテキストとほとんど変わらない。
いやオブジェクト化されているから GDI+ なのか、RGBA も利用できるし。

canvas のサンプルコードは検索で沢山見つかるけどグローバル設定を書き戻す処理を入れていない人が多すぎて唖然。
globalAlpha や fillStyle を変更したら元に戻さなければ後々まで引き継がれてしまうんですけど。
デバイスコンテキストではペンやブラシを使ったら元に戻すなんて Windows API をやった人なら常識だよね。
GDI とか全然知らない人ばかりなのだろうか。

てか WM_PAINT と InvalidateRect 関数のようなものはいらないのかな?
ちなみに GnomeShell や Aero では 3D になるからウインドウを重ねても消滅しない。
2D 状態を試すため VirtualBox 仮想マシンの Ubuntu で動かしてみる。

ウインドウを重ねても最小化しても描写が消えない、ココは GDI と少し違う。
どうやって描写状態を記憶しているかは解らないけどそういうこと。

てゆーかフォントのせいではみ出す、絶対値描写はコレが最大の欠点なんだよな…
私が WindowsForm や GtkFixed をバカにしているのは絶対値配置だからですし。
レイアウタ方式なら絶対にはみ出さない、HTML さえもレイアウタ方式だ。

上記コードは重ねるために FillRect していない。
この状態で Circle ボタンを複数回押してみる。

Alpha 値で薄くしても重ねてしまえば当然のように濃い色になる。
やはりボタンやイベントで描写する場合は clearRect 等で一度全体を塗りつぶす必要があるね。
上記コードの Clear 部コメントアウトを外せば一つづつ描写されるようになる。

つまり canvas 2d は GDI のようなものだと。
しかも JavaScript コードも GDI, GDI+ を勉強した人ならすぐ理解できる。
Windows SDK で何かを作れる人は色々試すと面白いかも。