工作解决方案
主要问题是 SVG 元素上没有innerHTML
属性,您需要自己创建所有子节点。但是您可以通过仅使用此字符串创建一个临时 DOM 对象,将您的 HTML 字符串转换为样式化tspan
的 s(没有)字符串解析魔法。之后,您可以使用 d3 创建正确的 tspans 元素。
var text = d3.select("#test"), tmp = document.createElement("text"); //create tmp
tmp.innerHTML = 'aaa <tspan style="font-weight:bold">bbb</tspan> ccc' //create HTML children (not yet an SVG!)
var nodes = Array.prototype.slice.call(tmp.childNodes) //create a real array from the childNodes variable
nodes.forEach( function(node) {
text.append("tspan")
.attr("style", node.getAttribute && node.getAttribute("style"))
.text(node.textContent)
})
剩余问题:此解决方案不支持 tspan 中的子节点,这需要遍历源childNodes
元素的tspans(或其他标签)。这最终将导致一个子 tspan 兼容的解析器完全解决这个问题。style
append
tspan
编辑:有一个更通用的innerSVG 垫片,也可以处理子节点。
破碎的解决方案
还有一些其他解决方案应该可以工作,但目前已被破坏。正如其他人已经指出的那样,.html()
直接在 jQuery 或 d3 中使用是行不通的,因为它们依赖于innerHTML
.
//not working
$("#test").html(...); d3.select("#test").html(...)
通过 jQuery 复制和附加(类似于我的工作解决方案)也被破坏了。它创建了正确的 DOM,但未显示 tspan(在 Firefox 和 Chrome 中尝试过):
//creates correct DOM, but disables/hides the created tspan
var tmp = $("<text>")
tmp.html('aaa <tspan style="font-weight:bold">bbb</tspan> ccc')
$("#test").append( Array.prototype.slice.call(tmp[0].childNodes) )
根据 W3C 规范,应该可以混合使用tspan 和 TextNode。