Boosted_d16
Boosted_d16

Reputation: 14082

chartjs data labels - character level font colour control

I want to set font colour at character level (or word level) in my data-labels in chartjs. See before and after image below.

For example, if my data-label is 0.89 I would like the paint the 0 as yellow, 8 as blue and 9 as red.

enter image description here

Sandbox: https://codesandbox.io/s/quizzical-hooks-zcg91?file=/src/components/LineChart.jsx

Upvotes: 0

Views: 184

Answers (1)

LeeLenalee
LeeLenalee

Reputation: 31401

Afaik you can set the individual collors of the letters with the datalabels plugin, you will need to write your own custom plugin for that, what you can do is provide an array of collors to the color property to give each entry a different collor: https://codesandbox.io/s/dazzling-leaf-pxmzm

datalabels: {
      display: true,
      color: ["black", "green", "blue", "pink", "purple"],
      align: "end",
      padding: {
        right: 2
      },
      labels: {
        padding: { top: 10 },
        title: {
          font: {
            weight: "bold"
          }
        }
      },
      formatter: function (value) {
        return "\n" + value;
      }
    }

Edit:

after looking at the code the datalabels plugin uses to render the labels its not possible to color individual characters, if you want that you will need to write your own custom plugin:

const customDatalabalesPlugin = {
  id: 'customDatalabels',
  afterDatasetsDraw: (chart, args, opts) => {
    const {
      ctx,
      _metasets
    } = chart;
    _metasets.forEach((meta) => {
      meta.data.forEach((datapoint) => {
        const lineHeight = ctx.measureText('M').width;
        const dpVal = datapoint.parsed.y;
        const text = dpVal.toString();
        const textWidth = ctx.measureText(text).width;
        const color = opts.color || 'black';

        if (typeof color === 'string') {
          ctx.fillStyle = color;
          ctx.fillText(text, (datapoint.x - textWidth / 2), (datapoint.y - lineHeight));
        } else if (Array.isArray(color)) {
          let x = datapoint.x - textWidth / 2;

          for (let i = 0; i < text.length; i++) {
            const char = text.charAt(i);

            ctx.fillStyle = color[i % color.length];
            ctx.fillText(char, x, (datapoint.y - lineHeight));
            x += ctx.measureText(char).width;
          }
        } else {
          console.error('Invalid color type provided');
        }
      })
    })
  }
}

const options = {
  type: 'line',
  data: {
    labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
    datasets: [{
      label: '# of Votes',
      data: [12.4, 19.234, 3.23213, 5.4, 2, 3],
      borderColor: 'pink'
    }]
  },
  options: {
    plugins: {
      customDatalabels: {
        color: ['pink', 'green', 'orange'], // Color each character individual collor
        // color: 'pink' // Color whole label this collor
      }
    }
  },
  plugins: [customDatalabalesPlugin]
}

const ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
  <canvas id="chartJSContainer" width="600" height="400"></canvas>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.0/chart.js"></script>
</body>

Upvotes: 1

Related Questions