121

I'm using ChartJS in a project I'm working on and I need a different color for each bar in a Bar Chart.

Here's an example of the bar chart data set:

    var barChartData = {
      labels: ["001", "002", "003", "004", "005", "006", "007"],
      datasets: [{
        label: "My First dataset",
        fillColor: "rgba(220,220,220,0.5)", 
        strokeColor: "rgba(220,220,220,0.8)", 
        highlightFill: "rgba(220,220,220,0.75)",
        highlightStroke: "rgba(220,220,220,1)",
        data: [20, 59, 80, 81, 56, 55, 40]
      }]
    };

Is there any way to paint each bar differently?

some-user
  • 3,888
  • 5
  • 19
  • 43
BoooYaKa
  • 2,051
  • 2
  • 16
  • 17
  • 3
    To save you some scrolling, [this answer](https://stackoverflow.com/a/29508005/625840) mentions that you can set the `fillColor` of a dataset to be an array, and chart.js will iterate through the array picking the next color for each bar drawn. – Hartley Brody Mar 20 '18 at 22:36

21 Answers21

105

As of v2, you can simply specify an array of values to correspond to a color for each bar via the backgroundColor property:

datasets: [{
  label: "My First dataset",
  data: [20, 59, 80, 81, 56, 55, 40],
  backgroundColor: ["red", "blue", "green", "blue", "red", "blue"], 
}],

This is also possible for the borderColor, hoverBackgroundColor, hoverBorderColor.

From the documentation on the Bar Chart Dataset Properties:

Some properties can be specified as an array. If these are set to an array value, the first value applies to the first bar, the second value to the second bar, and so on.

thanksd
  • 54,176
  • 22
  • 157
  • 150
69

Solution: call the update method to set new values ​​:

var barChartData = {
    labels: ["January", "February", "March"],
    datasets: [
        {
            label: "My First dataset",
            fillColor: "rgba(220,220,220,0.5)", 
            strokeColor: "rgba(220,220,220,0.8)", 
            highlightFill: "rgba(220,220,220,0.75)",
            highlightStroke: "rgba(220,220,220,1)",
            data: [20, 59, 80]
        }
    ]
};

window.onload = function(){
    var ctx = document.getElementById("mycanvas").getContext("2d");
    window.myObjBar = new Chart(ctx).Bar(barChartData, {
          responsive : true
    });

    //nuevos colores
    myObjBar.datasets[0].bars[0].fillColor = "green"; //bar 1
    myObjBar.datasets[0].bars[1].fillColor = "orange"; //bar 2
    myObjBar.datasets[0].bars[2].fillColor = "red"; //bar 3
    myObjBar.update();
}
Joshua Walsh
  • 1,915
  • 5
  • 25
  • 50
Jerry
  • 691
  • 1
  • 4
  • 2
  • 1
    This code won't work in its current form as myObjBar is defined in window.onload but it's used in the main script flow, so myObjBar won't be defined by the time we try to change the colours. However I moved the colour changing code at the bottom into the same scope as where my bar chart is generated and this works perfectly! I really didn't want to have to modify chart.js to get something so simple to work, so I'm very happy with this method. EDIT: I've submitted an edit to the answer to apply my fix, just need to wait for it to be approved. – Joshua Walsh Oct 28 '14 at 22:54
  • Unfortunately, this doesn't seem to work in Firefox, or IE 10 or 11. Here's a JSFiddle: http://jsfiddle.net/3fefqLko/1/. Any thoughts on how to make it work across browsers? – Sam Fen Feb 11 '15 at 02:44
  • Correction: it does work across browsers. It's just that you can do `fillColor = "#FFFFFF;"` in Chrome, but the final semi-colon shouldn't be there and FF and IE won't accept it. – Sam Fen Feb 11 '15 at 14:29
  • This is the best answer by far. It actually solves the problem without hacking core. I'm still pretty upset that this is the answer, but, it worked. – sic1 Feb 18 '15 at 22:29
  • 5
    Update: you'll need to assign "._saved.fillColor" as well as ".fillColor" - it uses the _saved value to restore after mouseover (highlight) - e.g. it restores the ORIGINAL color if you don't assign the new one to it –  Mar 22 '15 at 22:18
  • 5
    UPDATE : this is not working with latest version (2.0 +), but working with 1.0.2 – Madan Bhandari Jun 01 '16 at 09:19
68

After looking into the Chart.Bar.js file I've managed to find the solution. I've used this function to generate a random color:

function getRandomColor() {
    var letters = '0123456789ABCDEF'.split('');
    var color = '#';
    for (var i = 0; i < 6; i++ ) {
        color += letters[Math.floor(Math.random() * 16)];
    }
    return color;
}

I've added it to the end of the file and i called this function right inside the "fillColor:" under

helpers.each(dataset.data,function(dataPoint,index){
                    //Add a new point for each piece of data, passing any required data to draw.

so now it looks like this:

helpers.each(dataset.data,function(dataPoint,index){
                    //Add a new point for each piece of data, passing any required data to draw.

                    datasetObject.bars.push(new this.BarClass({
                        value : dataPoint,
                        label : data.labels[index],
                        datasetLabel: dataset.label,
                        strokeColor : dataset.strokeColor,
                        fillColor : getRandomColor(),
                        highlightFill : dataset.highlightFill || dataset.fillColor,
                        highlightStroke : dataset.highlightStroke || dataset.strokeColor
                    }));
                },this);

and it works I get different color for each bar.

BenMorel
  • 34,448
  • 50
  • 182
  • 322
BoooYaKa
  • 2,051
  • 2
  • 16
  • 17
  • 2
    Could you post your full solution (e.g. with data and dataset variables, etc.)? I'm looking to do something similar, and I can't seem to replicate your solution. Thanks – kck Sep 09 '14 at 17:15
  • hey @casey, this is the full Chart.Bar.js file (the one you need to replace). http://pastebin.com/G2Rf0BBn, Ive highlighted the line that makes the diffrence. note that at the buttom theres a function that returns diffrent color from an array according to the index "i". the dataset remains the same (like the one in the question). I hope it helped you. – BoooYaKa Sep 10 '14 at 18:18
  • That definitely helps, thank you! I didn't realize you were modifying the actual Chart.js file, rather than your own code. – kck Sep 12 '14 at 02:32
  • This is a great solution and not unique to ChartJS. – crooksey Oct 11 '18 at 07:52
26

If you take a look at the library "ChartNew" which builds upon Chart.js you can do this by passing the values in as an array like so:

var data = {
    labels: ["Batman", "Iron Man", "Captain America", "Robin"],
    datasets: [
        {
            label: "My First dataset",
            fillColor: ["rgba(220,220,220,0.5)", "navy", "red", "orange"],
            strokeColor: "rgba(220,220,220,0.8)",
            highlightFill: "rgba(220,220,220,0.75)",
            highlightStroke: "rgba(220,220,220,1)",
            data: [2000, 1500, 1750, 50]
        }
    ]
};
msp
  • 3,272
  • 7
  • 37
  • 49
25

You can call this function which generates random colors for each bars

var randomColorGenerator = function () { 
    return '#' + (Math.random().toString(16) + '0000000').slice(2, 8); 
};

var barChartData = {
        labels: ["001", "002", "003", "004", "005", "006", "007"],
        datasets: [
            {
                label: "My First dataset",
                fillColor: randomColorGenerator(), 
                strokeColor: randomColorGenerator(), 
                highlightFill: randomColorGenerator(),
                highlightStroke: randomColorGenerator(),
                data: [20, 59, 80, 81, 56, 55, 40]
            }
        ]
    };
Sudharshan
  • 3,634
  • 2
  • 27
  • 27
  • 2
    hey @Sudharshan thanks for the answer, this will result a diffrent color for each chart but not for each single bar inside the bar chart, which is my desired result. got any idea? – BoooYaKa Sep 06 '14 at 10:05
  • 1
    Thanks for this code. I was able to use it to change the color of the bars themselves. The backgroundColor option allows for this. – spyke01 Jun 16 '16 at 17:01
  • 1
    In version 2.8, you can set backgroundColor with a function `backgroundColor: randomColorGenerator,`, instead the result of a function `backgroundColor: randomColorGenerator(),`. The function is called for each item instead of one time for all. – negas Jul 17 '19 at 15:26
20

Here, I solved this issue by making two functions.

1. dynamicColors() to generate random color

function dynamicColors() {
    var r = Math.floor(Math.random() * 255);
    var g = Math.floor(Math.random() * 255);
    var b = Math.floor(Math.random() * 255);
    return "rgba(" + r + "," + g + "," + b + ", 0.5)";
}

2. poolColors() to create array of colors

function poolColors(a) {
    var pool = [];
    for(i = 0; i < a; i++) {
        pool.push(dynamicColors());
    }
    return pool;
}

Then, just pass it

datasets: [{
    data: arrData,
    backgroundColor: poolColors(arrData.length),
    borderColor: poolColors(arrData.length),
    borderWidth: 1
}]
Martin Schneider
  • 14,263
  • 7
  • 55
  • 58
Abdul Hameed
  • 1,025
  • 13
  • 17
20

As of August 2019, Chart.js now has this functionality built in.

Successful bar chart with different colored bars

You simply need to provide an array to backgroundColor.

Example taken from https://www.chartjs.org/docs/latest/getting-started/

Before:

  data: {
        labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
        datasets: [{
            label: 'My First dataset',
            backgroundColor: 'rgb(255, 99, 132)',
            borderColor: 'rgb(255, 99, 132)',
            data: [0, 10, 5, 2, 20, 30, 45]
        }]
    },

After:

  data: {
        labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
        datasets: [{
            label: 'My First dataset',
            backgroundColor: ['rgb(255, 99, 132)','rgb(0, 255, 0)','rgb(255, 99, 132)','rgb(128, 255, 0)','rgb(0, 255, 255)','rgb(255, 255, 0)','rgb(255, 255, 128)'],
            borderColor: 'rgb(255, 99, 132)',
            data: [0, 10, 5, 2, 20, 30, 45]
        }]
    },

I just tested this method and it works. Each bar has a different color.

legoblocks
  • 525
  • 1
  • 6
  • 16
11

Generate random colors;

function getRandomColor() {
    var letters = '0123456789ABCDEF'.split('');
    var color = '#';
    for (var i = 0; i < 6; i++) {
        color += letters[Math.floor(Math.random() * 16)];
    }
    return color;
}

and call it for each record;

function getRandomColorEachEmployee(count) {
    var data =[];
    for (var i = 0; i < count; i++) {
        data.push(getRandomColor());
    }
    return data;
}

finally set colors;

var data = {
    labels: jsonData.employees, // your labels
    datasets: [{
        data: jsonData.approvedRatios, // your data
        backgroundColor: getRandomColorEachEmployee(jsonData.employees.length)
    }]
};
Martin Schneider
  • 14,263
  • 7
  • 55
  • 58
9

Here's a way to generate consistent random colors using color-hash

const colorHash = new ColorHash()

const datasets = [{
  label: 'Balance',
  data: _.values(balances),
  backgroundColor: _.keys(balances).map(name => colorHash.hex(name))
}]

enter image description here

TeNNoX
  • 1,899
  • 3
  • 16
  • 27
3

here is how I dealed: I pushed an array "colors", with same number of entries than number of datas. For this I added a function "getRandomColor" at the end of the script. Hope it helps...

for (var i in arr) {
    customers.push(arr[i].customer);
    nb_cases.push(arr[i].nb_cases);
    colors.push(getRandomColor());
}

window.onload = function() {
    var config = {
        type: 'pie',
        data: {
            labels: customers,
            datasets: [{
                label: "Nomber of cases by customers",
                data: nb_cases,
                fill: true,
                backgroundColor: colors 
            }]
        },
        options: {
            responsive: true,
            title: {
                display: true,
                text: "Cases by customers"
            },
        }
    };

    var ctx = document.getElementById("canvas").getContext("2d");
    window.myLine = new Chart(ctx, config);
};

function getRandomColor() {
    var letters = '0123456789ABCDEF'.split('');
    var color = '#';
    for (var i = 0; i < 6; i++) {
        color += letters[Math.floor(Math.random() * 16)];
    }
    return color;
}
Martin Schneider
  • 14,263
  • 7
  • 55
  • 58
2

If you're not able to use NewChart.js you just need to change the way to set the color using array instead. Find the helper iteration inside Chart.js:

Replace this line:

fillColor : dataset.fillColor,

For this one:

fillColor : dataset.fillColor[index],

The resulting code:

//Iterate through each of the datasets, and build this into a property of the chart
  helpers.each(data.datasets,function(dataset,datasetIndex){

    var datasetObject = {
      label : dataset.label || null,
      fillColor : dataset.fillColor,
      strokeColor : dataset.strokeColor,
      bars : []
    };

    this.datasets.push(datasetObject);

    helpers.each(dataset.data,function(dataPoint,index){
      //Add a new point for each piece of data, passing any required data to draw.
      datasetObject.bars.push(new this.BarClass({
        value : dataPoint,
        label : data.labels[index],
        datasetLabel: dataset.label,
        strokeColor : dataset.strokeColor,
        //Replace this -> fillColor : dataset.fillColor,
        // Whith the following:
        fillColor : dataset.fillColor[index],
        highlightFill : dataset.highlightFill || dataset.fillColor,
        highlightStroke : dataset.highlightStroke || dataset.strokeColor
      }));
    },this);

  },this);

And in your js:

datasets: [
                {
                  label: "My First dataset",
                  fillColor: ["rgba(205,64,64,0.5)", "rgba(220,220,220,0.5)", "rgba(24,178,235,0.5)", "rgba(220,220,220,0.5)"],
                  strokeColor: "rgba(220,220,220,0.8)",
                  highlightFill: "rgba(220,220,220,0.75)",
                  highlightStroke: "rgba(220,220,220,1)",
                  data: [2000, 1500, 1750, 50]
                }
              ]
2

Code based on the following pull request:

datapoint.color = 'hsl(' + (360 * index / data.length) + ', 100%, 50%)';
voho
  • 2,805
  • 1
  • 21
  • 26
  • Very useful idea - much more so than just choosing random colours. To improve this further, when there is a large number of bars you can adjust the saturation value too, so that instead of just circling round on the colour wheel, you spiral in on it. – Martin CR Dec 07 '19 at 20:38
  • Great solution indeed, generates consistent colors. – LachoTomov Oct 21 '22 at 14:10
1

try this :

  function getChartJs() {
        **var dynamicColors = function () {
            var r = Math.floor(Math.random() * 255);
            var g = Math.floor(Math.random() * 255);
            var b = Math.floor(Math.random() * 255);
            return "rgb(" + r + "," + g + "," + b + ")";
        }**

        $.ajax({
            type: "POST",
            url: "ADMIN_DEFAULT.aspx/GetChartByJenisKerusakan",
            data: "{}",
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            success: function (r) {
                var labels = r.d[0];
                var series1 = r.d[1];
                var data = {
                    labels: r.d[0],
                    datasets: [
                        {
                            label: "My First dataset",
                            data: series1,
                            strokeColor: "#77a8a8",
                            pointColor: "#eca1a6"
                        }
                    ]
                };

                var ctx = $("#bar_chart").get(0).getContext('2d');
                ctx.canvas.height = 300;
                ctx.canvas.width = 500;
                var lineChart = new Chart(ctx).Bar(data, {
                    bezierCurve: false,
                    title:
                      {
                          display: true,
                          text: "ProductWise Sales Count"
                      },
                    responsive: true,
                    maintainAspectRatio: true
                });

                $.each(r.d, function (key, value) {
                    **lineChart.datasets[0].bars[key].fillColor = dynamicColors();
                    lineChart.datasets[0].bars[key].fillColor = dynamicColors();**
                    lineChart.update();
                });
            },
            failure: function (r) {
                alert(r.d);
            },
            error: function (r) {
                alert(r.d);
            }
        });
    }
FannyKaunang
  • 91
  • 1
  • 8
1

This works for me in the current version 2.7.1:

function colorizePercentageChart(myObjBar) {

var bars = myObjBar.data.datasets[0].data;
console.log(myObjBar.data.datasets[0]);
for (i = 0; i < bars.length; i++) {

    var color = "green";

    if(parseFloat(bars[i])  < 95){
        color = "yellow";
    }
    if(parseFloat(bars[i])  < 50){
         color = "red";
    }

    console.log(color);
    myObjBar.data.datasets[0].backgroundColor[i] = color;

}
myObjBar.update(); 

}

Damian
  • 2,930
  • 6
  • 39
  • 61
1

Taking the other answer, here is a quick fix if you want to get a list with random colors for each bar:

function getRandomColor(n) {
    var letters = '0123456789ABCDEF'.split('');
    var color = '#';
    var colors = [];
    for(var j = 0; j < n; j++){
        for (var i = 0; i < 6; i++ ) {
            color += letters[Math.floor(Math.random() * 16)];
        }
        colors.push(color);
        color = '#';
    }
    return colors;
}

Now you could use this function in the backgroundColor field in data:

data: {
        labels: count[0],
        datasets: [{
            label: 'Registros en BDs',
            data: count[1],
            backgroundColor: getRandomColor(count[1].length)
        }]
}
vimuth
  • 5,064
  • 33
  • 79
  • 116
  • 1
    This answer needs work. it leads to problems for me. I had to rewrite it as `function getRandomColor(n) { var letters = '0123456789ABCDEF'.split(''); var color = '#'; for (var i = 0; i < 6; i++) { color += letters[Math.floor(Math.random() * 16)]; } return color; }`. – SedJ601 Oct 31 '19 at 15:02
1

If you know which colors you want, you can specify color properties in an array, like so:

    backgroundColor: [
    'rgba(75, 192, 192, 1)',
    ...
    ],
    borderColor: [
    'rgba(75, 192, 192, 1)',
    ...
    ],
frostbyyte
  • 139
  • 1
  • 4
  • 9
1

Following this answer: https://stackoverflow.com/a/48067347/931409, this is what I came up with to generate consistent colors, that don't change with each refresh:

const generateColorHue = (colorI: number, totalColors: number) => {
    const step = 360 / totalColors;
    const hue = Math.round(colorI * step);

    return hue;
};

// ...
datasets: this.platforms.map((platform, i) => {
    const hue = generateColorHue(i, this.platforms.length);
    return {
        label: platform,
        borderColor: "hsl(" + hue + ", 50%, 40%)",
        backgroundColor: "hsla(" + hue + ", 50%, 90%, .2)",
    };
}),
LachoTomov
  • 3,312
  • 30
  • 42
0

I have just got this issue recently, and here is my solution

var labels = ["001", "002", "003", "004", "005", "006", "007"];
var data = [20, 59, 80, 81, 56, 55, 40];
for (var i = 0, len = labels.length; i < len; i++) {
   background_colors.push(getRandomColor());// I use @Benjamin method here
}

var barChartData = {
  labels: labels,
  datasets: [{
    label: "My First dataset",
    fillColor: "rgba(220,220,220,0.5)", 
    strokeColor: "rgba(220,220,220,0.8)", 
    highlightFill: "rgba(220,220,220,0.75)",
    highlightStroke: "rgba(220,220,220,1)",
    backgroundColor: background_colors,
    data: data
  }]
};
0

what I've done is create a random color generator as many here have suggested

function dynamicColors() {
        var r = Math.floor(Math.random() * 255);
        var g = Math.floor(Math.random() * 255);
        var b = Math.floor(Math.random() * 255);
        return "rgba(" + r + "," + g + "," + b + ", 0.5)";
    }

and then coded this

var chartContext = document.getElementById('line-chart');
    let lineChart = new Chart(chartContext, {
        type: 'bar',
        data : {
            labels: <?php echo json_encode($names); ?>,
            datasets: [{
                data : <?php echo json_encode($salaries); ?>,
                borderWidth: 1,
                backgroundColor: dynamicColors,
            }]
        }
        ,
        options: {
            scales: {
                yAxes: [{
                    ticks: {
                        beginAtZero: true
                    }
                }]
            },
            responsive: true,
            maintainAspectRatio: false,
        }
    });

Notice there is no parantheses at the function call This enables the code to call the function every time, instead of making an array This also prevents the code from using the same color for all the bars

Kapil
  • 165
  • 1
  • 9
  • I _assume_ that the downvote came from use of dynamic colors in answer while original question has hardcoded colors implying we want manual control over displayed colors – Alexander Kucheryuk Aug 26 '21 at 19:43
0

Pass a color parameter in dataPoints like below for each bar:

{y: your value, label: your value, color: your color code}

enter image description here

Raduan Santos
  • 1,023
  • 1
  • 21
  • 45
0

enter image description here

function getRandomColor() {

        const colors = [];
        var obj = @json($year);
        const length = Object.keys(obj).length;
        for(let j=0; j<length; j++ )
        {
            const letters = '0123456789ABCDEF'.split('');
            let color = '#';
            for (let i = 0; i < 6; i++ ) {
                color += letters[Math.floor(Math.random() * 16)];
            }
            colors.push(color);
        }
        return colors;
    }

use this function for different colors

Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
  • it is use for different colos in bar and pie chart JS – user8958855 Dec 17 '21 at 05:52
  • You can [edit] your answer instead of adding in comments. The link is right below your post next to share. – Suraj Rao Dec 17 '21 at 05:54
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Dec 17 '21 at 06:01