JavascriptでSVG要素にアクセスする方法


83

私はSVGをいじっていて、IllustratorでSVGファイルを作成し、Javascriptで要素にアクセスできることを望んでいました。

これがIllustratorがキックアウトするSVGファイルです(削除したファイルの先頭に大量のジャンクが追加されているようです)

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     width="276.843px" height="233.242px" viewBox="0 0 276.843 233.242" enable-background="new 0 0 276.843 233.242"
     xml:space="preserve">
<path id="delta" fill="#231F20" d="M34.074,86.094L0,185.354l44.444,38.519l80.741-0.74l29.63-25.186l-26.667-37.037
    c0,0-34.815-5.926-37.778-6.667s-13.333-28.889-13.333-28.889l7.407-18.519l31.111-2.963l5.926-21.481l-12.593-38.519l-43.704-5.185
    L34.074,86.094z"/>
<path id="cargo" fill="#DFB800" d="M68.148,32.761l43.704,4.445l14.815,42.963l-7.407,26.667l-33.333,2.963l-4.444,14.074
    l54.074-1.481l22.222,36.296l25.926-3.704l25.926-54.074c0,0-19.259-47.408-21.481-47.408s-31.852-0.741-31.852-0.741
    l-19.259-39.259L92.593,8.316L68.148,32.761z"/>
<polygon id="beta" fill="#35FF1F" points="86.722,128.316 134.593,124.613 158.296,163.872 190.889,155.724 214.593,100.909 
    194.593,52.02 227.186,49.057 246.444,92.02 238.297,140.909 216.074,172.761 197.556,188.316 179.778,169.798 164.963,174.983 
    163.481,197.946 156.815,197.946 134.593,159.428 94.593,151.279 "/>
<path class="monkey" id="alpha" fill="#FD00FF" d="M96.315,4.354l42.963,5.185l18.519,42.222l71.852-8.148l20.74,46.667l-5.926,52.593
    l-24.444,34.074l-25.185,15.555l-14.074-19.259l-8.889,2.964l-1.481,22.222l-14.074,2.963l-25.186,22.963l-74.074,4.444
    l101.481,4.444c0,0,96.297-17.777,109.63-71.852S282.24,53.983,250.389,20.65S96.315,4.354,96.315,4.354z"/>
</svg>

ご覧のとおり、各要素にはIDがあり、Javascriptを使用して個々の要素にアクセスできるようにして、Fill属性を変更し、クリックなどのイベントに応答できるようにしたいと考えていました。

HTMLは基本的なものです

<!DOCTYPE html>
<html>
    <head>
        <title>SVG Illustrator Test</title> 
    </head>
    <body>

        <object data="alpha.svg" type="image/svg+xml" id="alphasvg" width="100%" height="100%"></object>

    </body>
</html>

これは本当に2つの質問だと思います。

  1. RaphaelやjQuerySVGのようなものを使用するのではなく、この方法でそれを行うことは可能ですか?

  2. 可能であれば、テクニックは何ですか?


更新

現時点では、私は、SVGファイルを作成するために、イラストレーターを使用してに頼ってきた、と私は使用していラファエルJSをパスを作成すると、単純にSVGファイルからのポイントデータをコピーしてに貼り付けるpath()機能。ポイントデータを手動でコーディングして、マップに必要となるような複雑なパスを作成することは、(私の知る限り)非常に複雑です。

回答:


113

RaphaelやjQuerySVGのようなものを使用するのではなく、この方法でそれを行うことは可能ですか?

間違いなく。

可能であれば、テクニックは何ですか?

この注釈付きコードスニペットは機能します。

<!DOCTYPE html>
<html>
    <head>
        <title>SVG Illustrator Test</title> 
    </head>
    <body>

        <object data="alpha.svg" type="image/svg+xml"
         id="alphasvg" width="100%" height="100%"></object>

        <script>
            var a = document.getElementById("alphasvg");

            // It's important to add an load event listener to the object,
            // as it will load the svg doc asynchronously
            a.addEventListener("load",function(){

                // get the inner DOM of alpha.svg
                var svgDoc = a.contentDocument;
                // get the inner element by id
                var delta = svgDoc.getElementById("delta");
                // add behaviour
                delta.addEventListener("mousedown",function(){
                        alert('hello world!')
                }, false);
            }, false);
        </script>
    </body>
</html>

この手法の制限は、同一生成元ポリシーによって制限されているためalpha.svg.htmlファイルと同じドメインでホストする必要があることに注意してください。そうしないと、オブジェクトの内部DOMにアクセスできなくなります。

このHTMLを実行するために重要なことは、IIS、TomcatなどのWebサーバーへのホストHTMLファイルが必要です。


4
@ jbeard4のメモに関する注意:一部のブラウザーでは、この同一生成元ポリシーにより、サーバーを使用する必要があります(コードがhtmlとjs [サーバーサイド]のみを使用している場合でも)アクセスポリシーにより、svgへのアクセスが防止されます。
Michael

1
このHTMLを実行するために重要なことは、IIS、TomcatなどのWebサーバーへのホストHTMLファイルが必要です
Hien Nguyen

@HienNguyenが述べたように、Webサーバーで実行する前は、機能しませんでした。に返されdocument.getElementById("alphasvg").contentDocumentた値はでしたnull
am.rez

TL; DR:contentDocumentHTMLコンテキストからSVGコンテキストへのブリッジ
Abdull

19

jQueryを使用する場合$(window).load、埋め込まれたSVGドキュメントがまだロードされていない可能性があるため、を待つ必要があります。$(document).ready

$(window).load(function () {

    //alert("Document loaded, including graphics and embedded documents (like SVG)");
    var a = document.getElementById("alphasvg");

    //get the inner DOM of alpha.svg
    var svgDoc = a.contentDocument;

    //get the inner element by id
    var delta = svgDoc.getElementById("delta");
    delta.addEventListener("mousedown", function(){ alert('hello world!')}, false);
});

3
:このコードを使用している間、この他の答えは便利な補数であるかもしれないstackoverflow.com/a/5990945/1515819
ステファンBruckert

jQueryの場合は、の$('#alphasvg').load代わりに使用することをお勧めします$(window).load。これによりdata、その場で属性を変更できます
vkabachenko 2018

jQueryを使用してsvg内の要素にアクセスすることはできますが、jQueryを使用して要素をsvgに追加することはできないことに注意してください。理由については、stackoverflow.com / questions / 3642035 /…を参照してください。
hrabinowitz

4

<img>SVGにタグを使用している場合、その内容を操作することはできません(私が知る限り)。

受け入れられた答えが示すように、使用<object>はオプションです。

最近これが必要gulp-injectになり、gulpビルド中に、SVGファイルのコンテンツを<svg>要素としてHTMLドキュメントに直接挿入するために使用しました。これにより、CSSセレクターやquerySelector/を使用して非常に簡単に操作できgetElementBy*ます。


imgタグは大きなSVGロードに役立ちます...複雑な(そしてインタラクティブな!)SVGを使用するには、SVG + DOM +データ操作に特化したライトjQueryのようなD3jsを使用する方が良いでしょう。
ピータークラウス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.