2013-04-22 2 views
6

Я использую d3.js для создания диаграммы пончиков с надписями снаружи. Используя некоторую тригонометрию, основанную на центроидах каждого фрагмента пирога, я помещаю метки.d3js Перераспределение меток вокруг круговой диаграммы

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

То, что я в конечном счете, пытаюсь выполнить, чтобы изменить метки, которые находятся за пределами краев круговой диаграммы, чтобы предотвратить дублирование.

enter image description here

Один из способов я пытался решить эту проблему состоит в определении набора «опорные точки», где метки могут быть расположены, гарантируя, что они будут не перекрываются. Проблема заключается в сопоставлении центроидов с якорями и сохранении некоторого смысла визуального соответствия между срезами и ярлыками (особенно сложно, если срезы тонкие).

enter image description here

Изображение выше показывает возможное расположение анкеров (центроиды срезов показаны). С этими позициями невозможно совпадение.

Добавление сложности к проблеме заключается в том, что когда метки (они горизонтальные) расположены близко к верхней или нижней части пирога, они легче накладываются друг на друга, чем когда они находятся справа или слева от пирога ,

Любые идеи о том, как подойти к этой проблеме?

[EDIT] По предложению 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"; 
}) 

Это помогает немного, и дает некоторое пространство для этикеток, до сих пор ищет решение, которое будет охватывать все случаи, хотя. ..

+0

Не могли бы вы привести пример того, что у вас есть на jsfiddle? – Jonah

+0

Я добавил изображение для ясности. Я не реализовал в коде «якорь» решение, так как я разработал на бумаге различные случаи, когда он может потерпеть неудачу. – Cenobyte321

+0

Я вижу. В самом деле, у вас есть трудная проблема, и она действительно имеет мало общего с d3 как таковой: вы ищете общий алгоритм размещения меток на вашем графике. Можете ли вы сделать какие-либо предположения? Например, если бы все части были всего лишь зелеными и желтыми, просто не было бы хорошего способа разместить все ярлыки? Как насчет того, чтобы показывать ярлык только при наведении на части, которые ниже определенного размера? – Jonah

ответ

0

Не можете ли вы создать две дуги? один для диаграммы и один для ярлыков?

// 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; }); 
1

Существует хорошее, прагматичный d3.js основанного решения программиста John Williams представил здесь:

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

Он должен хорошо работать для случаев с разумными ограничениями, например, максимум 12 меток, как обсуждалось выше. В статье также есть указатели на более сложные алгоритмы, но этот простой подход может фактически использоваться при использовании с достаточными ограничениями на ярлык-ярлык для получения результатов, которые имеют более упорядоченный внешний вид, чем другие методы.

Смежные вопросы