HTML5 Canvas の謎

謎というか私がなにかを理解していないだけなんだろうけど。。Canvasを作る作り方によっては、サイズが上手く設定されない、というおはなし。

Canvas の作成

200x200のCanvas を4つの方法でつくってみる。まずは、普通に静的に作る。

<div id="placeHolder">
    <canvas id="static" width="200" height="200"></canvas>
</div>

次に3つの方法で動的に作る。

$("#placeHolder").append($('<canvas ' + 
       'id="dynamic0" width="200" height="200" ></canvas>'));

$("#placeHolder").append($('<canvas/>', {
        id: "dynamic1",
        width: 200,
        height: 200
}));

$("#placeHolder").append($('<canvas/>', {
        id: "dynamic2"
}));

'dynamic2' は別途 cssでサイズを指定する。

        #dynamic2 {
            width: 200px;
            height: 200px;
        }

こうすると、200 x 200の正方形のcanvasが4つできる。見た目は全く同じ(実はdynamic2だけなんかpaddingが違うような気もするがこの理由もわからない)だが、実は中身がぜんぜん違うらしいのだ。

どう違うのか

次のようにして、(0,0)から 中心の(100, 100) まで線を引いてみる。

            $("canvas").click(function(){
                var context = this.getContext("2d");
                context.moveTo(0, 0);
                context.lineTo(100, 100);
                context.stroke();
            });


するとこうなる。

上の2つ(static と dynamic0 は)期待通り真ん中まで線が引かれているが、下の二つは変なところに線が行っている。なんなんだ。。。

widthとheight

次のようにしてcanvasの幅と高さを表示させてみる。

   $("canvas").click(function(){alert(this.width + ", "+ this.height)});

すると、うえの2つはちゃんと200,200になっているが、下の二つは300,150になる。つまり画面上は200x200なのだが、内部的には300x150になっているらしい。

この300x150という変な値がどこから来たのか調べてみたところ、canvasのデフォルト値らしい。つまり、一度初期値で作成されたキャンバスが外部サイズだけ書き換えられて再利用されているのだろう。dynamic2のように、完全にcssで制御する場合には、実際そういう動作になるだろうからなんとなく理解できる。

しかしdynamic1 まで同じになるのは、ちょっと納得がいかない。jQueryの内部動作として、一度デフォルトサイズ作ったCanvasのサイズを後から変える、というように動いてるんだろうか。

所感

HTML、CSSJavaScriptは謎が多すぎてキツイ。。。WebStormを導入することでJavaScriptの記述自体はずいぶん楽になったけど、こういう小さい落とし穴がたくさんあるからなあ。

追記:実装が異なる firefoxchrome で全く同じ動作なので、多分仕様どおりの挙動なんだろう。わけわからんけど。。