Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/366.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript d3js围绕饼图重新分配标签_Javascript_D3.js - Fatal编程技术网

Javascript d3js围绕饼图重新分配标签

Javascript d3js围绕饼图重新分配标签,javascript,d3.js,Javascript,D3.js,我正在使用d3.js创建一个在外面有标签的甜甜圈图表。使用基于饼图每个切片质心的三角法,我定位标签 g.append("g") .attr("class", "percentage") .append("text") .attr("transform", function(d) { var c = arc.centroid(d);

我正在使用d3.js创建一个在外面有标签的甜甜圈图表。使用基于饼图每个切片质心的三角法,我定位标签

g.append("g")
        .attr("class", "percentage")
        .append("text")
            .attr("transform", function(d)
                { 
                    var c = arc.centroid(d);
                    var x = c[0];
                    var y = c[1];
                    var h = Math.sqrt(x*x + y*y);
                    return "translate(" + (x/h * obj.labelRadius) +  ',' + (y/h * obj.labelRadius) +  ")"; 
                }
            ) 
            .attr("dy", ".4em")
            .attr("text-anchor", function(d) 
                {
                    return (d.endAngle + d.startAngle)/2 > Math.PI ? "end" : "start";
                }
            )
            .text(function(d) { return d.data.percentage+"%"; });
我最终要做的是重新排列饼图边缘以外的标签,以防止重叠

我试图解决这个问题的方法之一是定义一组“锚定点”,在这里可以定位标签,保证它们不会重叠。问题是将质心映射到锚点,并在切片和标签之间保留某种视觉对应感(切片很薄时特别困难)

上图显示了锚的可能位置(所示切片的质心)。有了这些位置,就不可能有重叠

使问题更加复杂的是,当标签(它们是水平的)靠近饼图的顶部或底部时,它们比位于饼图的右侧或左侧时更容易重叠

关于如何解决这个问题有什么想法吗

[编辑]根据meetamit的建议,我实施了以下内容:

.attr("dy", function(d)
{
    var c = arc.centroid(d);
        var x = c[0];
        var y = c[1];
        var h = Math.sqrt(x*x + y*y);
        var dy = y/h * obj.labelRadius; 
    dy=dy*fontSizeParam*.14/heightParam);
    return (dy)+"em";
})

这有点帮助,并且给了标签一些空间,仍然在寻找一种解决方案来覆盖所有情况,但是…

你不能创建两个弧吗?一个用于图表,一个用于标签

// first arc used for drawing the pie chart
var arc = d3.svg.arc()
  .outerRadius(radius - 10)
  .innerRadius(0);

// label attached to first arc
g.append("text")
  .attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")"; })
  .attr("dy", ".35em")
  .style("text-anchor", "middle")
  .text(function(d) { return d.data.age; });

// second arc for labels
var arc2 = d3.svg.arc()
  .outerRadius(radius + 20)
  .innerRadius(radius + 20);

// label attached to second arc
g.append("text")
  .attr("transform", function(d) { return "translate(" + arc2.centroid(d) + ")"; })
  .attr("dy", ".35em")
  .style("text-anchor", "middle")
  .text(function(d) { return d.data.age; });

程序员John Williams在这里提出了一个很好的、基于实用的解决方案:


它应该适用于具有合理限制的情况,例如,如上所述,最多12个标签。文章中还指出了更高级的算法,但这种简单的方法在使用足够的标签内容约束时,实际上可能会产生比其他方法更有序的视觉效果。

你能举一个关于JSFIDLE的例子吗?为了清晰起见,我添加了一个图像。我还没有在代码中实现“锚定”解决方案,因为我已经在纸上解决了各种可能失败的情况。我明白了。事实上,您遇到了一个困难的问题,而且实际上与d3本身没有什么关系:您正在寻找一种在图形上放置标签的通用算法。你能做出任何假设吗?如果所有的标签都像绿色和黄色的一样小,那么根本就没有好办法把所有的标签都贴进去?对于低于一定尺寸的零件,只在悬停处显示标签怎么样?谢谢Jonah。Hover被排除在外,因为它们是触摸设备,不支持交互。一些可能的假设:不允许超过12个切片,所以标签的排列总是可能没有重叠。映射位置和保持视觉连贯性是这里的问题。你不能旋转标签以径向向外粘贴吗?