Soy nuevo en el d3.js y yo estoy tratando de hacer un gráfico de Tarta con ella.
Sólo tengo un problema: no puedo entrar a mi las etiquetas fuera de mi arcos…
Las etiquetas se colocan con arco.centroide

arcs.append("svg:text")
    .attr("transform", function(d) {
        return "translate(" + arc.centroid(d) + ")";
    })
    .attr("text-anchor", "middle")

Quien me puede ayudar con esto?

  • Esta función calcula el punto central de la rebanada de pastel para un gráfico de tarta. Puedo agregar una función para obtener el punto central del arco. Abajo es una imagen basada en mi nueva función . consulte el enlace: github.com/mbostock/d3/issues/1124
  • Así que si quieres ir con un aspecto muy agradable leyenda en lugar de texto al azar colgar alrededor. He encontrado una solución bastante buena para las etiquetas. stackoverflow.com/questions/20675617/…

8 Comentarios

  1. 62

    Puedo resolver ese problema – con la trigonometría :).

    Ver violín: http://jsfiddle.net/nrabinowitz/GQDUS/

    Básicamente, llamando arc.centroid(d) devuelve un [x,y] matriz. Usted puede utilizar el Teorema de Pitágoras para calcular la hipotenusa, que es la longitud de la línea desde el centro de la tarta para el arco del centroide. A continuación, puede utilizar los cálculos x/h * desiredLabelRadius y y/h * desiredLabelRadius para calcular el deseado x,y para la etiqueta de anclaje:

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

    El único inconveniente aquí es que text-anchor: middle no es una gran elección ya – que estaría mejor ajuste de la text-anchor la base de qué lado de la tarta estamos en:

    .attr("text-anchor", function(d) {
        //are we past the center?
        return (d.endAngle + d.startAngle)/2 > Math.PI ?
            "end" : "start";
    })
    • Traté de tu técnica, pero no puede conseguir que funcione casi correctamente, el texto no cabe la tarta área de plnkr.co/editar/VYH5QbO99ZbMkvc2D4Fe?p=vista previa
    • Parece que funciona bien – puede establecer el display estilo de la etiqueta condicionalmente en d.endAngle - d.startAngle > someValue.
  2. 16

    Específicamente para los gráficos circulares, los d3.layout.pie() función de formato de datos con un startAngle y endAngle atributos. La radio puede ser lo que usted desea (la distancia desde el centro desea colocar la etiqueta).

    La combinación de estas piezas de información, con un par de funciones trigonométricas permite determinar las coordenadas x e y para las etiquetas.

    Considerar este gist/bloque.

    Con respecto a x/y posicionamiento del texto, la magia está en esta línea (formato para mejorar la legibilidad):

    .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 nos da el ángulo (theta) en radianes.
    • (radius - 12) es la arbitrariedad de la radio que he elegido para la posición del texto.
    • -1 * el eje y es invertida (ver más abajo).

    Las funciones trigonométricas que se utilizan son: cos = adjacent /hypotenuse y sin = opposite /hypotenuse. Pero hay un par de cosas que debemos considerar para hacer estos trabajos con nuestras etiquetas.

    1. 0 ángulo es a las 12 h.
    2. El ángulo aumenta en dirección de las agujas.
    3. El eje y es la inversa de la norma de sistema de coordenadas cartesianas. Y positivo en la dirección de las 6 de la mañana hacia abajo.
    4. X positivo es todavía en la dirección de las 3 de la tarde – a la derecha.

    Que se mete cosas un poco y, básicamente, tiene el efecto de intercambio de sin y cos. Nuestras funciones trigonométricas, a continuación, convertirse en: sin = adjacent /hypotenuse y cos = opposite /hypotenuse.

    La sustitución de los nombres de las variables que hemos sin(radians) = x /r y cos(radians) = y /r. Después de algunos manipulación algebraica podemos conseguir ambas funciones en términos de x y y respectivamente r * sin(radians) = x y r * cos(radians) = y. A partir de ahí, sólo tiene que enchufar en la transformación/traducir atributo.

    Que voy a poner los rótulos en el lugar correcto, para que se vean de lujo, necesitas algo de estilo lógica como este:

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

    Esto hará que las etiquetas de las 10:30 de la mañana a 1:30 de la mañana y desde las 4:30 de la mañana a las 7:30 de la mañana de anclaje en el medio (que están por encima y por debajo), las etiquetas de la 1:30 de la mañana a 4:30 de la mañana de anclaje a la izquierda (a la derecha), y las etiquetas de las 7:30 de la mañana a las 10:30 de la mañana de anclaje a la derecha (a la izquierda).

    Las mismas fórmulas se pueden usar para cualquier D3 gráfico radial, la única diferencia es la forma de determinar el ángulo.

    Espero que esto ayude a alguien tropezar a través de él!

  3. 15

    Gracias!

    He encontrado una manera diferente de resolver este problema, pero el tuyo parece mejor 🙂

    He creado un segundo de arco, con un mayor radio y la utilizó para la posición de mis etiquetas.

    /////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) + "%"});
    • Puntos para la legibilidad de la derecha aquí! Es allí una manera de clonar un existente arco, de modo que yo pudiera decir my_arc.clone.outerRadius(r + 20) en lugar de los d3.svg.arc()... ?
    • siempre se puede escribir una función que devuelve el radio que desee. Escribir una vez que la uso siempre que lo desee.
  4. 5

    No sé si esto ayuda, pero yo era capaz de crear arcos donde pongo el texto, ambos, en el arco y sólo fuera de ella. En un caso, donde pongo las magnitudes del arco dentro de los arcos, puedo girar el texto en el arco para que coincida con el ángulo del arco. En el otro, donde pongo el texto fuera del arco, es simplemente horizontal. El código se encuentra en: http://bl.ocks.org/2295263

    Lo Mejor De Mi,

    Frank

  5. 3

    sí bebé, es SOHCAHTOA

    JS:

    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)

  6. 1

    La siguiente CoffeeScript trabajado para mí para obtener etiquetas dentro de los sectores circulares, pero hacia el borde exterior:

    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) + ')'
  7. 1

    Este fue el bajo costo de respuesta que yo estaba feliz con. Empuja todas las etiquetas en forma horizontal (que es donde yo tenía el espacio extra):

    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; });
    • Esto podría ser un poco más simple manera de llevar el texto dentro o fuera del centroide. Primero inicializar centroide multiplicador cm a un valor, >1 para empujar a cabo, <1 exprimir hacia el centro. Intente cm=1.1 para empezar. El primer término se multiplica de forma horizontal y el segundo verticalmente. .attr(«transformar», function(d) { return «traducir(» + arco.centroide(d)[0]*cm + «, » + arco.centroide(d)[1]*cm + «)»; }) (lo siento originalmente publicado pos/neg en lugar de >1/<1.)
  8. 1

    He conseguido el mismo mediante el dibujo de un porcentaje de las etiquetas fuera del gráfico circular gráfico, aquí está el código 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 + '%';
          });

Dejar respuesta

Please enter your comment!
Please enter your name here