web-dev-qa-db-ja.com

HTML5キャンバス対SVG対div

その場で要素を作成し、それらを移動できるようにするための最善の方法は何ですか?たとえば、長方形、円、多角形を作成してから、それらのオブジェクトを選択して移動したいとします。

私はHTML5がこれを可能にすることができる3つの要素を提供することを理解します: svgcanvas そして div 。私がやりたいことのために、それらの要素のどれが最高のパフォーマンスを提供するでしょうか?

これらのアプローチを比較するために、3つの視覚的に同一のWebページを作成することを考えていました。それぞれのWebページには、ヘッダー、フッター、ウィジェット、およびテキストコンテンツが含まれています。最初のページのウィジェットは完全にcanvas要素で、2番目のウィジェットはsvg要素で、3番目のウィジェットはプレーンのdiv要素で、HTMLとCSSで作成されます。

438
verdy

短い答え:

選択と移動はすでに組み込まれているため、SVGはより簡単です。SVGオブジェクトはDOMオブジェクトなので、「クリック」ハンドラーなどがあります。

DIVは大丈夫ですが、不格好で、大量にawfulパフォーマンスをロードします。

Canvasには最高のパフォーマンスがありますが、管理状態のすべての概念(オブジェクト選択など)を自分で実装するか、ライブラリを使用する必要があります。


長い答え:

HTML5 Canvasは、単にビットマップの描画面です。描画するように設定し(色と線の太さで言う)、そのことを描画すると、キャンバスはそのことを認識しません:描画した場所や描画したものがわかりません。ただのピクセル。長方形を描き、それらを動かしたり選択可能にしたい場合は、そのすべてを最初からコーディングする必要がありますincludeそれらを描いた。

一方、SVGは、レンダリングする各オブジェクトへの参照を維持する必要があります。作成するすべてのSVG/VML要素は、DOMの実際の要素です。デフォルトでは、これにより、作成した要素をはるかに追跡しやすくなり、マウスイベントなどの処理がデフォルトで簡単になりますが、多数のオブジェクトがある場合は大幅に遅くなります

これらのSVG DOM参照は、描画するものを扱うためのフットワークの一部があなたのために行われることを意味します。また、SVGは本当に大きなオブジェクトをレンダリングする場合は高速ですが、多くのオブジェクトをレンダリングする場合は遅くなります。

おそらく、Canvasでのゲームの方が高速です。巨大なマッププログラムは、おそらくSVGで高速になります。 Canvasを使用したい場合は、可動オブジェクトの起動と実行に関するチュートリアルがあります here

Canvasは高速な処理やビットマップ操作(アニメーションなど)には適していますが、多くのインタラクティブ機能が必要な場合は、より多くのコードが必要になります。

HTML DIVで作成した描画とCanvasで作成した描画で多数の数値を実行しました。それぞれの利点について大きな投稿をすることもできますが、特定のアプリケーションについて検討するために、テストの関連する結果の一部を提供します。

CanvasとHTML DIVのテストページを作成しました。どちらも移動可能な「ノード」を備えていました。 Canvasノードは、私が作成し、Javascriptで追跡したオブジェクトです。 HTMLノードは移動可能なDivでした。

2つのテストのそれぞれに100,000個のノードを追加しました。彼らは非常に異なって実行しました:

HTMLテストタブの読み込みに時間がかかりました(5分弱のタイミングで、chromeは最初にページを強制終了するように要求しました)。 Chromeのタスクマネージャーは、タブが168MBを占有していると言います。私が見ているときは12-13%のCPU時間を、見ていなければ0%を消費します。

Canvasタブは1秒で読み込まれ、30MBを占有します。また、CPU時間の13%を占有します。これは、誰かが見ているかどうかに関係ありません。 (2013編集:ほとんど修正済み)

現在の設定ではCanvasテストで30ミリ秒ごとにすべてを再描画するため、HTMLページでのドラッグはよりスムーズです。このためにCanvasには多くの最適化が必要です。 (キャンバスの無効化が最も簡単で、クリッピング領域、選択的な再描画なども、実装する気分に依存します)

この単純なテストのdivとしてCanvasをオブジェクト操作で高速化し、もちろん読み込み時間ではるかに高速にすることができたことは間違いありません。 Canvasでは描画/読み込みが高速で、最適化の余地もはるかにあります(つまり、画面外のものを除外するのは非常に簡単です)。

結論:

  • SVGはおそらく、少数のアイテム(1000未満ですか?実際に依存します)のアプリケーションおよびアプリに適しています。
  • Canvasは何千ものオブジェクトと注意深い操作には適していますが、それを地面から取り出すにはさらに多くのコード(またはライブラリ)が必要です。
  • HTML Divは不格好でスケールしないので、丸い角は丸い角でのみ可能です。複雑な形状を作ることは可能ですが、数百の小さなピクセル幅のdivが必要です。狂気が続きます。
535
Simon Sarris

これに加えて、私はダイアグラムアプリケーションをやってきました、そして最初はキャンバスから始めました。ダイアグラムは多数のノードで構成されており、非常に大きくなる可能性があります。ユーザーはダイアグラム内の要素をドラッグすることができます。

私が見つけたのは、私のMacでは、非常に大きな画像の場合、SVGが優れているということでした。私はMacBook Pro 2013 13 "Retinaを持っていて、下のフィドルをうまく動かしている。画像は6000x6000ピクセルで、1000個のオブジェクトがある。図.

最近のディスプレイでは、さまざまな解像度も考慮する必要があります。ここでは、SVGがこれらすべてを無料で提供しています。

フィドル: http://jsfiddle.net/knutsi/PUcr8/16/

フルスクリーン: http://jsfiddle.net/knutsi/PUcr8/16/embedded/result/

var wiggle_factor = 0.0;
nodes = [];

// create svg:
var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg.setAttribute('style', 'border: 1px solid black');
svg.setAttribute('width', '6000');
svg.setAttribute('height', '6000');

svg.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xlink",
    "http://www.w3.org/1999/xlink");

document.body.appendChild(svg);


function makeNode(wiggle) {
    var node = document.createElementNS("http://www.w3.org/2000/svg", "g");
    var node_x = (Math.random() * 6000);
    var node_y = (Math.random() * 6000);
    node.setAttribute("transform", "translate(" + node_x + ", " + node_y +")");

    // circle:
    var circ = document.createElementNS("http://www.w3.org/2000/svg", "circle");
    circ.setAttribute( "id","cir")
    circ.setAttribute( "cx", 0 + "px")
    circ.setAttribute( "cy", 0 + "px")
    circ.setAttribute( "r","100px");
    circ.setAttribute('fill', 'red');
    circ.setAttribute('pointer-events', 'inherit')

    // text:
    var text = document.createElementNS("http://www.w3.org/2000/svg", "text");
    text.textContent = "This is a test! ÅÆØ";

    node.appendChild(circ);
    node.appendChild(text);

    node.x = node_x;
    node.y = node_y;

    if(wiggle)
        nodes.Push(node)
    return node;
}

// populate with 1000 nodes:
for(var i = 0; i < 1000; i++) {
    var node = makeNode(true);
    svg.appendChild(node);
}

// make one mapped to mouse:
var bnode = makeNode(false);
svg.appendChild(bnode);

document.body.onmousemove=function(event){
    bnode.setAttribute("transform","translate(" +
        (event.clientX + window.pageXOffset) + ", " +
        (event.clientY + window.pageYOffset) +")");
};

setInterval(function() {
    wiggle_factor += 1/60;
    nodes.forEach(function(node) {

        node.setAttribute("transform", "translate(" 
                          + (Math.sin(wiggle_factor) * 200 + node.x) 
                          + ", " 
                          + (Math.sin(wiggle_factor) * 200 + node.y) 
                          + ")");        
    })
},1000/60);
37
knut

SVGとCanvasの違いを知っていると、正しいものを選択するのに役立ちます。

キャンバス

SVG

  • 解像度に依存しない
  • イベントハンドラのサポート
  • レンダリング領域が広いアプリケーションに最適(Googleマップ)
  • 複雑な場合はレンダリングが遅くなります(DOMを多用するものはすべて遅くなります)。
  • ゲームアプリケーションには適していません
22
Leo The Four

Simon Sarrisの結論に同意します。

私は、Protovis(SVG)での視覚化と、2000ポイントを超えるProcessingjs(Canvas)とを比較しました。processingjsは、protovisよりはるかに高速です。

SVGを使ってイベントを処理することは、オブジェクトにそれらを結び付けることができるので、もちろんずっと簡単です。 Canvasでは手動で行う必要があります(マウスの位置などを確認してください)が、簡単な操作ではそれほど難しいことではありません。

Dojoツールキットの dojo.gfx ライブラリーもあります。抽象化レイヤを提供し、レンダラ(SVG、Canvas、Silverlight)を指定できます。追加の抽象化レイヤがどれほどのオーバーヘッドを追加するのかわからないが、それは実行可能な選択かもしれませんが、それはインタラクションやアニメーションをコーディングするのを容易にし、そしてレンダラにとらわれません。

ここにいくつかの興味深いベンチマークがあります:

18
Ümit

Divsオプションに関して私の2セントだけ。

Famous/InfamousとSamsaraJS(そしておそらく他の人たち)は、絶対配置されたネストされていないdivを(自明でないHTML/CSSコンテンツと共に)ポジショニングと2D/3D変換に組み合わせ、中程度のモバイルハードウェアで安定した60FPSを達成します。だから、私はdivが遅い選択であることに対して議論したいと思います。

Youtubeや他の場所にはたくさんのスクリーンレコーディングがあり、高性能の2D/3Dのものはすべてブラウザで動作し、60FPSでInspect Elementonにすることができます。 WebGLは特定の効果を提供しますが、レンダリングの主要部分は対象外です。

16
Erik Allik

あなたの目的のために、私はSVGを使うことを勧めます、ドラッグアンドドロップを含むマウス操作のようなDOMイベントを含むので、あなたはあなた自身の再描画を実装する必要はありませんあなたの物あなたがビットマップ画像操作をしなければならないときにCanvasを使います、そしてあなたがHTMLで作成されたものを操作したいときに通常のdivを使います。パフォーマンスに関しては、最近のブラウザが3つすべてを加速させていることがわかりますが、キャンバスはこれまでのところ最も注目を集めています。一方、キャンバスで最高のパフォーマンスを引き出すには、JavaScriptをどの程度うまく記述するかが重要です。そのため、SVGを使用することをお勧めします。

13
Gaurav

上記の答えのほとんどにはまだいくつかの真実がありますが、私はそれらが更新に値すると思います:

何年にもわたってSVGのパフォーマンスは大幅に向上しており、現在はSVG用のハードウェアアクセラレーションによるCSSトランジションおよびアニメーションがあり、JavaScriptのパフォーマンスにはまったく依存していません。もちろん、JavaScriptのパフォーマンスもCanvasのパフォーマンスも向上していますが、SVGほどは向上していません。また、今日のほとんどすべてのブラウザで利用可能なブロック上に「新しい子供」があります。それはWebGLです。 Simonが上記で使用したのと同じ単語を使用するには、これはCanvasとSVGの両方を撃退します。しかしこれは、それがGo-to-Technologyであるべきという意味ではありません。

今日のほとんどのユースケースでは、私見、SVGは最高のパフォーマンス/ユーザビリティの比率を提供します。 Canvas、さらにはWebGLがさらに輝くように、視覚化は(要素数に関して)非常に複雑で、同時に(要素ごとに)非常に単純である必要があります。

この質問に答える 私はより多くの詳細を提供しています、なぜ私はすべての3つの技術の組み合わせがあなたが持っている最良の選択肢であると思う。

12
Sebastian

グーグルしながら私は http://)でSVGCanvasの使用法と圧縮についての良い説明を見つけます。 teropa.info/blog/2016/12/12/graphics-in-angular-2.html

それが役に立てば幸い:

  • HTMLと同じように、SVGは保持レンダリングを使用します:画面上に長方形を描画する場合は、宣言的にDOMの要素を使用します。ブラウザは長方形を描画しますが、長方形を表すインメモリ SVGRectElement オブジェクトも作成します。このオブジェクトは私たちが操作するために固執するものです - それは保持されます。時間の経過とともに、さまざまな位置やサイズを割り当てることができます。インタラクティブにするためにイベントリスナーを添付することもできます。
  • Canvasは即時レンダリングを使用します。 長方形を描く の場合、ブラウザは直ちにスクリーン上に長方形をレンダリングしますが、「長方形」は存在しません。それを表す "オブジェクト"です。キャンバスバッファにはたくさんのピクセルがあります。四角形は移動できません。別の四角形しか描けません。四角形のクリックやその他のイベントには反応できません。キャンバス全体のイベントにのみ応答できます

そのため、キャンバスはSVGよりも低レベルで制限のあるAPIです。しかし、それに対する裏返​​しがあります、それはキャンバスであなたが同じ量のリソースでより多くをすることができるということです。ブラウザは描画したものすべてのインメモリオブジェクトグラフを作成して維持する必要がないため、同じビジュアルシーンを描画するために必要なメモリおよび計算リソースが少なくて済みます。あなたが描くべき非常に大きくて複雑な視覚化を持っているならば、キャンバスはあなたのチケットかもしれません。

2
Alireza Fattahi