jquery的追加不与svg元素一起工作?
假设:
<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>
为什么我看不到任何东西?
当您将标记字符串传递到$
,它会使用浏览器的<div>
(或其他适当的容器,用于特殊情况下的<tr>
)的innerHTML
属性解析为HTML。 innerHTML
无法解析SVG或其他非HTML内容,即使它可能无法分辨<circle>
应该在SVG名称空间中。
innerHTML
在SVGElement上不可用 - 它仅是HTMLElement的一个属性。 目前还没有innerSVG
属性或其他方式(*)来解析SVGElement的内容。 出于这个原因,你应该使用DOM风格的方法。 jQuery不会让您轻松访问创建SVG元素所需的名称空间方法。 真的,jQuery并非设计用于SVG,许多操作可能会失败。
HTML5承诺可以让您在未来使用<svg>
而无需在纯HTML( text/html
)文档中使用xmlns
。 但这只是一个解析器hack(**),SVG内容仍然是SVG命名空间中的SVGElements,而不是HTMLElements,所以即使它们看起来像HTML文档的一部分,也不能使用innerHTML
。
但是,对于今天的浏览器,您必须使用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多年前解决了这些问题。
接受的答案显示过于复杂。 正如Forresto在他的回答中所声称的那样,“它似乎将它们添加到DOM浏览器中,但不在屏幕上”,原因是html和svg具有不同的名称空间。
最简单的解决方法是“刷新”整个svg。 附加圆圈(或其他元素)后,使用以下内容:
$("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').prepend('<defs><marker></marker><mask></mask></defs>');
就像你在jQuery中做的一样。 $("#cont").html($("#cont").html());
在屏幕上可见$("#cont").html($("#cont").html());
他们的属性可以使用jQuery进行编辑。 编辑:
上述技术仅适用于“硬编码”或DOM操作(= document.createElementNS等)SVG。 如果使用Raphael创建元素,(根据我的测试),如果$("#cont").html($("#cont").html());
则断开Raphael对象与SVG DOM之间的链接$("#cont").html($("#cont").html());
用来。 解决方法是不使用$("#cont").html($("#cont").html());
根本不使用虚拟SVG文档。
这个虚拟SVG首先是SVG文档的文本表示,并且仅包含所需的元素。 如果我们想要例如。 为Raphael文档添加一个过滤元素,该虚拟元素可以是类似于<svg id="dummy" style="display:none"><defs><filter><!-- Filter definitons --></filter></defs></svg>
。 文本表示首先使用jQuery的$(“body”)。append()方法转换为DOM。 当(filter)元素在DOM中时,可以使用标准jQuery方法查询它,并附加到由Raphael创建的主SVG文档。
为什么需要这个假人? 为什么不向Raphael创建的文档严格添加滤镜元素? 如果你尝试使用例如。 $("svg").append("<circle ... />")
,它被创建为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。
(我还没有想过,为什么$("#cont").html($("#cont").html());
在使用Raphael时不起作用,这将会非常短暂。
日益流行的D3库非常好地处理了添加/操作svg的古怪事情。 你可能要考虑使用它,而不是这里提到的jQuery hack。
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");
链接地址: http://www.djcxy.com/p/49173.html