web-dev-qa-db-de.com

So greifen Sie mit Javascript auf SVG-Elemente zu

Ich habe mit SVG rumgespielt und gehofft, ich könnte SVG-Dateien in Illustrator erstellen und mit Javascript auf Elemente zugreifen.

Hier ist die SVG-Datei, die Illustrator entfernt hat (außerdem scheint sie eine Menge Müll an den Anfang der Datei zu setzen, die ich entfernt habe)

<?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>

Wie Sie wahrscheinlich sehen, hat jedes Element eine ID, und ich hatte die Hoffnung, mit Javascript auf einzelne Elemente zugreifen zu können, damit ich das Fill-Attribut ändern und auf Ereignisse wie das Klicken reagieren kann.

Das HTML ist sehr einfach

<!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>

Ich denke, das sind wirklich zwei Fragen.

  1. Ist es möglich, dies auf diese Weise zu tun, anstatt etwas wie Raphael oder jQuery SVG zu verwenden?.

  2. Wenn es möglich ist, was ist die Technik?


[~ # ~] Update [~ # ~]

Im Moment habe ich Illustrator verwendet, um die SVG-Datei zu erstellen, und ich verwende Raphaël JS , um Pfade zu erstellen, und kopiere einfach die Punktdaten aus der SVG-Datei und füge sie in die Funktion path() ein . Das Erstellen komplexer Pfade, wie sie für eine Karte erforderlich sein könnten, durch manuelles Codieren der Punktdaten ist (meines Wissens) unerschwinglich komplex.

77
gargantuan

Ist es möglich, dies auf diese Weise zu tun, anstatt so etwas wie Raphael oder jQuery SVG zu verwenden?

Bestimmt.

Wenn es möglich ist, was ist die Technik?

Dieser mit Anmerkungen versehene Codeausschnitt funktioniert wie folgt:

<!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>

Beachten Sie, dass eine Einschränkung dieser Technik darin besteht, dass dieselbe Origin-Richtlinie gilt, sodass alpha.svg In derselben Domäne wie die Datei .html Gehostet werden muss, andernfalls im inneren DOM des Objekts wird unzugänglich sein.

102
jbeard4

Wenn Sie jQuery verwenden, müssen Sie auf $(window).load warten, da das eingebettete SVG-Dokument möglicherweise noch nicht unter $(document).ready geladen wurde.

$(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);
});
18
jediz

Wenn Sie ein <img> - Tag für die SVG verwenden, können Sie deren Inhalt (soweit mir bekannt) nicht manipulieren.

Wie die akzeptierte Antwort zeigt, ist die Verwendung von <object> Eine Option.

Ich brauchte dies kürzlich und verwendete gulp-inject Während meines gulp-Builds, um den Inhalt einer SVG-Datei als <svg> - Element direkt in das HTML-Dokument einzufügen, was dann mit CSS-Selektoren sehr einfach zu handhaben ist und querySelector/getElementBy*.

4
Drew Noakes