7

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+"%"; });

私が最終的に達成しようとしているのは、円グラフの端の外側にあるラベルを再配置して、重複を防ぐことです。

ここに画像の説明を入力

私がこの問題を解決しようとした方法の 1 つは、ラベルを配置できるセットの「アンカー ポイント」を定義することです。問題は、セントロイドをアンカーにマッピングし、スライスとラベルの間の視覚的な対応関係を維持することです (スライスがスリムな場合は特に困難です)。

ここに画像の説明を入力

上の画像は、アンカーの可能な位置を示しています (表示されているスライスの重心)。これらの位置では、オーバーラップすることはできません。

問題を複雑にしているのは、ラベル (水平) が円グラフの上部または下部に近い場合、円グラフの右側または左側にある場合よりも簡単に重なり合うという事実です。

この問題にアプローチする方法についてのアイデアはありますか?

[編集] 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";
})

それは少し役立ち、ラベルにいくらかの余地を与えますが、それでもすべてのケースをカバーするソリューションを探しています...

4

2 に答える 2

1

2 つの円弧を作成できませんか? 1 つはグラフ用で、もう 1 つはラベル用ですか?

// 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; });
于 2013-10-23T21:12:41.500 に答える
1

プログラマー John Williams によるd3.jsベースの優れた実用的なソリューションがここに示されています。

https://www.safaribooksonline.com/blog/2014/03/11/solving-d3-label-placement-constraint-relaxing/

上記のように最大 12 個のラベルなど、妥当な制限がある場合にはうまく機能するはずです。この記事には、より高度なアルゴリズムへのポインタもありますが、この単純なアプローチは、実際には、十分なラベル コンテンツの制約と共に使用すると、他の方法よりも整然とした視覚的外観を持つ結果をもたらす可能性があります。

于 2015-08-25T09:38:56.027 に答える