如何使用D3.js限制Voronoi图中多边形的文本?

3

我看过D3.js的例子- Voronoi Tessellation。但是我想在每个多边形中放置一些文本,而不是一个圆圈。这里是我的js代码:

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: 我的voronoi代码 现在,我希望每个多边形的文本都位于多边形的中心,并且不要与多边形的边框重叠。如果多边形没有足够的空间来容纳所有文本,只需包含其第一部分即可! 请让我知道是否有什么可以解决这个问题,谢谢!
PS:非常抱歉我的英语很差! :)

将文本适配到多边形中并不容易。首先,您需要确定文本的最佳位置(因为一些多边形的形状非常不规则),然后确定文本的大小、多边形的大小以及它们的交点。然后根据这个缩短文本。使用剪辑路径可能更容易实现这一点。 - Lars Kotthoff
@LarsKotthoff 你能给我展示一些有关剪辑路径的文章吗? :) - CodingMonkey
请看这里:http://www.svgbasics.com/clipping.html。 - Lars Kotthoff
1个回答

4
请看这个例子:http://bl.ocks.org/mbostock/6909318,你可能希望将文本放置在多边形的质心而不是用于确定 Voronoi tessellation 的种子(点)。

那应该可以解决大部分布局问题。

自动缩放文本以适应所需大小需要一些技术。如果您愿意缩放和旋转文本,则可以使用类似于以下技术来确定该点处线段的长度:

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一样使布局退火)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接