CanvasとSVG | パークのソフトウエア開発者ブログ|ICT技術(Java・Android・iPhone・C・Ruby)なら株式会社パークにお任せください

パークのソフトウエア開発者ブログ|ICT技術(Java・Android・iPhone・C・Ruby)なら株式会社パークにお任せください

開発の解決方法や新しい手法の情報を、パークのエンジニアが提供します。パークのエンジニアが必要な場合は、ぜひお気軽にお問い合わせ下さい。 株式会社パーク:http://www.pa-rk.co.jp/

こんにちは。

HTML5のCanvasとSVGについて、様々な観点から比較していきたいと思います。

動作環境
今回の比較は下記の環境で行います。
OS:Windows7 64bit
メモリ:4GB
CPU:Intel Core2Duo E8400 3.00GHz

描画速度
単純に円を描画するだけの速度を比較してみます。
ちなみにソースコードはこんな感じ↓
window.onload = function() {
    var time = new Date().getTime();

    var div_canvas = document.getElementById("canvas");
    var canvas = document.createElement("canvas");
    div_canvas.appendChild(canvas);

    canvas.width = width;
    canvas.height = height;

    var ctx = canvas.getContext('2d');

    var r = radius;
    for( var i=0; i<width; i+=(r*2) ){
        for( var j=0; j<height; j+=(r*2) ){
            ctx.beginPath();
            ctx.arc( i, j, r, 0, Math.PI*2, false);
            ctx.fillStyle = '#FF0000';
            ctx.fill();
        }
    }

    console.log( new Date().getTime() - time );
}



window.onload = function() {

    var time = new Date().getTime();

    svg = document.createElementNS("http://www.w3.org/2000/svg","svg");
    svg.setAttribute('width', width);
    svg.setAttribute('height', height);

    var div_svg = document.getElementById("svg");
    div_svg.appendChild(svg);

    var r = radius;
    for( var i=0; i<width; i+=(r*2) ){
        for( var j=0; j<height; j+=(r*2) ){
            var circle = document.createElementNS("http://www.w3.org/2000/svg","circle");
            circle.cx.baseVal.value = i;
            circle.cy.baseVal.value = j;
            circle.r.baseVal.value = r;
            circle.style.strokeWidth = 0;
            circle.style.fill = "#FF0000";

            svg.appendChild(circle);
        }
    }
    
    console.log( new Date().getTime() - time );
}



描画速度(ms) radius = 10,width=2000,height=2000
ブラウザCanvasSVG
Chome21185
IE9207258
FireFox192460


描画速度(ms) radius = 100,width=2000,height=2000
ブラウザCanvasSVG
Chome12
IE923
FireFox426


描画速度(ms) radius = 1,width=200,height=200
ブラウザCanvasSVG
Chome46184
IE9140256
FireFox114456


上から順に、
・大量オブジェクト且つ描画領域大
・少量オブジェクト且つ描画領域大
・大量オブジェクト且つ描画領域小
を検証しています。

表を見て分かるように、下記のような結果になりました。
・全体的にSVGよりもCanvasの方が描画が早い。
・SVGはオブジェクト数に速度が依存している。
・Canvasはオブジェクト数・描画領域サイズに速度が依存している。

メモリ使用量

ソースコードは上記と同様です。

メモリ使用量(KB) radius = 10,width=2000,height=2000
ブラウザCanvasSVG
Chome1224434316

メモリ使用量(KB) radius = 100,width=2000,height=2000
ブラウザCanvasSVG
Chome1227226916

メモリ使用量(KB) radius = 1,width=200,height=200
ブラウザCanvasSVG
Chome1202035140


表を見て分かるように、下記のような結果になりました。
・全体的にSVGよりもCanvasの方がメモリ使用量が少ない。
・SVGはオブジェクト数にメモリ使用量が依存している。

各円に対するクリック

円をクリックした際に、円の色を青色に変えるコードを比較してみます。


var Circle = function(x, y, r, fill) {
    this.x = x;
    this.y = y;
    this.r = r;
    this.fill = fill;
};

Circle.prototype.draw = function(ctx){
    ctx.beginPath();
    ctx.arc( this.x, this.y, this.r, 0, Math.PI*2, false);
    ctx.fillStyle = this.fill;
    ctx.fill();
};

window.onload = function() {

    var time = new Date().getTime();

    var div_canvas = document.getElementById("canvas");
    var canvas = document.createElement("canvas");
    div_canvas.appendChild(canvas);

    canvas.width = 2000;
    canvas.height = 2000;

    var ctx = canvas.getContext('2d');

    var circles = new Array();

    var r = 10;
    for( var i=0; i<2000; i+=(r*2) ){
        for( var j=0; j<2000; j+=(r*2) ){
            var circle = new Circle(i, j, r, '#FF0000');
            circles.push(circle);
            circle.draw(ctx);
        }
    }

    var click = function(e){
        var x = e.layerX;
        var y = e.layerY;
        for (var i = 0; i < circles.length; i++){
            var dx = x - circles[i].x;
            var dy = y - circles[i].y;
            var d = Math.sqrt(dx*dx+dy*dy);
            if(d <= circles[i].r){
                circles[i].fill = '#0000FF';
                circles[i].draw(ctx);
                break;
            }
        }
    };

    canvas.addEventListener('click', click, false);

    console.log( new Date().getTime() - time );
}



window.onload = function() {

    var time = new Date().getTime();

    svg = document.createElementNS("http://www.w3.org/2000/svg","svg");
    svg.setAttribute('width', '2000');
    svg.setAttribute('height', '2000');

    var div_svg = document.getElementById("svg");
    div_svg.appendChild(svg);

    var r = 10;
    for( var i=0; i<2000; i+=(r*2) ){
        for( var j=0; j<2000; j+=(r*2) ){
            var circle = document.createElementNS("http://www.w3.org/2000/svg","circle");
            circle.onclick = function(){
                this.style.fill = "#0000FF";
            }
            circle.cx.baseVal.value = i;
            circle.cy.baseVal.value = j;
            circle.r.baseVal.value = r;
            circle.style.strokeWidth = 0;
            circle.style.fill = "#FF0000";
            svg.appendChild(circle);
        }
    }
    console.log( new Date().getTime() - time );
}


SVGは各円がオブジェクトになっているため簡単に実装できますが、
Canvasは座標からどの円がクリックされたかを割り出す必要があるため、
SVGに比べると手間がかかります。


結論
今回は単純な円の描画なので単純に結論は出せませんが。。。

個人的には膨大な数のオブジェクトを描画する必要がある場合は、
パフォーマンス的にCanvasの方がいいのかなと感じています。

ただ、SVGには拡大しても画質が劣化しないという強みがあるため、
きれいに描画したい場合はSVGの方がいいですね。