How set color family to pie chart in chart.js
Asked Answered
P

4

22

I am trying to draw a pie chart using Chart.js. My values are coming from a database hence I don't know how many values there are going to be in the database. Here I want to set set a unique color to each value. Below is my example.

var pieData = [
    {
        value: 20,
        color:"#878BB6"
    },
    {
        value : 40,
        color : "#4ACAB4"
    },
    {
        value : 10,
        color : "#FF8153"
    },
    {
        value : 30,
        color : "#FFEA88"
    }
];

var pieOptions = {
    segmentShowStroke : false,
    animateScale : true
}

var countries= document.getElementById("countries").getContext("2d");
        new Chart(countries).Pie(pieData, pieOptions);

Currently in above example I have set hard coded values but in my example data (Json) is coming from DB.

Progestin answered 3/3, 2015 at 10:3 Comment(0)
L
9

You could loop thought your pieData array and set random values for the color value.

You can set this one with a value like "rgb(230,0,0)" and generate the red green blue integer values randomly.

Something like this :

r = Math.floor(Math.random() * 200);
g = Math.floor(Math.random() * 200);
b = Math.floor(Math.random() * 200);
color = 'rgb(' + r + ', ' + g + ', ' + b + ')';

See an example jsfiddle here, with random values and random colors. (Run it several times to get an idea of how it displays with different data sets.)

Or else you could define an array of predefined colors and just use that. Consider that a pie chart with more than 50 items is not very readeable. So a default list of 50 might just be ok.

Labyrinthine answered 4/3, 2015 at 17:19 Comment(3)
Hey sorry, I followed your jsfiddle code but it does not work. The chart is showing nothing and no error message. Do you have any idea why is it so?Hagiology
Hi Denise. I was calling chart.js from a cdn that no longer exists. It's fixed now. Give it a try, I've updated the link.Labyrinthine
You can also multiply to 255 instead of 200 as each RGB value ranges from 0 to 255.Chadwell
C
30

I have created a simple color family with 15 different colors.
They are not randomly chosen. Instead, the colors have been chosen to maximize the difference between near colors.

You can still create the chart with less than 15 data points and no warning will be generated.

Here is the code:

ctx = document.getElementById('myChart').getContext('2d');
chart = new Chart(ctx, {
    type: 'pie',
    data: {
        datasets: [{
            label: 'Colors',
            data: [9, 8, 7, 6, 5, 4, 3, 2, 1],
            backgroundColor: ["#0074D9", "#FF4136", "#2ECC40", "#FF851B", "#7FDBFF", "#B10DC9", "#FFDC00", "#001f3f", "#39CCCC", "#01FF70", "#85144b", "#F012BE", "#3D9970", "#111111", "#AAAAAA"]
        }],
        labels: ['a','b','c','d','e','f','g','h','i']
    },
    options: {
        responsive: true,
        title:{
            display: true,
            text: "Color test"
        }
    }
});

This is the html:

<canvas id="myChart" width="600" height="400"></canvas>

enter image description here

If you want to play with it, here is the code on jsfiddle.

I hope this will help :)

Covetous answered 3/8, 2017 at 16:12 Comment(1)
I am trying to start out with an empty array of backgroundColor and using a for loop over the data to fill up the backgroundColor with random color values. This does not work. Any clue why? Also, when I hover over the slices of the pie, colors appear but this happens only on JSFiddle with Script ErrorIndeterminate
U
12

First of all, there are a lot of color blind people out there. Here is a nice article about charts and color blindness: Finding the Right Color Palettes for Data Visualizations

This uses Chart.js 2.4.0

I'm calculating the different colors from a gradient like this:

enter image description here

This gives a nice cohesive look. I have borrowed the palettes from the link above. I have only tested with doughnut, bar and line charts, but it should be easy enough to add other types. You can also easily make your own gradients.

You can find a jsfiddle here.

HTML:

<div>
    <button onclick="doughnut();">Doughnut</button>
    <button onclick="lineBar('bar')">Bar</button>
    <button onclick="lineBar('line')">Line</button>
</div>
<div>
    <button onclick="chartColors('cool');">Cool</button>
    <button onclick="chartColors('warm')">Warm</button>
    <button onclick="chartColors('neon')">Neon</button>
</div>
<hr />
<canvas id="canvas"></canvas>
<hr />
Palettes borrowed from:<br />
<a href="https://blog.graphiq.com/finding-the-right-color-palettes-for-data-visualizations-fcd4e707a283">
    Finding the Right Color Palettes for Data Visualizations
</a>

Javascript:

var ctx = document.getElementById('canvas').getContext('2d');
var chart;
var currentPalette = "cool";

function doughnut() {
    if (chart) chart.destroy();
    chart = new Chart(ctx, {
        type: 'doughnut',
        data: {
            labels: ["Bananas", "Street lights", "Emotions", "Colors", "Children", "Nodes"],
            datasets: [{
                data: [1, 2, 6, 9, 1, 2],
            }]
        },
    });
    chartColors();
}

function lineBar(type) {
    if (chart) chart.destroy();
    chart = new Chart(ctx, {
        type: type,
        data: {
            labels: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
            datasets: [{
                label: "Bananas",
                data: [1, 2, 6, 9, 1, 2]
            }, {
                label: "Street lights",
                data: [2, 6, 9, 1, 2, 7]
            }, {
                label: "Emotions",
                data: [2, 4, 6, 8, 6, 4]
            }, {
                label: "Colors",
                data: [3, 6, 3, 1, 3, 1]
            }, {
                label: "Children",
                data: [4, 4, 4, 5, 5, 5]
            }, {
                label: "Nodes",
                data: [5, 1, 2, 3, 4, 5]
            }, ]
        },
    });
    chartColors();
}

function chartColors(palette) {
    if (!palette) palette = currentPalette;
    currentPalette = palette;

    /*Gradients
      The keys are percentage and the values are the color in a rgba format.
      You can have as many "color stops" (%) as you like.
      0% and 100% is not optional.*/
    var gradient;
    switch (palette) {
        case 'cool':
            gradient = {
                0: [255, 255, 255, 1],
                20: [220, 237, 200, 1],
                45: [66, 179, 213, 1],
                65: [26, 39, 62, 1],
                100: [0, 0, 0, 1]
            };
            break;
        case 'warm':
            gradient = {
                0: [255, 255, 255, 1],
                20: [254, 235, 101, 1],
                45: [228, 82, 27, 1],
                65: [77, 52, 47, 1],
                100: [0, 0, 0, 1]
            };
            break;
        case 'neon':
            gradient = {
                0: [255, 255, 255, 1],
                20: [255, 236, 179, 1],
                45: [232, 82, 133, 1],
                65: [106, 27, 154, 1],
                100: [0, 0, 0, 1]
            };
            break;
    }

    //Get a sorted array of the gradient keys
    var gradientKeys = Object.keys(gradient);
    gradientKeys.sort(function(a, b) {
        return +a - +b;
    });

    //Find datasets and length
    var chartType = chart.config.type;
    switch (chartType) {
        case "pie":
        case "doughnut":
            var datasets = chart.config.data.datasets[0];
            var setsCount = datasets.data.length;
            break;
        case "bar":
        case "line":
            var datasets = chart.config.data.datasets;
            var setsCount = datasets.length;
            break;
    }

    //Calculate colors
    var chartColors = [];
    for (i = 0; i < setsCount; i++) {
        var gradientIndex = (i + 1) * (100 / (setsCount + 1)); //Find where to get a color from the gradient
        for (j = 0; j < gradientKeys.length; j++) {
            var gradientKey = gradientKeys[j];
            if (gradientIndex === +gradientKey) { //Exact match with a gradient key - just get that color
                chartColors[i] = 'rgba(' + gradient[gradientKey].toString() + ')';
                break;
            } else if (gradientIndex < +gradientKey) { //It's somewhere between this gradient key and the previous
                var prevKey = gradientKeys[j - 1];
                var gradientPartIndex = (gradientIndex - prevKey) / (gradientKey - prevKey); //Calculate where
                var color = [];
                for (k = 0; k < 4; k++) { //Loop through Red, Green, Blue and Alpha and calculate the correct color and opacity
                    color[k] = gradient[prevKey][k] - ((gradient[prevKey][k] - gradient[gradientKey][k]) * gradientPartIndex);
                    if (k < 3) color[k] = Math.round(color[k]);
                }
                chartColors[i] = 'rgba(' + color.toString() + ')';
                break;
            }
        }
    }

    //Copy colors to the chart
    for (i = 0; i < setsCount; i++) {
        switch (chartType) {
            case "pie":
            case "doughnut":
                if (!datasets.backgroundColor) datasets.backgroundColor = [];
                datasets.backgroundColor[i] = chartColors[i];
                if (!datasets.borderColor) datasets.borderColor = [];
                datasets.borderColor[i] = "rgba(255,255,255,1)";
                break;
            case "bar":
                datasets[i].backgroundColor = chartColors[i];
                datasets[i].borderColor = "rgba(255,255,255,0)";
                break;
            case "line":
                datasets[i].borderColor = chartColors[i];
                datasets[i].backgroundColor = "rgba(255,255,255,0)";
                break;
        }
    }

    //Update the chart to show the new colors
    chart.update();
}

doughnut();

This would give something like this:

enter image description here

Ufo answered 2/2, 2018 at 19:22 Comment(0)
L
9

You could loop thought your pieData array and set random values for the color value.

You can set this one with a value like "rgb(230,0,0)" and generate the red green blue integer values randomly.

Something like this :

r = Math.floor(Math.random() * 200);
g = Math.floor(Math.random() * 200);
b = Math.floor(Math.random() * 200);
color = 'rgb(' + r + ', ' + g + ', ' + b + ')';

See an example jsfiddle here, with random values and random colors. (Run it several times to get an idea of how it displays with different data sets.)

Or else you could define an array of predefined colors and just use that. Consider that a pie chart with more than 50 items is not very readeable. So a default list of 50 might just be ok.

Labyrinthine answered 4/3, 2015 at 17:19 Comment(3)
Hey sorry, I followed your jsfiddle code but it does not work. The chart is showing nothing and no error message. Do you have any idea why is it so?Hagiology
Hi Denise. I was calling chart.js from a cdn that no longer exists. It's fixed now. Give it a try, I've updated the link.Labyrinthine
You can also multiply to 255 instead of 200 as each RGB value ranges from 0 to 255.Chadwell
C
6

Don't waste your time creating a random generator. Instead, pick a few bright pretty colors to loop through.

This function takes any size and builds an array of background colors using the pallet array.

function getColors(length) {
    let pallet = ["#0074D9", "#FF4136", "#2ECC40", "#FF851B", "#7FDBFF", "#B10DC9", "#FFDC00", "#001f3f", "#39CCCC", "#01FF70", "#85144b", "#F012BE", "#3D9970", "#111111", "#AAAAAA"];
    let colors = [];

    for (let i = 0; i < length; i++) {
        colors.push(pallet[i % (pallet.length - 1)]);
    }

    return colors;
}

console.log(getColors(10));

You can then set your background colors by calling this function, passing the size of your data as a parameter.

datasets:
[
  {
    data: data,
    backgroundColor: getColors(data.length)
  }
]

This way your colors are always pretty and every data element is assigned a value.

Chadwell answered 24/4, 2020 at 4:24 Comment(2)
What if the elements for the pie chart are more than the colors specified here?Slovene
@KaranBhalla The colors will go back to the beginning. This is because I use the modulus symbol. 23 % 24 == 23 but 24 % 24 == 0, creating a repeating color scheme. Personally, I find this method of displaying colors looks much prettier, as you can select what colors you'd like to display.Chadwell

© 2022 - 2024 — McMap. All rights reserved.