jquery的附加不使用svg元素?
假设这个:
$(document).ready(function(){ $("svg").append(''); });
我为什么看不到任何东西?
当您将标记字符串传递给$
,它会使用浏览器的
上的innerHTML
属性(或其他适用于
等特殊情况的容器)解析为HTML。 innerHTML
无法解析SVG或其他非HTML内容,即使它可能无法告诉
应该在SVG名称空间中。
innerHTML
在SVGElement上不可用 – 它只是HTMLElement的属性。 目前还没有内部innerSVG
属性或其他方式(*)来将内容解析为SVGElement。 因此,您应该使用DOM样式的方法。 jQuery不允许您轻松访问创建SVG元素所需的命名空间方法。 实际上jQuery根本不适合与SVG一起使用,许多操作可能会失败。
HTML5承诺将来允许您在纯HTML( text/html
)文档中使用而不使用
xmlns
。 但这只是一个解析器hack(**),SVG内容仍然是SVG名称空间中的SVGElements,而不是HTMLElements,所以即使它们看起来像是HTML文档的一部分,你也无法使用innerHTML
。
但是,对于今天的浏览器,您必须使用X HTML(适当地用作application/xhtml+xml
;使用.xhtml文件扩展名保存以进行本地测试)以使SVG完全正常工作。 (无论如何它都是有意义的; SVG是一个基于XML的正确标准。)这意味着您必须转义脚本块中的<
符号(或包含在CDATA部分中),并包含XHTML xmlns
声明。 例:
*:嗯,有DOM Level 3 LS的parseWithContext ,但浏览器支持很差。 编辑添加:但是,虽然您无法将标记注入SVGElement,但您可以使用innerHTML
将新的SVGElement注入HTMLElement,然后将其传输到所需的目标。 它可能会慢一点:
**:我讨厌HTML5的作者似乎害怕XML的方式,并决心将基于XML的function扼杀到HTML这个繁琐的混乱中。 XHTML多年前解决了这些问题。
接受的答案显示过于复杂的方式。 正如Forresto在他的回答中声称的那样,“ 它似乎确实将它们添加到DOM浏览器中,但不会添加到屏幕上 ”,其原因是html和svg的命名空间不同。
最简单的解决方法是“刷新”整个svg。 在附加圆圈(或其他元素)后,使用此:
$("body").html($("body").html());
这样就可以了。 圆圈在屏幕上。
或者如果你想,使用容器div:
$("#cont").html($("#cont").html());
并将你的svg包装在容器div中:
function示例:
http://jsbin.com/ejifab/1/edit
这种技术的优点:
- 你可以编辑现有的svg(已经在DOM中),例如。 使用Raphael创建或在您的示例中使用“硬编码”而无需编写脚本。
- 你可以添加复杂的元素结构作为字符串,例如
$('svg').prepend('
就像你在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文档添加过滤元素,虚拟对象可能类似于 。 文本表示首先使用jQuery的$(“body”)。append()方法转换为DOM。 当(filter)元素在DOM中时,可以使用标准jQuery方法查询它并将其附加到由Raphael创建的主SVG文档中。
为什么需要这个假人? 为什么不严格添加过滤元素到Raphael创建的文档? 如果您尝试使用例如。 $("svg").append("
,它被创建为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 = ' '; // Create dummy svg with filter definition $("body").append(''); // 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 hacks。
HTML
使用Javascript
var circle = d3.select("svg").append("circle") .attr("r", "10") .attr("style", "fill:white;stroke:black;stroke-width:5");
JQuery无法将元素附加到 (它似乎确实将它们添加到DOM资源管理器中,但不会添加到屏幕上)。
一种解决方法是将附加到页面所需的所有元素,然后使用
.attr()
修改元素的属性。
$('body') .append($('')) .mousemove( function (e) { $("#c").attr({ cx: e.pageX, cy: e.pageY }); });
我没有看到有人提到这个方法,但document.createElementNS()
在这个实例中很有帮助。
您可以使用vanilla Javascript创建元素作为具有正确名称空间的普通DOM节点,然后从那里使用jQuery-ify。 像这样:
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元素,否则它将无法工作。
我可以在firefox中看到圈子,做两件事:
1)将文件从html重命名为xhtml
2)将脚本更改为
找到一种适用于我所有浏览器的简单方法(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(' '); $('#svgObject').append(' '); // 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; }
It works if two shapes (one square and one circle) are displayed above.
基于@ chris-dolphin的答案,但使用辅助函数:
// 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);
如果您需要附加的字符串是SVG并且您添加了正确的命名空间,则可以将该字符串解析为XML并附加到父级。
var xml = jQuery.parseXML(' '); $("svg").append(xml.documentElement))
Bobince接受的答案是一个简短的便携式解决方案。 如果您不仅需要附加SVG而且还需要操作它,您可以尝试使用JavaScript库“Pablo” (我写了它)。 jQuery用户会觉得很熟悉。
您的代码示例将如下所示:
$(document).ready(function(){ Pablo("svg").append(' '); });
您还可以动态创建SVG元素,而无需指定标记:
var circle = Pablo.circle({ cx:100, cy:50, r:40 }).appendTo('svg');
我建议使用ajax并从另一个页面加载svg元素可能会更好。
$('.container').load(href + ' .svg_element');
其中href是带有svg的页面的位置。 这样您就可以避免替换html内容时可能出现的任何抖动。 此外,不要忘记在加载后打开svg:
$('.svg_element').unwrap();
var svg; // if you have variable declared and not assigned value. // then you make a mistake by appending elements to that before creating element svg.appendChild(document.createElement("g")); // at some point you assign to svg svg = document.createElementNS('http://www.w3.org/2000/svg', "svg") // then you put it in DOM document.getElementById("myDiv").appendChild(svg) // it wont render unless you manually change myDiv DOM with DevTools // to fix assign before you append var svg = createElement("svg", [ ["version", "1.2"], ["xmlns:xlink", "http://www.w3.org/1999/xlink"], ["aria-labelledby", "title"], ["role", "img"], ["class", "graph"] ]); function createElement(tag, attributeArr) { // .createElementNS NS is must! Does not draw without let elem = document.createElementNS('http://www.w3.org/2000/svg', tag); attributeArr.forEach(element => elem.setAttribute(element[0], element[1])); return elem; } // extra: for example requires attributes to render. Check if missing.
这对我今天的FF 57有用:
function () { // JQuery, today, doesn't play well with adding SVG elements - tricks required $(selector_to_node_in_svg_doc).parent().prepend($(this).clone().text("Your")); $(selector_to_node_in_svg_doc).text("New").attr("x", "340").text("New") .attr('stroke', 'blue').attr("style", "text-decoration: line-through"); }
使得:
一种更简单的方法是将SVG生成为字符串,创建包装HTML元素并使用$("#wrapperElement").html(svgString)
将svg字符串插入HTML元素。 这在Chrome和Firefox中运行良好。