Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

117
Views
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 answers
Answer question

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!