web-dev-qa-db-fra.com

Comment accéder aux éléments SVG avec Javascript

Je bricolais avec SVG et j'espérais pouvoir créer des fichiers SVG dans Illustrator et accéder aux éléments en Javascript.

Voici le fichier SVG illustré par Illustrator (Il semble également ajouter une charge de pourriels au début du fichier que j'ai supprimé)

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

Comme vous pouvez probablement le constater, chaque élément a un identifiant et j'espérais pouvoir accéder à des éléments individuels avec Javascript pour pouvoir modifier l'attribut Remplir et répondre à des événements tels que click.

Le HTML est basique

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

Je suppose que ce sont vraiment deux questions.

  1. Est-il possible de le faire de cette façon, par opposition à quelque chose comme Raphael ou jQuery SVG.

  2. Si c'est possible, quelle est la technique?


[~ # ~] met à jour [~ # ~]

Pour le moment, j’ai eu recours à Illustrator pour créer le fichier SVG, et j’utilise Raphaël JS pour créer des chemins et simplement copier les données de points du fichier SVG et les coller dans path() fonction. Créer des chemins complexes tels que ceux nécessaires pour une carte, en codant les données de points manuellement, est (à ma connaissance) prohibitif.

77
gargantuan

Est-il possible de le faire de cette façon, par opposition à l'utilisation de quelque chose comme Raphael ou jQuery SVG?

Absolument.

Si c'est possible, quelle est la technique?

Cet extrait de code annoté fonctionne:

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

Notez qu'une des limitations de cette technique est qu'elle est limitée par la politique de même origine, donc alpha.svg doit être hébergé sur le même domaine que le .html fichier, sinon le DOM interne de l’objet sera inaccessible.

102
jbeard4

Si vous utilisez jQuery, vous devez attendre $(window).load, car le document SVG incorporé n'est peut-être pas encore chargé à $(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);
});
18
jediz

Si vous utilisez un <img> tag pour le fichier SVG, vous ne pouvez pas manipuler son contenu (pour autant que je sache).

Comme le montre la réponse acceptée, en utilisant <object> est une option.

J'avais besoin de cela récemment et utilisé gulp-inject lors de ma construction gulp pour injecter le contenu d’un fichier SVG directement dans le document HTML en tant que <svg> élément, qui est alors très facile à utiliser avec les sélecteurs CSS et querySelector/getElementBy*.

4
Drew Noakes