我想让文本包装在以下D3树上,而不是
Foo is not a long word
每条线都被包裹起来
Foo is not a long word
我已经尝试使文本为“foreignObject”而不是文本对象,文本确实包含,但它不会在树动画上移动,并且都分组在左上角.
代码位于
http://jsfiddle.net/mikeyai/X43X5/1/
使用Javascript:
var width = 960,height = 500; var tree = d3.layout.tree() .size([width - 20,height - 20]); var root = {},nodes = tree(root); root.parent = root; root.px = root.x; root.py = root.y; var diagonal = d3.svg.diagonal(); var svg = d3.select("body").append("svg") .attr("width",width) .attr("height",height) .append("g") .attr("transform","translate(10,10)"); var node = svg.selectAll(".node"),link = svg.selectAll(".link"); var duration = 750,timer = setInterval(update,duration); function update() { if (nodes.length >= 500) return clearInterval(timer); // Add a new node to a random parent. var n = {id: nodes.length},p = nodes[Math.random() * nodes.length | 0]; if (p.children) p.children.push(n); else p.children = [n]; nodes.push(n); // Recompute the layout and data join. node = node.data(tree.nodes(root),function(d) { return d.id; }); link = link.data(tree.links(nodes),function(d) { return d.source.id + "-" + d.target.id; }); // Add entering nodes in the parent’s old position. node.enter().append("text") .attr("class","node") .attr("x",function(d) { return d.parent.px; }) .attr("y",function(d) { return d.parent.py; }) .text('Foo is not a long word'); // Add entering links in the parent’s old position. link.enter().insert("path",".node") .attr("class","link") .attr("d",function(d) { var o = {x: d.source.px,y: d.source.py}; return diagonal({source: o,target: o}); }); // Transition nodes and links to their new positions. var t = svg.transition() .duration(duration); t.selectAll(".link") .attr("d",diagonal); t.selectAll(".node") .attr("x",function(d) { return d.px = d.x; }) .attr("y",function(d) { return d.py = d.y; }); }
解决方法
您可以修改
Mike Bostock’s “Wrapping Long Labels” example以添加< tspan>元素到您的< text>节点.将包装文本添加到您的节点需要两个主要更改.我没有深入了解文本在过渡期间更新其位置,但不应该太难添加.
第一个是在上面的例子中添加一个基于函数的函数换行符. wrap将负责添加< tspan>元素使您的文字适合一定宽度:
function wrap(text,width) { text.each(function () { var text = d3.select(this),words = "Foo is not a long word".split(/\s+/).reverse(),word,line = [],lineNumber = 0,lineHeight = 1.1,// ems x = text.attr("x"),y = text.attr("y"),dy = 0,//parseFloat(text.attr("dy")),tspan = text.text(null) .append("tspan") .attr("x",x) .attr("y",y) .attr("dy",dy + "em"); while (word = words.pop()) { line.push(word); tspan.text(line.join(" ")); if (tspan.node().getComputedTextLength() > width) { line.pop(); tspan.text(line.join(" ")); line = [word]; tspan = text.append("tspan") .attr("x",x) .attr("y",y) .attr("dy",++lineNumber * lineHeight + dy + "em") .text(word); } } }); }
第二个变化是,不需要设置每个节点的文本,您需要为每个节点调用换行符:
// Add entering nodes in the parent’s old position. node.enter().append("text") .attr("class","node") .attr("x",function (d) { return d.parent.px; }) .attr("y",function (d) { return d.parent.py; }) .call(wrap,30); // wrap the text in <= 30 pixels