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

时间:2012-12-28 10:21:06

标签: javascript html svg

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

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

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

2 个答案:

答案 0 :(得分:85)

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

  1. 如何准备图像以进行交互
  2. 如何在页面中嵌入图像
  3. 如何将CSS与SVG一起使用
  4. 如何使用JavaScript进行交互
  5. 准备图片

    首先,我建议清理图像。 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>
    

    如何使用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);
    

    如何使用CSS

    SVG可以像HTML一样进行样式设置。当然,SVG拥有自己的一组属性,例如fill-opacitystroke-dasharray,并且不支持很多HTML属性,例如marginposition等。但是选择器机制是100%相同的。

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

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

    #Bronckhorst, #Laarbeek {fill:red}
    

    *[data-gemeente=Bronckhorst], *[data-gemeente=Laarbeek] {fill:red}
    

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

    JavaScript互动

    HTML和SVG在JavaScript交互方面基本没有区别,至少只要你使用普通的vanilla DOM。这意味着,SVG不支持innerHTML等HTML特定功能(即没有innerSVG)。但是SVG有自己的图形特定的DOM方法集(see the W3C specs)。

    要注意的一件事是使用命名空间。所有SVG元素都应位于SVG名称空间中,使用JavaScript创建时,必须使用createElementNS()而不是createElement()

    var use = document.createElementNS("http://www.w3.org/2000/svg","use")
    

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

    use.setAttributeNS("http://www.w3.org/1999/xlink","href","#foo")
    

    像jQuery这样的库部分依赖于HTML特定功能,在操作SVG时避免使用它们更安全。还有一些SVG特定的库,如RaphaëlD3.js,可用于特定目的,值得一看。 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)
    

    旁注:Toopltips 使用SVG中的title元素可以实现使用HTML中<title>属性获得的相同效果。只需将一个<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>
    

答案 1 :(得分:8)

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

http://snapsvg.io