2013-10-22 57 views
3

我已经看到D3.js- Voronoi Tessellation的例子。但我希望把一些文字中的每个多边形,而不是圆的,这是我的js代码:如何用D3.js限制Voronoi图中的多边形文本?

var width = 600, height = 400; 

var vertices = d3.range(20).map(function(d){ 
    return [Math.random() * width, Math.random() * height] 
}); 

var voronoi = d3.geom.voronoi(); 

var svg = d3.select("body").append("svg") 
    .attr("width", width) 
    .attr("height", height); 

path = svg.append("g").selectAll("path"); 

svg.selectAll("info") 
    .data(vertices.slice(1)) 
    .enter().append("text") 
    .attr("transform", function(d) { 
     return "translate(" + d + ")"; 
    }) 
    .text("someText") 
    .attr("shape-rendering","crispEdges") 
    .style("text-anchor","middle"); 

redraw(); 

function redraw(){ 
    path = path 
     .data(voronoi(vertices), polygon); 

    path.exit().remove(); 

    path.enter().append("path") 
     .attr("class", function(d, i) {return "q" + (i % 9) + "-9";}) 
     .attr("d", polygon); 

    path.order(); 
} 

function polygon(d){ 
    return "M" + d.join("L") + "Z"; 
} 

我有一个的jsfiddle为这里的基本示例: my voronoi code

现在,我希望每个多边形的文本位于多边形的中心,并且不要与多边形的边框交叉。如果多边形没有足够的空间来容纳全部文本,只需包含它的第一部分! 让我知道如果有什么我可以做的解决这个问题,谢谢! PS:我很抱歉我的英语,是的,它太可怜了! :)

+0

件文成多边形是不平凡的。首先,您需要找出文本的最佳位置(因为某些多边形非常不规则),然后确定文本的大小,多边形的大小以及它们相交的位置。然后根据这个缩短文本。剪辑路径可能会更容易。 –

+0

@LarsKotthoff你能告诉我一些关于剪辑路径的文章吗? :) – CodingMonkey

+0

看看例如[这里](http://www.svgbasics.com/clipping.html)。 –

回答

3

看看这个例子http://bl.ocks.org/mbostock/6909318,你可能想把文本放置在多边形质心而不是用来确定voronoi镶嵌的种子(点)。

这应该解决您的大部分布局问题。

自动缩放文本以适应是有点困难,如果你愿意缩放和旋转,你可以使用类似如下的技术来确定该点的行的文本长度:

https://mathoverflow.net/questions/116418/find-longest-segment-through-centroid-of-2d-convex-polygon

然后你需要确定线的角度。我有一个插件,应该有所帮助: http://bl.ocks.org/stephen101/7640188/3ffe0c5dbb040f785b91687640a893bae07e36c3

最后,您需要缩放和旋转文本以适合。为了确定文本的宽度使用getBBox()的文本元素:

var text = svg.append("svg:text") 
    .attr("x", 480) 
    .attr("y", 250) 
    .attr("dy", ".35em") 
    .attr("text-anchor", "middle") 
    .style("font", "300 128px Helvetica Neue") 
    .text("Hello, getBBox!"); 

var bbox = text.node().getBBox(); 

然后,可以使用前面计算的缩放和旋转文本的角度:

text.attr("transform", "rotate(40) scale(7)") 

我很乐意给一个完整的例子,但这是相当多的工作,以使其正确。

还有其他选项,以达到同样的效果,但他们都不是简单的(例如,你可以退火相似D3的方式做了桑基布局布局)