假设:

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

为什么我什么都看不到?


当前回答

公认的答案显得太复杂了。正如Forresto在他的回答中所声称的那样,“它似乎是在DOM资源管理器中添加它们,而不是在屏幕上”,其原因是html和svg的名称空间不同。

最简单的解决方法是“刷新”整个svg。在添加circle(或其他元素)后,使用以下语句:

$("body").html($("body").html());

这很管用。这个圆在屏幕上。

或者,如果你愿意,使用容器div:

$("#cont").html($("#cont").html());

然后将svg包装到容器div中:

<div id="cont">
    <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>
</div>

函数示例: http://jsbin.com/ejifab/1/edit

该技术的优点:

您可以编辑现有的svg(已经在DOM中),例如。创建使用Raphael或像在你的例子中“硬编码”没有脚本。 你可以添加复杂的元素结构如字符串。$ (svg) .prepend(“< def > <标记> < / >标记<面具> < /面具> < / def >”);就像在jQuery中一样。 在添加元素并在屏幕上显示后,使用$("#cont").html($("#cont").html());它们的属性可以使用jQuery编辑。


编辑:

上述技术适用于“硬编码”或DOM操纵(= document。仅支持SVG。如果Raphael用于创建元素,(根据我的测试)Raphael对象和SVG DOM之间的链接被破坏,如果$(“#cont”).html($(“#cont”).html());使用。解决方法不是使用$("#cont").html($("#cont").html());而不是使用虚拟SVG文档。

This dummy SVG is first a textual representation of SVG document and contains only elements that are needed. If we want eg. to add a filter element to Raphael document, the dummy could be something like <svg id="dummy" style="display:none"><defs><filter><!-- Filter definitons --></filter></defs></svg>. The textual representation is first converted to DOM using jQuery's $("body").append() method. And when the (filter) element is in DOM, it can be queried using standard jQuery methods and appended to the main SVG document which is created by Raphael.

为什么需要这个假人?为什么不添加一个过滤器元素严格拉斐尔创建的文件?如果你试着用eg。美元(svg)。追加(“<圆…/>"),它被创建为HTML元素,屏幕上没有答案中描述的内容。但是如果附加了整个SVG文档,那么浏览器将自动处理SVG文档中所有元素的名称空间转换。

下面是一个例子:

// Add Raphael SVG document to container element
var p = Raphael("cont", 200, 200);
// Add id for easy access
$(p.canvas).attr("id","p");
// Textual representation of element(s) to be added
var f = '<filter id="myfilter"><!-- filter definitions --></filter>';

// Create dummy svg with filter definition 
$("body").append('<svg id="dummy" style="display:none"><defs>' + f + '</defs></svg>');
// Append filter definition to Raphael created svg
$("#p defs").append($("#dummy filter"));
// Remove dummy
$("#dummy").remove();

// Now we can create Raphael objects and add filters to them:
var r = p.rect(10,10,100,100);
$(r.node).attr("filter","url(#myfilter)");

该技术的完整演示在这里:http://jsbin.com/ilinan/1/edit。

(我有(还)不知道,为什么美元(“#合同”). html($(" #合同”). html ());当使用拉斐尔时不工作。这将是非常短的hack。)

其他回答

我可以看到圈在firefox,做2件事:

1)将文件从html重命名为xhtml

2)更改脚本为

<script type="text/javascript">
$(document).ready(function(){
    var obj = document.createElementNS("http://www.w3.org/2000/svg", "circle");
    obj.setAttributeNS(null, "cx", 100);
    obj.setAttributeNS(null, "cy", 50);
    obj.setAttributeNS(null, "r",  40);
    obj.setAttributeNS(null, "stroke", "black");
    obj.setAttributeNS(null, "stroke-width", 2);
    obj.setAttributeNS(null, "fill", "red");
    $("svg")[0].appendChild(obj);
});
</script>

基于@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);

公认的答案显得太复杂了。正如Forresto在他的回答中所声称的那样,“它似乎是在DOM资源管理器中添加它们,而不是在屏幕上”,其原因是html和svg的名称空间不同。

最简单的解决方法是“刷新”整个svg。在添加circle(或其他元素)后,使用以下语句:

$("body").html($("body").html());

这很管用。这个圆在屏幕上。

或者,如果你愿意,使用容器div:

$("#cont").html($("#cont").html());

然后将svg包装到容器div中:

<div id="cont">
    <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>
</div>

函数示例: http://jsbin.com/ejifab/1/edit

该技术的优点:

您可以编辑现有的svg(已经在DOM中),例如。创建使用Raphael或像在你的例子中“硬编码”没有脚本。 你可以添加复杂的元素结构如字符串。$ (svg) .prepend(“< def > <标记> < / >标记<面具> < /面具> < / def >”);就像在jQuery中一样。 在添加元素并在屏幕上显示后,使用$("#cont").html($("#cont").html());它们的属性可以使用jQuery编辑。


编辑:

上述技术适用于“硬编码”或DOM操纵(= document。仅支持SVG。如果Raphael用于创建元素,(根据我的测试)Raphael对象和SVG DOM之间的链接被破坏,如果$(“#cont”).html($(“#cont”).html());使用。解决方法不是使用$("#cont").html($("#cont").html());而不是使用虚拟SVG文档。

This dummy SVG is first a textual representation of SVG document and contains only elements that are needed. If we want eg. to add a filter element to Raphael document, the dummy could be something like <svg id="dummy" style="display:none"><defs><filter><!-- Filter definitons --></filter></defs></svg>. The textual representation is first converted to DOM using jQuery's $("body").append() method. And when the (filter) element is in DOM, it can be queried using standard jQuery methods and appended to the main SVG document which is created by Raphael.

为什么需要这个假人?为什么不添加一个过滤器元素严格拉斐尔创建的文件?如果你试着用eg。美元(svg)。追加(“<圆…/>"),它被创建为HTML元素,屏幕上没有答案中描述的内容。但是如果附加了整个SVG文档,那么浏览器将自动处理SVG文档中所有元素的名称空间转换。

下面是一个例子:

// Add Raphael SVG document to container element
var p = Raphael("cont", 200, 200);
// Add id for easy access
$(p.canvas).attr("id","p");
// Textual representation of element(s) to be added
var f = '<filter id="myfilter"><!-- filter definitions --></filter>';

// Create dummy svg with filter definition 
$("body").append('<svg id="dummy" style="display:none"><defs>' + f + '</defs></svg>');
// Append filter definition to Raphael created svg
$("#p defs").append($("#dummy filter"));
// Remove dummy
$("#dummy").remove();

// Now we can create Raphael objects and add filters to them:
var r = p.rect(10,10,100,100);
$(r.node).attr("filter","url(#myfilter)");

该技术的完整演示在这里:http://jsbin.com/ilinan/1/edit。

(我有(还)不知道,为什么美元(“#合同”). html($(" #合同”). html ());当使用拉斐尔时不工作。这将是非常短的hack。)

替代方案1:原生js insertAdjacentHTML()

如果你根本不考虑切换到原生JavaScript…… 您还可以使用本地javaScript方法insertAdjacentHTML()来获得同样方便的表示法。

  $("#svg")[0].insertAdjacentHTML(
    "beforeEnd",
    '<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>'
  );

$("#svg")[0]使你的jQuery对象在原生JS中可选。

替代方案2:编写一个原生js DOMParser()帮助器

mdn web文档:DOMParser.parseFromString()

  function createSvgEl(markup) {
    markup = `<svg xmlns="http://www.w3.org/2000/svg">
  ${markup}</svg>`;
    const svgEl = new DOMParser().parseFromString(markup, "image/svg+xml")
      .documentElement.children[0];
    return svgEl;
  }

jQuery的用法:

  $("#svgXML").append(
    createSvgEl(
      '<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>'
    )
  );

Demo

// native js helper function createSvgEl(markup) { markup = `<svg xmlns="http://www.w3.org/2000/svg"> ${markup}</svg>`; const svgEl = new DOMParser().parseFromString(markup, "image/svg+xml") .documentElement.children[0]; return svgEl; } $(document).ready(function() { // works - but will remove existing children $("#svg1").html( '<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>' ); // works // $("#svg")[0] makes your jQueryObject selectable in native JS $("#svg")[0].insertAdjacentHTML( "beforeEnd", '<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>' ); $("#svgXML").append( createSvgEl( '<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>' ) ); // jquery still works! Vanilla doesn't harm! $("#svgXML circle:nth-of-type(2)").attr('fill', 'orange'); //insert after() $("#svgAfter circle").after( createSvgEl( '<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>' ) ); //insert after native $("#svgAfterNative circle")[0].insertAdjacentHTML( "afterEnd", '<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>' ); }); svg { border: 1px solid red; overflow: visible; } <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <p>Append via native js insertAdjacentHTML()</p> <svg id="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"> <circle cx="10" cy="10" r="5" fill="green" /> </svg> <p>Append via DOMParser() helper</p> <svg id="svgXML" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 100" width="200px" height="100px"> <circle cx="10" cy="10" r="5" fill="green" /> </svg> <p>Append via jquery html() - will strip existing child nodes</p> <svg id="svg1" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 100" width="200px" height="100px"> <circle cx="10" cy="10" r="5" fill="green" /> </svg> <p>Insert after existing element with jQuery after() using DOMParser() helper</p> <svg id="svgAfter" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 100" width="200px" height="100px"> <circle cx="10" cy="10" r="5" fill="green" /> </svg> <p>Insert after existing element with native js insertAdjacentHTML()</p> <svg id="svgAfterNative" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 100" width="200px" height="100px"> <circle cx="10" cy="10" r="5" fill="green" /> </svg>

jquery的after()或before()方法也将无法添加SVG DOM(取决于正确的名称空间)元素。

使用前面提到的变通方法也可以解决这个问题。

发现了一个简单的方法,适用于我所有的浏览器(Chrome 49, Edge 25, Firefox 44, IE11, Safari 5 [Win], Safari 8 (MacOS)):

// Clean svg content (if you want to update the svg's objects) // Note : .html('') doesn't works for svg in some browsers $('#svgObject').empty(); // add some objects $('#svgObject').append('<polygon class="svgStyle" points="10,10 50,10 50,50 10,50 10,10" />'); $('#svgObject').append('<circle class="svgStyle" cx="100" cy="30" r="25"/>'); // Magic happens here: refresh DOM (you must refresh svg's parent for Edge/IE and Safari) $('#svgContainer').html($('#svgContainer').html()); .svgStyle { fill:cornflowerblue; fill-opacity:0.2; stroke-width:2; stroke-dasharray:5,5; stroke:black; } <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div id="svgContainer"> <svg id="svgObject" height="100" width="200"></svg> </div> <span>It works if two shapes (one square and one circle) are displayed above.</span>