Etykieta poza łukiem (Wykres kołowy) d3.js

Jestem nowy w d3.JS i ja próbujemy z nim zrobić Wykres kołowy. Mam tylko jeden problem: nie mogę wyjąć etykiet poza moje łuki... Etykiety są pozycjonowane łukiem.centroid

arcs.append("svg:text")
    .attr("transform", function(d) {
        return "translate(" + arc.centroid(d) + ")";
    })
    .attr("text-anchor", "middle")
Kto mi w tym pomoże?
Author: peller, 2011-11-08

10 answers

Mogę rozwiązać ten problem-z trygonometrii :).

Zobacz: http://jsfiddle.net/nrabinowitz/GQDUS/

Zasadniczo wywołanie arc.centroid(d) zwraca tablicę [x,y]. Możesz użyć twierdzenia Pitagorasa, aby obliczyć przeciwprostokątną, która jest długością linii od środka ciasta do centroidu łuku. Następnie możesz użyć obliczeń x/h * desiredLabelRadius i y/h * desiredLabelRadius, aby obliczyć żądaną wartość x,y dla kotwicy etykiety:

.attr("transform", function(d) {
    var c = arc.centroid(d),
        x = c[0],
        y = c[1],
        // pythagorean theorem for hypotenuse
        h = Math.sqrt(x*x + y*y);
    return "translate(" + (x/h * labelr) +  ',' +
       (y/h * labelr) +  ")"; 
})

Jedynym minusem jest to, że text-anchor: middle to już nie jest dobry wybór - lepiej byłoby ustawić text-anchor w oparciu o to, po której stronie ciasta jesteśmy:

.attr("text-anchor", function(d) {
    // are we past the center?
    return (d.endAngle + d.startAngle)/2 > Math.PI ?
        "end" : "start";
})
 58
Author: nrabinowitz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-19 23:43:17

Dzięki!

Znalazłem inny sposób na rozwiązanie tego problemu, ale twój wydaje się lepszy: -)

Stworzyłem drugi łuk o większym promieniu i użyłem go do pozycjonowania etykiet.

///// Arc Labels ///// 
// Calculate position 
var pos = d3.svg.arc().innerRadius(r + 20).outerRadius(r + 20); 

// Place Labels 
arcs.append("svg:text") 
       .attr("transform", function(d) { return "translate(" + 
    pos.centroid(d) + ")"; }) 
       .attr("dy", 5) 
       .attr("text-anchor", "middle") 
       .attr("fill", function(d, i) { return colorL(i); }) //Colorarray Labels
       .attr("display", function(d) { return d.value >= 2 ? null : "none"; })  
       .text(function(d, i) { return d.value.toFixed(0) + "%"});
 15
Author: Ibe Vanmeenen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-25 14:43:25

Specjalnie dla wykresów kołowych, Funkcja d3.layout.pie() będzie formatować dane za pomocą atrybutów startAngle i endAngle. Promień może być dowolny (jak daleko od centrum chcesz umieścić etykietę).

Połączenie tych informacji z parą funkcji trygonometrycznych pozwala określić współrzędne x i y dla etykiet.

Rozważmy to gist/blok .

Jeśli chodzi o pozycjonowanie X / y tekstu, magia jest w tej linii (sformatowanej pod kątem czytelności):

.attr("transform", function(d) {
  return "translate(" + 
    ( (radius - 12) * Math.sin( ((d.endAngle - d.startAngle) / 2) + d.startAngle ) ) +
    ", " +
    ( -1 * (radius - 12) * Math.cos( ((d.endAngle - d.startAngle) / 2) + d.startAngle ) ) +
  ")";
 })
  • ((d.endAngle - d.startAngle) / 2) + d.startAngle daje nam nasz kąt (theta) w radianach.
  • (radius - 12) to dowolny promień, który wybrałem dla pozycji tekstu.
  • -1 * oś y jest odwrócona (patrz niżej).

Używane funkcje Tryg to: cos = adjacent / hypotenuse i sin = opposite / hypotenuse. Ale jest kilka rzeczy, które musimy rozważyć, aby działały z naszymi etykietami.

  1. 0 kąt jest na godzinie dwunastej.
  2. kąt wciąż wzrasta w zgodnie z ruchem wskazówek zegara.
  3. oś y jest odwrócona od standardowego kartezjańskiego układu współrzędnych. Dodatnie y jest w kierunku 6 o ' Clock-w dół.
  4. dodatni x jest nadal w kierunku 3 o ' Clock-prawo.

To trochę namiesza i w zasadzie ma efekt zamiany sin i cos. Nasze funkcje Tryg stają się wtedy: sin = adjacent / hypotenuse i cos = opposite / hypotenuse.

Podstawiając nazwy zmiennych mamy sin(radians) = x / r i cos(radians) = y / r. Po jakiejś algebraicznej manipulacji możemy get obie funkcje w kategoriach x i y odpowiednio r * sin(radians) = x i r * cos(radians) = y. Stamtąd po prostu podłącz je do atrybutu transform/translate.

To umieści etykiety we właściwym miejscu, aby wyglądały fantazyjnie, potrzebujesz logiki stylizacji takiej jak ta:

.style("text-anchor", function(d) {
    var rads = ((d.endAngle - d.startAngle) / 2) + d.startAngle;
    if ( (rads > 7 * Math.PI / 4 && rads < Math.PI / 4) || (rads > 3 * Math.PI / 4 && rads < 5 * Math.PI / 4) ) {
      return "middle";
    } else if (rads >= Math.PI / 4 && rads <= 3 * Math.PI / 4) {
      return "start";
    } else if (rads >= 5 * Math.PI / 4 && rads <= 7 * Math.PI / 4) {
      return "end";
    } else {
      return "middle";
    }
  })

Spowoduje to, że etykiety od 10: 30 do 1:30 i od 4:30 do 7: 30 zakotwiczą w środku (są powyżej i poniżej), etykiety od 1:30 do 4: 30 zakotwiczą po lewej stronie (są po prawej), a etykiety od 7:30 do 10: 30 Kotwica po prawej (są po lewej).

Te same wzory mogą być używane dla dowolnego grafu promieniowego D3, jedyną różnicą jest sposób wyznaczania kąta.

Mam nadzieję, że to pomoże każdemu, kto się na to natknie!

 14
Author: clayzermk1,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-17 20:10:30

Nie wiem, czy to pomaga, ale udało mi się stworzyć łuki, w których umieszczam tekst, zarówno na łuku, jak i na zewnątrz. W jednym przypadku, gdzie umieszczam magnitudę łuku w łukach, obracam tekst na łuku, aby dopasować kąt łuku. W drugim, gdzie umieszczam tekst poza łukiem, jest on po prostu poziomy. Kod znajduje się pod adresem: http://bl.ocks.org/2295263

My Best,

Frank

 5
Author: Information Technology,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-19 03:28:04

Yes baby, it ' s SOHCAHTOA

function coordinates_on_circle(hyp, angle){
  var radian= angle * Math.PI / 180 //trig uses radians
  return {
    x: Math.cos(radian) * hyp, //adj = cos(r) * hyp
    y: Math.sin(radian) * hyp //opp = sin(r) * hyp
  }
}
var radius=100
var angle=45
coordinates_on_circle(radius, angle)
 2
Author: spencercooly,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-30 20:14:09

Następujący CoffeeScript pracował dla mnie, aby etykiety nadal wewnątrz plastrów ciasta, ale w kierunku zewnętrznej krawędzi:

attr 'transform', (d) ->
  radius = width / 2 # radius of whole pie chart
  d.innerRadius = radius * 0.5
  d.outerRadius = radius * 1.5
  'translate(' + arc.centroid(d) + ')'
 1
Author: Sarah Vessels,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-29 22:54:35

Ta funkcja obliczała punkt środkowy wycinka dla wykresu kołowego. Dodaję funkcję, aby uzyskać punkt środkowy łuku. Poniżej znajduje się obraz oparty na mojej nowej funkcji . zobacz link: https://github.com/mbostock/d3/issues/1124

 1
Author: Sean Wang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-07 08:10:48

To była tania odpowiedź, z której byłem zadowolony. Wypycha wszystkie etykiety poziomo (tam miałem dodatkową przestrzeń):

g.append("text")
  .attr("transform", function(d) { 
      var pos = arc.centroid(d); 
      return "translate(" + (pos[0] + (.5 - (pos[0] < 0)) * radius) + "," + (pos[1]*2) + ")"; 
  })
  .attr("dy", ".35em")
  .style("text-anchor", function(d) { 
      return arc.centroid(d)[0] > 0 ? "start" : "end";
   })
  .text(function(d) { return d.label; });
 1
Author: cheepychappy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-18 04:19:17

Więc jeśli chcesz iść z bardzo ładnie wyglądającą legendą zamiast przypadkowego tekstu kręcącego się wokół. Znalazłem całkiem dobre rozwiązanie dla etykiet. Jak dodać legendę do wykresu kołowego za pomocą D3js? Jak scentralizować Wykres kołowy?

 1
Author: DeadlyChambers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:30:47

Osiągnąłem to samo rysując procent jako etykiety poza wykresem kołowym, oto kod http://bl.ocks.org/farazshuja/e2cb52828c080ba85da5458e2304a61f

g.append("text")
        .attr("transform", function(d) {
        var _d = arc.centroid(d);
        _d[0] *= 2.2;   //multiply by a constant factor
        _d[1] *= 2.2;   //multiply by a constant factor
        return "translate(" + _d + ")";
      })
      .attr("dy", ".50em")
      .style("text-anchor", "middle")
      .text(function(d) {
        if(d.data.percentage < 8) {
          return '';
        }
        return d.data.percentage + '%';
      });
 1
Author: FarazShuja,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-22 06:31:30