4

In my code below, I am able to draw a Treemap and also display the tag in each tree cell. But the text is overflowing the tile if it's a long word

I need to ensure the word stays in the tile even If it means putting .... after certain characters. How can I achieve them? Please have a look at the version of chart.js and Treemap I am using before providing the solution. Thanks a lot :)


  var topTags = [
  {tag:'android',num:42657},{tag:'reactjs',num:38844},{tag:'php',num:34381},{tag:'sql',num:29996},
];

var canvas = document.getElementById("treemap");
var ctx = canvas.getContext("2d");
var chart = window.chart = new Chart(ctx, {
  type: "treemap",
  data: {
    datasets: [{
      tree: topTags,
      key: "num",
      groups: ['tag'],
      spacing: 0.5,
      borderWidth: 1.5,
      fontColor: "black",
      borderColor: "grey"
    }]
  },
  options: {
    maintainAspectRatio: false,
    legend: { display: false },
    tooltips: { enabled: false }
  }
});

CHART.JS AND TREEMAP VERSION :

<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js"></script>

<script src="https://cdn.jsdelivr.net/npm/chartjs-chart-treemap@0.2.3"></script>

Amila Senadheera
  • 12,229
  • 15
  • 27
  • 43
mewbie
  • 63
  • 2

1 Answers1

0

I solved it by splitting the text into multiple lines, starting a new line whenever the max width would be exceeded.

const chart = new Chart(context, {
    type: 'treemap',
      data:  {
        datasets: [
          {
/* ... */
            labels: {
              display: true,
              formatter(ctx: TreemapScriptableContext) {
                if (ctx.type !== 'data') {
                  return;
                }
                return splitLabelToFit(ctx.raw["_data"].label, ctx.raw.w*0.9, ctx);
              }
            }
          }
        ],
      },
    });

function splitLabelToFit(label: string, maxWidth: number, ctx: TreemapScriptableContext) {
    const words = label.split(' ');
    const lines = [];
    let currentLine = '';
    for (let i = 0; i < words.length; i++) {
      const word = words[i];
      const newLine = currentLine + ' ' + word;
      const width = ctx.chart.ctx.measureText(newLine).width;
      if (width < maxWidth) {
        currentLine = newLine;
      } else {
        lines.push(currentLine);
        currentLine = word;
      }
    }
    lines.push(currentLine);
    return lines;
  }
Timo Zikeli
  • 166
  • 1
  • 3
  • 7