如何使用Javascript访问SVG元素

时间:2022-11-20 18:27:38

I'm messing around with SVG and I was hoping I could create SVG files in Illustrator and access elements with Javascript.

我正在搞乱SVG,我希望我可以在Illustrator中创建SVG文件并使用Javascript访问元素。

Here's the SVG file Illustrator kicks out (It also seems to add a load of junk to the beginning of the file that I've removed)

这是SVG文件Illustrator的开始(它似乎也添加了一堆垃圾到我删除的文件的开头)

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

As you can probably see, each element has an ID, and I was hoping to be able to access individual elements with Javascript so I could change the Fill attribute and respond to events such as click.

正如您可能看到的,每个元素都有一个ID,我希望能够使用Javascript访问单个元素,这样我就可以更改Fill属性并响应诸如click之类的事件。

The HTML is bog basic

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>

I guess this is two questions really.

我想这真是两个问题。

  1. Is it possible to do it this way, as opposed to using something like Raphael or jQuery SVG.

    是否可以这样做,而不是使用像Raphael或jQuery SVG这样的东西。

  2. If it is possible, what's the technique?

    如果有可能,技术是什么?


UPDATE

UPDATE

At the moment, I've resorted to using Illustrator to create the SVG file, and I'm using Raphaël JS to create paths and simply copying the point data from the SVG file and pasting it into path() function. Creating complex paths such as might be needed for a map, by coding the point data manually is (to my knowledge) prohibitively complex.

目前,我已经使用Illustrator创建SVG文件,我正在使用RaphaëlJS来创建路径,只需从SVG文件复制点数据并将其粘贴到path()函数中。通过手动编码点数据来创建地图可能需要的复杂路径(据我所知)非常复杂。

3 个解决方案

#1


87  

Is it possible to do it this way, as opposed to using something like Raphael or jQuery SVG?

是否可以这样做,而不是使用像Raphael或jQuery SVG这样的东西?

Definitely.

当然。

If it is possible, what's the technique?

如果有可能,技术是什么?

This annotated code snippet works:

这个带注释的代码段有效:

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

Note that a limitation of this technique is that it is restricted by the same-origin policy, so alpha.svg must be hosted on the same domain as the .html file, otherwise the inner DOM of the object will be inaccessible.

请注意,此技术的局限性在于它受同源策略的限制,因此alpha.svg必须与.html文件托管在同一域中,否则对象的内部DOM将无法访问。

#2


17  

In case you use jQuery you need to wait for $(window).load, because the embedded SVG document might not be yet loaded at $(document).ready

如果您使用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


1  

If you are using an <img> tag for the SVG, then you cannot manipulate its contents (as far as I know).

如果您使用SVG的如何使用Javascript访问SVG元素标签,那么您无法操纵其内容(据我所知)。

As the accepted answer shows, using <object> is an option.

如接受的答案所示,使用是一个选项。

I needed this recently and used gulp-inject during my gulp build to inject the contents of an SVG file directly into the HTML document as an <svg> element, which is then very easy to work with using CSS selectors and querySelector/getElementBy*.

我最近需要这个并在我的gulp构建期间使用gulp-inject将SVG文件的内容作为 元素直接注入到HTML文档中,然后使用CSS选择器和querySelector / getElementBy *非常容易。

#1


87  

Is it possible to do it this way, as opposed to using something like Raphael or jQuery SVG?

是否可以这样做,而不是使用像Raphael或jQuery SVG这样的东西?

Definitely.

当然。

If it is possible, what's the technique?

如果有可能,技术是什么?

This annotated code snippet works:

这个带注释的代码段有效:

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

Note that a limitation of this technique is that it is restricted by the same-origin policy, so alpha.svg must be hosted on the same domain as the .html file, otherwise the inner DOM of the object will be inaccessible.

请注意,此技术的局限性在于它受同源策略的限制,因此alpha.svg必须与.html文件托管在同一域中,否则对象的内部DOM将无法访问。

#2


17  

In case you use jQuery you need to wait for $(window).load, because the embedded SVG document might not be yet loaded at $(document).ready

如果您使用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


1  

If you are using an <img> tag for the SVG, then you cannot manipulate its contents (as far as I know).

如果您使用SVG的如何使用Javascript访问SVG元素标签,那么您无法操纵其内容(据我所知)。

As the accepted answer shows, using <object> is an option.

如接受的答案所示,使用是一个选项。

I needed this recently and used gulp-inject during my gulp build to inject the contents of an SVG file directly into the HTML document as an <svg> element, which is then very easy to work with using CSS selectors and querySelector/getElementBy*.

我最近需要这个并在我的gulp构建期间使用gulp-inject将SVG文件的内容作为 元素直接注入到HTML文档中,然后使用CSS选择器和querySelector / getElementBy *非常容易。