SVG文本的动态样式

时间:2012-12-19 22:26:23

标签: javascript svg d3.js

<svg>
    <text id="test" x="0" y="15"></text>
</svg>

d3.select("#test").text("aaa");

document.getElementById("test").textContent("aaa");

工作正常。但我需要在文本中添加样式。现在:

d3.select("#test").text('aaa <tspan style="font-weight:bold">bbb</tspan> ccc');
遗憾的是,

不起作用,因为该参数被视为纯字符串。针对此问题的最佳跨浏览器解决方案是什么?

4 个答案:

答案 0 :(得分:5)

工作解决方案

主要问题是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)
})

剩余问题:此解决方案不支持tspans中需要遍历源元素childNodes的子节点,复制style(可能还有其他属性)从子节点和append新的子tspan元素(和其他可能的标签)到相应的父tspans(或其他标签)。这最终将导致一个sub tspan兼容的解析器来完全解决这个问题。

编辑:还有一个更通用的innerSVG shim,它也可以处理子节点。

破碎的解决方案

还有一些其他解决方案应该可行,但目前已被打破。正如其他人已经指出的那样,直接在jQuery或d3中使用.html()不起作用,因为它们依赖于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规范,应该可以mix tspan和TextNodes。

答案 1 :(得分:0)

var t = d3.select("#test")
t.append("tspan").text("aaa ");
t.append("tspan").text("bbb").style("font-weight","bold");
t.append("tspan").text(" ccc");

答案 2 :(得分:-1)

document.getElementById("test").style.fontWeight="bold"

上述内容会改变一切。

但你可以试试innerHTML方法:

document.getElementById("test").innerHTML('aaa <tspan style=\"font-weight:bold\">bbb</tspan> ccc');

答案 3 :(得分:-3)

试试这个

d3.select("#test").html('aaa <tspan style="font-weight:bold">bbb</tspan> ccc');