2015-06-04 1 views
3

Я бы хотел показать ярлыки для крошечных фрагментов (chart.minAngleForLabel(0.05)), избегая перекрытия текста.Как разместить ярлыки на круговой диаграмме dc.js?

Я добавил renderlet, что сдвигает метки в сторону внешнего края:

.on('renderlet', function(chart) { 
     chart.selectAll('text').attr('transform', function(d, i) { 
      var old = this.getAttribute('transform'); 
      if (d.endAngle-d.startAngle > 0.3) { return old; } 
      var xy = old.slice(10,-1).split(','); 
      var m = 1.25 + (i%3) * 0.25; 
      return 'translate(' + (+xy[0]*m) + ',' + (+xy[1]*m) + ')'; 
     }) 
    }) 

и я довольно счастлива с ним (второе изображение после renderlet):

before after

но он вызывает раздражающие переходы - метки перемещаются в центр тяжести, а затем отскакивают назад. Есть ли обходной путь для этого?

ответ

4

Мое решение является немного чрезмерным, но я хотел бы знать, если это теперь возможно замененных перешедших позиции, now that we have the pretransition event в dc.js 2.0 Beta 11.

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

Мне не удалось заставить ваш код работать, поэтому я просто проверяю это, компенсируя все позиции ярлыков на -25, -25. Но это та же самая идея, мы используем исходный код, чтобы получить центроида, а затем изменить эту позицию:

// copied from pieChart 
function buildArcs(chart) { 
    return d3.svg.arc().outerRadius(chart.radius()).innerRadius(chart.innerRadius()); 
} 

function labelPosition(d, arc) { 
    var centroid = arc.centroid(d); 
    if (isNaN(centroid[0]) || isNaN(centroid[1])) { 
     return [0,0]; 
    } else { 
     return centroid; 
    } 
} 
// 
     .on('pretransition', function(chart) { 
      chart.selectAll('text.pie-slice').transition().duration(chart.transitionDuration()) 
       .attr('transform', function(d, i) { 
        var arc = buildArcs(chart); 
        var xy = labelPosition(d, arc); 
        return 'translate(' + (+xy[0] - 25) + ',' + (+xy[1] - 25) + ')'; 
      }) 
     }); 

Большая идея здесь заключается в том, что если вы задаете новый переход для элемента, он заменит переход который уже был активным. Таким образом, мы полностью удаляем исходное положение и переход и заменяем его собственными. Нет «прыгать»!

+0

Спасибо за добавление нового мероприятия! Одним из способов сделать размещение меток более гибким является то, что функция '_externalLabelRadius' должна быть функцией (в' labelPosition() '). Я думаю, что отрицательный '_externalLabelRadius' можно было бы злоупотреблять, чтобы установить внутренний радиус. Просто мысль. – marcin

+0

А это отличная идея. Я также думал о регуляторе положения метки, чтобы помочь изменить исходную рассчитанную позицию, как вы делаете, но то, что вы предлагаете, может быть более полезным. – Gordon

+0

Добавлена ​​проблема для обсуждения/решения: https://github.com/dc-js/dc.js/issues/945 – Gordon

2

Не совсем решить вашу проблему, но может выглядеть лучше с переходом на позицию?

chart.selectAll('text') 
    .transition() 
    .delay(800) 
    .attr("transform", ... 
+0

«Задержка» не годится, но с дополнительным переходом она выглядит действительно лучше. На самом деле довольно забавно - ярлык попал в центр, ударился друг в друга, а затем распространился. – marcin