如何使用 Javascript 访问 SVG 元素

我正在使用 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 属性并响应诸如 click 之类的事件。

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>

我想这其实是两个问题。

  1. 有没有可能这样做,而不是使用 Raphael 或 jQuerySVG 之类的东西。

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


更新

目前,我使用 Illustrator 来创建 SVG 文件,我使用 拉斐尔 JS来创建路径,并简单地从 SVG 文件中复制点数据,然后将其粘贴到 path()函数中。通过手工编码点数据来创建复杂的路径,比如地图可能需要的路径,(据我所知)是非常复杂的。

210941 次浏览

Is it possible to do it this way, as opposed to using something like Raphael or 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.

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

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

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

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

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*.