在HTML中嵌入外部SVG以进行JavaScript操作

Ger*_*rit 35 html javascript svg

我有一个SVG图像,显示地理区域. http://upload.wikimedia.org/wikipedia/commons/7/71/Nederland_gemeenten_2009.svg

我想在网页上显示SVG图像,并使用JavaScript和CSS的组合来与图像进行交互.(即,检测区域上的点击,为区域设置不同的背景颜色).

我知道在StackOverflow上多次询问这个问题,但我找不到完整的代码示例.欢迎任何有关JavaScript包的建议,如jQuery或插件.

Tho*_*s W 89

我对这个问题的理解是,有不同的方面需要解决:

  1. 如何准备图像进行交互
  2. 如何在页面中嵌入图像
  3. 如何在SVG中使用CSS
  4. 如何使用JavaScript进行交互

准备图像

首先,我建议清理图像.Inkscape会在那里留下您不需要的所有内容,包括sodipodi:inkscape:名称空间中的元素和属性以及重复和/或冗余样式属性.你不具有移除,但它可以节省你一些带宽/加载时间,如果你想与CSS的匹配工作,比作风属性在你的方式.

在您的示例文件中,您拥有相同样式属性的472倍.删除所有这些并创建一个等效的CSS规则.

您还可以向标记添加有关城市的一些信息.您可以例如根据其名称更改代表市政当局的每条路径的ID.您也可以使用data-*属性来实现此目的.后者的优点是可以使用空格.请参阅下文,了解它如何用于交互,尤其是CSS.

嵌入图像

我建议使用SVG内联,特别是如果你想与CSS/JavaScript交互.这意味着,您只需将SVG标记添加到HTML中,或者使用Ajax加载并插入它.后者的好处是周围的页面加载速度更快,响应更快.

内联SVG元素的示例:

<div id="svgContainer">
  <!-- This is an HTML div, and inside goes the SVG -->
  <svg xmlns="http://www.w3.org/2000/svg" width="100px" height="100px">
    <circle r="50" cx="50" cy="50" fill="green"/>
  </svg>
</div>
Run Code Online (Sandbox Code Playgroud)

如何使用Ajax加载SVG的简化示例:

xhr = new XMLHttpRequest();
xhr.open("GET","my.svg",false);
// Following line is just to be on the safe side;
// not needed if your server delivers SVG with correct MIME type
xhr.overrideMimeType("image/svg+xml");
xhr.send("");
document.getElementById("svgContainer")
  .appendChild(xhr.responseXML.documentElement);
Run Code Online (Sandbox Code Playgroud)

如何使用CSS

SVG可以像HTML一样进行样式设置.当然,SVG有它自己的属性集,如fill-opacitystroke-dasharray与不支持大量的HTML代码的性质,像margin,position等等.但选择器机制是100%相同.

您可以将内联SVG的CSS与HTML的CSS混合使用,无论是在<style>元素内还是外部CSS文件中.您还可以使用<style>SVG代码和style属性中的元素.

假设您为SVG元素提供了有意义的ID或data-*属性,使用CSS突出显示城市的两种方法是:

#Bronckhorst, #Laarbeek {fill:red}
Run Code Online (Sandbox Code Playgroud)

要么

*[data-gemeente=Bronckhorst], *[data-gemeente=Laarbeek] {fill:red}
Run Code Online (Sandbox Code Playgroud)

或者,当然,您可以更改相应元素的样式属性.属性也作为属性支持,即style="stroke-width:2"也可以指定为stroke-width="2".如果使用属性和CSS(使用样式属性,样式元素或外部样式表)设置相同的属性,则CSS将覆盖该属性.

JavaScript互动

HTML和SVG之间在JavaScript交互方面基本没有区别,至少只要你使用普通的vanilla DOM.这意味着,innerHTMLSVG不支持HTML特定功能(即没有innerSVG).但是SVG有自己的图形特定的DOM方法集(参见W3C规范).

需要注意的一件事是使用命名空间.所有SVG元素都应该在SVG名称空间中,并且在使用JavaScript创建它们时,createElementNS()必须使用而不是createElement():

var use = document.createElementNS("http://www.w3.org/2000/svg","use")
Run Code Online (Sandbox Code Playgroud)

同样,XLink命名空间(即xlink:href)中的属性必须使用setAttributeNS()而不是setAttribute():

use.setAttributeNS("http://www.w3.org/1999/xlink","href","#foo")
Run Code Online (Sandbox Code Playgroud)

由于像jQuery这样的库部分依赖于HTML特定功能,因此在操作SVG时避免它们更安全.还有像RaphaëlD3.js这样的SVG特定库,它们可用于特定目的,值得一看.Raphaël特别适用于与HTML5之前的版本6到8兼容的版本,它们没有SVG支持.但是,据我所知,它实际上只适合使用JavaScript生成图形而不是使用现有图形,因为它是SVG之上的抽象层.如果你对普通的DOM不满意,那么D3.js会更适合像你这样的应用程序(老实说,我只是把它称为SVG特定的库,这样做是不公平的,因为它更多).

您可以使用onclick和类似的属性和标准DOM addEventListener().使用JavaScript事件的一个非常简单的示例是向<svg>报告用户点击的市政府名称的元素添加事件监听器:

document.getElementsByTagName("svg")[0]
  .addEventListener("click",function(evt){
    alert(evt.target.getAttribute("data-gemeente"))
  },
  false)
Run Code Online (Sandbox Code Playgroud)

附注:Toopltipstitle使用<title>SVG中的元素可以实现使用HTML中 的属性获得的相同效果.只需将一个<title>元素放在SVG元素中,并在悬停时,您会看到一个包含<title>元素内容的工具提示.

<svg xmlns="http://www.w3.org/2000/svg" width="100px" height="100px">
  <rect width="100" height="100">
    <title>test</title>
  </rect>
</svg>
Run Code Online (Sandbox Code Playgroud)

  • 这是一个非常完整的答案.我只是补充说,最好避免将jQuery与SVG结合使用,因为它假设所有内容都是HTML,这有时会失败.IE9 +支持DOM 3的`addEventListener`,它解决了跨浏览器开发的一些主要难题.Vanilla js经常完成工作,但如果你想抽象一些DOM操作,我建议D3 http://d3js.org. (4认同)
  • 只是一点点赞赏我会经常回来的答案:) (2认同)

小智 8

只是为了记录(知道这是一年晚了)我发现SnapSVG非常适合SVG操作.Raphaël背后的同一个人:

http://snapsvg.io