假设:

<html>
<head>
 <script type="text/javascript" src="jquery.js"></script>
 <script type="text/javascript">
 $(document).ready(function(){
  $("svg").append('<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>');
 });
 </script>
</head>
<body>
 <svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 100" width="200px" height="100px">
 </svg>
</body>

为什么我什么都看不到?


当前回答

Bobince给出的公认答案是一个简短的、可移植的解决方案。如果您不仅需要添加SVG,而且还需要操作它,那么可以尝试JavaScript库“Pablo”(它是我编写的)。jQuery用户会感觉很熟悉。

您的代码示例将如下所示:

$(document).ready(function(){
    Pablo("svg").append('<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>');
});

你也可以动态地创建SVG元素,而不需要指定标记:

var circle = Pablo.circle({
    cx:100,
    cy:50,
    r:40
}).appendTo('svg');

其他回答

当您将标记字符串传递给$时,它将使用浏览器的innerHTML属性在<div>(或其他适合特殊情况的容器,如<tr>)上被解析为HTML。innerHTML不能解析SVG或其他非html内容,即使它可以,它也不能告诉<circle>应该在SVG名称空间中。

innerHTML在svgelement上是不可用的,它只是HTMLElement的一个属性。目前也没有innerSVG属性或其他方法(*)来将内容解析为SVGElement。出于这个原因,您应该使用dom风格的方法。jQuery不能让您轻松访问创建SVG元素所需的名称空间方法。实际上,jQuery根本不是为SVG设计的,许多操作可能会失败。

HTML5承诺让您在未来使用<svg>而无需在纯HTML(文本/ HTML)文档中使用xmlns。但这只是一个解析器hack(**), SVG内容仍然是SVG名称空间中的SVGElements,而不是HTMLElements,因此您将无法使用innerHTML,即使它们看起来像HTML文档的一部分。

然而,对于今天的浏览器,您必须使用XHTML(适当地作为application/ XHTML +xml;保存为本地测试的.xhtml文件扩展名)以使SVG能够正常工作。(这是有道理的;SVG是一种适当的基于xml的标准。)这意味着您必须转义脚本块中的<符号(或包含在CDATA部分中),并包括XHTML xmlns声明。例子:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head>
</head><body>
    <svg id="s" xmlns="http://www.w3.org/2000/svg"/>
    <script type="text/javascript">
        function makeSVG(tag, attrs) {
            var el= document.createElementNS('http://www.w3.org/2000/svg', tag);
            for (var k in attrs)
                el.setAttribute(k, attrs[k]);
            return el;
        }

        var circle= makeSVG('circle', {cx: 100, cy: 50, r:40, stroke: 'black', 'stroke-width': 2, fill: 'red'});
        document.getElementById('s').appendChild(circle);
        circle.onmousedown= function() {
            alert('hello');
        };
    </script>
</body></html>

*:嗯,有DOM Level 3 LS的parseWithContext,但是浏览器的支持很差。编辑添加:然而,虽然你不能将标记注入到SVGElement中,你可以使用innerHTML将一个新的SVGElement注入到HTMLElement中,然后将它传输到所需的目标。不过它可能会慢一点:

<script type="text/javascript"><![CDATA[
    function parseSVG(s) {
        var div= document.createElementNS('http://www.w3.org/1999/xhtml', 'div');
        div.innerHTML= '<svg xmlns="http://www.w3.org/2000/svg">'+s+'</svg>';
        var frag= document.createDocumentFragment();
        while (div.firstChild.firstChild)
            frag.appendChild(div.firstChild.firstChild);
        return frag;
    }

    document.getElementById('s').appendChild(parseSVG(
        '<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red" onmousedown="alert(\'hello\');"/>'
    ));
]]></script>

**:我讨厌HTML5的作者似乎害怕XML,并决心将基于XML的功能硬塞进混乱的HTML中。XHTML几年前就解决了这些问题。

JQuery不能将元素附加到<svg>(它似乎在DOM资源管理器中添加了它们,但不在屏幕上)。

一种解决方法是在页面中附加一个<svg>和所有需要的元素,然后使用.attr()修改元素的属性。

$('body')
  .append($('<svg><circle id="c" cx="10" cy="10" r="10" fill="green" /></svg>'))
  .mousemove( function (e) {
      $("#c").attr({
          cx: e.pageX,
          cy: e.pageY
      });
  });

http://jsfiddle.net/8FBjb/1/

越来越流行的D3库很好地处理了附加/操作svg的奇怪问题。您可能会考虑使用它,而不是这里提到的jQuery hacks。

HTML

<svg xmlns="http://www.w3.org/2000/svg"></svg>

Javascript

var circle = d3.select("svg").append("circle")
    .attr("r", "10")
    .attr("style", "fill:white;stroke:black;stroke-width:5");

基于@chris-dolphin的回答,但使用了helper函数:

// Creates svg element, returned as jQuery object
function $s(elem) {
  return $(document.createElementNS('http://www.w3.org/2000/svg', elem));
}

var $svg = $s("svg");
var $circle = $s("circle").attr({...});
$svg.append($circle);

我建议最好使用ajax并从另一个页面加载svg元素。

$('.container').load(href + ' .svg_element');

其中href是带有svg. xml的页面的位置。通过这种方式,您可以避免替换html内容时可能发生的任何紧张影响。另外,不要忘记在svg加载后打开它:

$('.svg_element').unwrap();