Home > Net >  Chart.js: Change lengend colors to array
Chart.js: Change lengend colors to array

Time:03-29

I have a chart with three datasets (Svelte REPL with code and result) and would like to change the background colors of the boxes corresponding to each set, for example:

let legendColors = ['#dddddd', '#aaaaaa', '#777777'];

After several attempts the closest I got was changing font color, but not even that as array, only a single one. :(

How do I get the boxes of the legend to be in the 3 colors I want?

Thank you in advance for your help!

Edit: I did find something here: What happened to generateLegend() in chartjs 3.0?, but that removes the functionality of the legend (i.e. removing parts of the data).

CodePudding user response:

Live Demo. I've found this is fun...

Some points to note:

  1. You need to build the legend yourself, as your colors are not "relevant" to the data you use (that's why by default it is using the colors from dataset "a")
  2. As you are using Svelte, in the Demo I used the <style> which binds with the <div> for the legend for styling of the legend.
  3. For people who ain't using Svelte, or are seeking solutions within Chart.js, they should follow the advice from the StackOverflow answer OP linked -- they need to build the legend using the plugins field of 2nd argument when creating a new Chart()

No matter which route to take, to keep the functionality of the legend as OP mentioned, I added a tweaked version of default behaviour of OnClick.

P.S. For (3) we have to further override generateLabels() (here, but may cause meta.controllers._resolveAnimation having problems, which we may still need to override onClick).

P.P.S. When a legend item is clicked, the label is crossed out (strikethrough) as a default behaviour. That is left as a further exercise or another answer. (For Svelte, use Boolean flags to change styles. Alternatively, hack with CSS checked checkbox labels).

CodePudding user response:

You can achieve this in 2 ways, using a custom generateLabels function or by specifying a backgroundcolor in the dataset.

Custom generateLabels:

let legendColors = ['#dddddd', '#aaaaaa'];

const options = {
  type: 'line',
  data: {
    labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
    datasets: [{
        label: '# of Votes',
        data: [12, 19, 3, 5, 2, 3],
        borderColor: 'pink'
      },
      {
        label: '# of Points',
        data: [7, 11, 5, 8, 3, 7],
        borderColor: 'orange'
      }
    ]
  },
  options: {
    plugins: {
      legend: {
        labels: {
          generateLabels: function(chart) {
            const datasets = chart.data.datasets;
            const {
              labels: {
                usePointStyle,
                pointStyle,
                textAlign,
                color
              }
            } = chart.legend.options;

            return chart._getSortedDatasetMetas().map((meta, i) => {
              const style = meta.controller.getStyle(usePointStyle ? 0 : undefined);
              const borderWidth = Chart.helpers.toPadding(style.borderWidth);

              return {
                text: datasets[meta.index].label,
                fillStyle: legendColors[i],
                fontColor: color,
                hidden: !meta.visible,
                lineCap: style.borderCapStyle,
                lineDash: style.borderDash,
                lineDashOffset: style.borderDashOffset,
                lineJoin: style.borderJoinStyle,
                lineWidth: (borderWidth.width   borderWidth.height) / 4,
                strokeStyle: style.borderColor,
                pointStyle: pointStyle || style.pointStyle,
                rotation: style.rotation,
                textAlign: textAlign || style.textAlign,
                borderRadius: 0, // TODO: v4, default to style.borderRadius

                // Below is extra data used for toggling the datasets
                datasetIndex: meta.index
              };
            }, this);
          }
        }
      }
    }
  },
}

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.7.1/chart.js"></script>
</body>

Adding background color prop in datasets:

const options = {
  type: 'line',
  data: {
    labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
    datasets: [{
        label: '# of Votes',
        data: [12, 19, 3, 5, 2, 3],
        borderColor: 'pink',
        pointBackgroundColor: 'pink',
        backgroundColor: '#dddddd'
      },
      {
        label: '# of Points',
        data: [7, 11, 5, 8, 3, 7],
        borderColor: 'orange',
        pointBackgroundColor: 'orange',
        backgroundColor: '#aaaaaa'
      }
    ]
  },
  options: {},
}

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.7.1/chart.js"></script>
</body>

  • Related