web-dev-qa-db-ja.com

JavaScript操作のためにHTMLに外部SVGを埋め込む

地理的な地域を示すSVG画像があります。 http://upload.wikimedia.org/wikipedia/commons/7/71/Nederland_gemeenten_2009.svg

WebページにSVG画像を表示し、JavaScriptとCSSの組み合わせを使用して画像とやり取りしたい。 (つまり、領域のクリックを検出し、領域に異なる背景色を設定します)。

StackOverflowでこの質問が何度も尋ねられることは知っていますが、さらに作業を進めるための完全なコードサンプルは見つかりません。 jQueryなどのJavaScriptパッケージまたはプラグインに関する推奨事項を歓迎します。

34
Gerrit

この質問に対する私の理解は、解決すべきさまざまな側面があるということです。

  1. 相互作用のために画像を準備する方法
  2. ページに画像を埋め込む方法
  3. SVGでCSSを使用する方法
  4. インタラクションにJavaScriptを使用する方法

画像の準備

まず、画像をクリーンアップすることをお勧めします。 Inkscapeは、_sodipodi:_名前空間と_inkscape:_名前空間の要素と属性、繰り返しおよび/または冗長なスタイル属性を含む、必要のないあらゆる種類のものをそこに残します。 haveを削除することはありませんが、帯域幅/読み込み時間を節約できます。CSSマッチングを使用する場合は、スタイル属性が邪魔になります。

サンプルファイルでは、同じスタイル属性が472倍あります。それらをすべて削除し、同等のCSSルールを一度作成します。

自治体に関する情報をマークアップに追加することもできます。あなたは例えば市町村を表す各パスのIDを名前に従って変更します。この目的で_data-*_属性を使用することもできます。後者には、スペースを使用できるという利点があります。これがインタラクション、特にCSSでどのように役立つかについては、以下を参照してください。

画像の埋め込み

特にCSS/JavaScriptを操作する場合は、SVGインラインを使用することをお勧めします。つまり、SVGマークアップをHTMLに追加するか、Ajaxを使用してそれをロードして挿入します。後者には、周囲のページの読み込みが速くなり、応答性が向上するという利点があります。

インラインSVG要素の例:

_<div id="svgContainer">
  <!-- This is an HTML div, and inside goes the SVG -->
  <svg xmlns="http://www.w3.org/2000/svg" width="100px" height="100px">
    <circle r="50" cx="50" cy="50" fill="green"/>
  </svg>
</div>
_

Ajaxを使用してSVGをロードする方法の簡単な例:

_xhr = new XMLHttpRequest();
xhr.open("GET","my.svg",false);
// Following line is just to be on the safe side;
// not needed if your server delivers SVG with correct MIME type
xhr.overrideMimeType("image/svg+xml");
xhr.send("");
document.getElementById("svgContainer")
  .appendChild(xhr.responseXML.documentElement);
_

CSSの使用方法

SVGはHTMLと同様にスタイル設定できます。もちろん、SVGには_fill-opacity_や_stroke-dasharray_などの独自のプロパティセットがあり、marginpositionなどの多くのHTMLプロパティをサポートしていません。ただし、セレクターのメカニズムは100%同じです。

_<style>_要素または外部CSSファイル内で、インラインSVGのCSSとHTMLのCSSを混在させることができます。 SVGコードおよびstyle属性内で_<style>_要素を使用することもできます。

SVG要素に意味のあるIDまたは_data-*_属性を与えたとすると、CSSを使用して自治体を強調表示する2つの方法は次のとおりです。

_#Bronckhorst, #Laarbeek {fill:red}
_

または

_*[data-gemeente=Bronckhorst], *[data-gemeente=Laarbeek] {fill:red}
_

または、もちろん、それぞれの要素のスタイル属性を変更できます。プロパティは属性としてもサポートされています。つまり、_style="stroke-width:2"_は_stroke-width="2"_のように指定することもできます。属性とCSSの両方を使用して(style属性、style要素、または外部スタイルシートを使用して)同じプロパティが設定されている場合、CSSは属性をオーバーライドします。

JavaScriptインタラクション

少なくとも単純なVanilla DOMを使用している限り、JavaScriptの相互作用に関してHTMLとSVGの間に基本的な違いはありません。つまり、innerHTMLなどのHTML固有の機能はSVGではサポートされていません(つまり、innerSVGはありません)。ただし、SVGには独自のグラフィックス固有のDOMメソッドのセットがあります( W3C仕様を参照 )。

知っておくべきことの1つは、名前空間の処理です。すべてのSVG要素はSVG名前空間にある必要があり、JavaScriptを使用してそれらを作成する場合、createElementNS()の代わりにcreateElement()を使用する必要があります。

_var use = document.createElementNS("http://www.w3.org/2000/svg","use")
_

同様に、XLink名前空間の属性(つまり_xlink:href_)は、setAttributeNS()の代わりにsetAttribute()を使用して操作する必要があります。

_use.setAttributeNS("http://www.w3.org/1999/xlink","href","#foo")
_

JQueryのようなライブラリはHTML固有の機能に部分的に依存しているため、SVGを操作するときにそれらを避ける方が安全です。 RaphaëlD3.js のようなSVG固有のライブラリもあります。これらは特定の目的に役立ち、一見の価値があります。 Raphaëlは、SVGをサポートしていないHTML5以前のInternet Explorerバージョン6〜8と互換性がある場合に特に便利です。しかし、私が理解しているように、これは、SVGの抽象レイヤーであるため、既存のグラフィックスを操作するのではなく、JavaScriptのみを使用してグラフィックスを生成するのに適しています。 D3.jsは、単純なDOMに満足していない場合、あなたのようなアプリケーションにより適しています(そして、正直なところ、単純にSVG固有のライブラリを呼び出すと、それが不公平になります。

onclickおよび同様の属性と標準DOM addEventListener()を使用できます。 JavaScriptイベントを使用する非常に簡単な例は、ユーザーがクリックした自治体の名前を報告する_<svg>_要素にイベントリスナーを追加することです。

_document.getElementsByTagName("svg")[0]
  .addEventListener("click",function(evt){
    alert(evt.target.getAttribute("data-gemeente"))
  },
  false)
_

サイドノート:ToopltipsHTMLでtitle属性を使用するのと同じ効果は、_<title>_要素を使用して達成できます。 SVGで。 _<title>_要素をSVG要素内に置くと、ホバーすると_<title>_要素の内容を含むツールチップが表示されます。

_<svg xmlns="http://www.w3.org/2000/svg" width="100px" height="100px">
  <rect width="100" height="100">
    <title>test</title>
  </rect>
</svg>
_
88
Thomas W

記録のためだけに(これが1年遅れになることを知っています)、SnapSVGはSVG操作に最適であることがわかりました。ラファエルの背後にいた同じ男:

http://snapsvg.io

8
droid001