假设:

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

为什么我什么都看不到?


当前回答

我为此做了一个小函数。对于jQuery的追加方法,问题是需要为SVG指定命名空间,即“http://www.w3.org/2000/svg”更多

如果我准备它为appendmethod呢?在这种情况下,你只需要提供一些参数:

tagName:它可以是每一个SVG元素,如矩形,圆,文本,g等。

text:如果您正在使用类似text tagname的东西,则需要指定text

和SVG元素的其他已知属性。

因此,我要做的是定义一个名为createSvgElem()的函数,它在内部使用document.createElementNS()。

这里有一个例子:

$("svg").append(
   createSvgElem({tagName: "text", x: 10, y: 10, text: "ABC", style: "fill: red"})
)

这是函数:

   function createSvgElem(options){
        var settings = $.extend({
            }, options);

        if(!$.isEmptyObject(settings.tagName)){
            var el = document.createElementNS('http://www.w3.org/2000/svg', settings.tagName);
            for (var k in settings)
                if(k != "tagName" && k != "text" && settings[k] != "")//If attribute has value
                    el.setAttribute(k, settings[k]);

            if ("text" in settings)
                el.textContent = settings.text; //el.innerText; For IE
            return el;
        }
    }

你可以自己试试:

//Definition: function createSvgElem(options){ var settings = $.extend({ }, options); if(!$.isEmptyObject(settings.tagName)){ var el = document.createElementNS('http://www.w3.org/2000/svg', settings.tagName); for (var k in settings) if(k != "tagName" && k != "text" && settings[k] != "")//If attribute has value el.setAttribute(k, settings[k]); if ("text" in settings) el.textContent = settings.text; //el.innerText; For IE return el; } } //Usage: $(function(){ $("#svg-elem").append( createSvgElem({tagName: "rect", width: 130, height: 500, style: "fill: #000000a3;"}) ) $("#svg-elem").append( createSvgElem({tagName: "text", x: 30, y: 30, text: "ABCD", style: "fill: red"}) ) }) <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <svg id="svg-elem" width="200" height="200"> </svg>

其他回答

如果需要追加的字符串是SVG,并且添加了适当的名称空间,则可以将字符串解析为XML并追加到父对象。

var xml = jQuery.parseXML('<circle xmlns="http://www.w3.org/2000/svg" cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>');
$("svg").append(xml.documentElement)

公认的答案显得太复杂了。正如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。)

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/

当您将标记字符串传递给$时,它将使用浏览器的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几年前就解决了这些问题。

我还没见过有人提到这个方法,但是document.createElementNS()在这个实例中很有帮助。

您可以使用普通Javascript将元素创建为具有正确名称空间的普通DOM节点,然后从那里对它们进行jquery化。像这样:

var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'),
    circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');

var $circle = $(circle).attr({ //All your attributes });

$(svg).append($circle);

唯一的缺点是您必须使用正确的名称空间单独创建每个SVG元素,否则它将无法工作。