如何使用 Javascript 访问 SVG 元素

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2753732/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 01:46:26  来源:igfitidea点击:

How to access SVG elements with Javascript

javascriptsvgraphael

提问by gargantuan

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)

这是 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>

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 属性并响应诸如单击之类的事件。

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.

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

  1. 是否可以通过这种方式来实现,而不是使用 Raphael 或 jQuery SVG 之类的东西。

  2. 如果可能,技术是什么?



UPDATE

更新

At the moment, I've resorted to using Illustrator to create the SVG file, and I'm using Rapha?l JSto 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?l JS来创建路径并简单地从 SVG 文件中复制点数据并将其粘贴到path()函数中。通过手动编码点数据来创建地图可能需要的复杂路径(据我所知)非常复杂。

回答by jbeard4

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.svgmust be hosted on the same domain as the .htmlfile, otherwise the inner DOM of the object will be inaccessible.

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

Important thingto run this HTML, you need host HTML file to web server like IIS, Tomcat

运行此 HTML 的重要事项,您需要将 HTML 文件托管到 IIS、Tomcat 等 Web 服务器

回答by jediz

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);
});

回答by Drew Noakes

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

如果您<img>为 SVG使用标签,则您无法操作其内容(据我所知)。

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

正如接受的答案所示,使用<object>是一种选择。

I needed this recently and used gulp-injectduring 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-inject在我的 gulp 构建期间使用它来将 SVG 文件的内容作为<svg>元素直接注入 HTML 文档,然后使用 CSS 选择器和querySelector/非常容易使用getElementBy*