Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

119
Vistas
How do I split labels for my donut chart to multiple lines using d3.js?

I am displaying labels with my donut chart like this;

this.graphGroup
      .selectAll('allLabels')
      .data(data_ready)
      .enter()
      .append('text').style('font-size', '24px')
      .text(d => {
        return d.data.name;   //LINE 1
      })
      .attr('transform',`${calculatedValue}`)
      .style('text-anchor', 'start');

I want to use this answer How do I include newlines in labels in D3 charts? but adding the code after this addition of labels like this,

this.graphGroup
    .selectAll('text')
    .each
    ( function (d) {
      var el = this.d3.select(this);
      console.log(el);
      var words = d.name.split(' ');
      console.log(words);
      el.text('');

      for (var i = 0; i < words.length; i++) {
        var tspan = el.append('tspan').text(words[i]);
        if (i > 0)
          tspan.attr('x', 0).attr('dy', '15');
      }
    });

When I use the each() on the first selection I get an error saying the selection is undefined. I tried adding the code on line 1 but I can only pass text into a d3.text().

How can I break the labels correctly?

EDIT: I also had an error saying my local variable d3 was undefined, but it worked while creating the graphGroup and all the other selections, I then imported select from d3 directly.

about 4 years ago · Juan Pablo Isaza
1 Respuestas
Responde la pregunta

0

I figured out the answer; each() does not work if the data() function has been called on that selection, so the answer directly from the linked post will not work.

The other option is to use the call() on every text element made, like this;

this.graphGroup
      .selectAll('allLabels')
      .data(data_ready)
      .enter()
      .append('text').style('font-size', '24px')
      .attr('transform',`${calculatedValue}`)
      .style('text-anchor', 'start')
      .text(d => {
        return d.data.name;
      })
      .call(lineBreak, 40);

Where lineBreak is another function I have defined, the first parameter that gets passed into the function will be a reference to the looped element in the case, the different text elements.

the linebreak function:

function lineBreak(text, width) {
      text.each(function () {
        var el = d3.select(this);
        let words = el.text().split(' ');
        let wordsFormatted = [];

        let string = '';
        for (let i = 0; i < words.length; i++) {
          if (words[i].length + string.length <= width) {
            string = string + words[i] + ' ';
          }
          else {
            wordsFormatted.push(string);
            string = words[i] + ' ';
          }
        }
        wordsFormatted.push(string);

        el.text('');
        for (var i = 0; i < wordsFormatted.length; i++) {
          var tspan = el.append('tspan').text(wordsFormatted[i]);
          if (i > 0)
            tspan.attr('x', 0).attr('dy', '20');
        }
      });
    }

Will optimize this function and edit later. Thanks!

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda