Cor diferente para cada barra em um gráfico de barras; ChartJS

94

Estou usando o ChartJS em um projeto no qual estou trabalhando e preciso de uma cor diferente para cada barra em um gráfico de barras.

Aqui está um exemplo do conjunto de dados do gráfico de barras:

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]
  }]
};

Existe alguma maneira de pintar cada barra de forma diferente?

BoooYaKa
fonte
3
Para economizar um pouco de rolagem, esta resposta menciona que você pode definir o fillColorde um conjunto de dados como um array, e chart.js iterará através do array escolhendo a próxima cor para cada barra desenhada.
Hartley Brody de

Respostas:

74

A partir da v2, você pode simplesmente especificar uma matriz de valores para corresponder a uma cor para cada barra por meio da backgroundColorpropriedade:

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

Isto também é possível para a borderColor, hoverBackgroundColor, hoverBorderColor.

A partir da documentação sobre as propriedades do conjunto de dados do gráfico de barras :

Algumas propriedades podem ser especificadas como uma matriz. Se eles forem configurados para um valor de matriz, o primeiro valor se aplica à primeira barra, o segundo valor à segunda barra e assim por diante.

obrigado
fonte
66

Solução: chame o método de atualização para definir novos valores:

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();
}
Jerry
fonte
1
Este código não funcionará em sua forma atual, pois myObjBar está definido em window.onload, mas é usado no fluxo do script principal, portanto, myObjBar não será definido no momento em que tentarmos alterar as cores. No entanto, movi o código de mudança de cor na parte inferior para o mesmo escopo de onde meu gráfico de barras é gerado e isso funciona perfeitamente! Eu realmente não queria ter que modificar chart.js para fazer algo tão simples funcionar, então estou muito feliz com esse método. EDITAR: Enviei uma edição à resposta para aplicar minha correção, só preciso aguardar sua aprovação.
Joshua Walsh
Infelizmente, isso não parece funcionar no Firefox, ou IE 10 ou 11. Aqui está um JSFiddle: jsfiddle.net/3fefqLko/1 . Alguma ideia de como fazê-lo funcionar em todos os navegadores?
Sam Fen
Correção: funciona em vários navegadores. É só isso que você pode fazer fillColor = "#FFFFFF;"no Chrome, mas o ponto-e-vírgula final não deveria estar lá e o FF e o IE não o aceitarão.
Sam Fen
5
Atualizar: você precisará atribuir "._saved.fillColor" assim como ".fillColor" - usa o valor _saved para restaurar após mouseover (destaque) - por exemplo, restaura a cor ORIGINAL se você não atribuir a nova para ele
4
ATUALIZAÇÃO: isso não está funcionando com a versão mais recente (2.0 +), mas funcionando com 1.0.2
Madan Bhandari
52

Depois de examinar o arquivo Chart.Bar.js, consegui encontrar a solução. Usei esta função para gerar uma cor aleatória:

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

Eu o adicionei ao final do arquivo e chamei esta função dentro de "fillColor:" em

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

então agora se parece com isto:

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);

e funciona, eu obtenho cores diferentes para cada barra.

BoooYaKa
fonte
1
Você poderia postar sua solução completa (por exemplo, com dados e variáveis ​​de conjunto de dados, etc.)? Estou tentando fazer algo semelhante e não consigo replicar sua solução. Obrigado
caseklim
Ei @casey, este é o arquivo Chart.Bar.js completo (aquele que você precisa substituir). pastebin.com/G2Rf0BBn , Ive destaque a linha que faz a diferença. observe que no botão há uma função que retorna cores diferentes de uma matriz de acordo com o índice "i". o conjunto de dados permanece o mesmo (como o da pergunta). Espero que tenha ajudado.
BoooYaKa
Isso definitivamente ajuda, obrigado! Não percebi que você estava modificando o arquivo Chart.js real, em vez de seu próprio código.
caseklim
Esta é uma ótima solução e não é exclusiva do ChartJS.
crooksey,
24

Se você der uma olhada na biblioteca " ChartNew ", que se baseia em Chart.js, você pode fazer isso passando os valores como uma matriz assim:

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]
        }
    ]
};
Muhammad Mohsin Muneer
fonte
sua solução simples funcionou para mim, obrigado e chartNew.js funciona perfeitamente bem para mim
Pratswinz
como podemos mudar a cor ingraphdatashow em chartnew js ??
Pratswinz
Espero que isto ajude! github.com/FVANCOP/ChartNew.js/wiki/100_080_In_Graph_Data
Muhammad Mohsin Muneer
Muito obrigado! Não sabia que fillColor aceitava um array.
Francisco Quintero
18

Você pode chamar esta função que gera cores aleatórias para cada barra

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
fonte
2
hey @Sudharshan obrigado pela resposta, isso resultará em uma cor diferente para cada gráfico, mas não para cada barra individual dentro do gráfico de barras, que é o resultado desejado. tem alguma ideia?
BoooYaKa
1
Obrigado por este código. Consegui usá-lo para mudar a cor das próprias barras. A opção backgroundColor permite isso.
spyke01
Na versão 2.8, você pode definir backgroundColor com uma função backgroundColor: randomColorGenerator,, em vez do resultado de uma função backgroundColor: randomColorGenerator(),. A função é chamada para cada item em vez de uma vez para todos.
negas
14

Desde agosto de 2019, Chart.js agora tem essa funcionalidade integrada.

Gráfico de barras de sucesso com barras coloridas diferentes

Você simplesmente precisa fornecer uma matriz para backgroundColor.

Exemplo retirado de https://www.chartjs.org/docs/latest/getting-started/

Antes:

  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]
        }]
    },

Depois de:

  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]
        }]
    },

Acabei de testar esse método e funciona. Cada barra possui uma cor diferente.

legoblocks
fonte
13

Aqui, resolvi esse problema criando duas funções.

1. dynamicColors () para gerar cores aleatórias

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 () para criar matriz de cores

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

Então, é só passar

datasets: [{
    data: arrData,
    backgroundColor: poolColors(arrData.length),
    borderColor: poolColors(arrData.length),
    borderWidth: 1
}]
Abdul Hameed
fonte
10

Gere cores aleatórias;

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

e chamá-lo para cada registro;

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

finalmente defina as cores;

var data = {
    labels: jsonData.employees, // your labels
    datasets: [{
        data: jsonData.approvedRatios, // your data
        backgroundColor: getRandomColorEachEmployee(jsonData.employees.length)
    }]
};
Martin Schneider
fonte
4

Esta é uma maneira de gerar cores aleatórias consistentes usando color-hash

const colorHash = new ColorHash()

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

insira a descrição da imagem aqui

TeNNoX
fonte
3

aqui está como eu lidei: eu empurrei uma matriz "cores", com o mesmo número de entradas do que número de dados. Para isso, adicionei uma função "getRandomColor" no final do script. Espero que ajude...

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;
}
Jean-François Rullier
fonte
2

Se você não puder usar NewChart.js, você só precisa alterar a forma de definir a cor usando array. Encontre a iteração auxiliar dentro de Chart.js:

Substitua esta linha:

fillColor : dataset.fillColor,

Para este:

fillColor : dataset.fillColor[index],

O código resultante:

//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);

E em seu 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]
                }
              ]
Armando Reyna
fonte
Criei uma subclasse personalizada do código do gráfico de barras e adicionei um código semelhante ao inicializador para fazer isso.
David Reynolds
1

tente isto:

  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
fonte
1

Isso funciona para mim na versão atual 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
fonte
1

Tomando a outra resposta, aqui está uma solução rápida se você deseja obter uma lista com cores aleatórias para cada barra:

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;
}

Agora você pode usar esta função no campo backgroundColor nos dados:

data: {
        labels: count[0],
        datasets: [{
            label: 'Registros en BDs',
            data: count[1],
            backgroundColor: getRandomColor(count[1].length)
        }]
}
Eduardo luis santos
fonte
1
Essa resposta precisa ser trabalhada. isso me causa problemas. Tive que reescrever como 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; }.
Sedrick,
0

Acabei de pegar esse problema recentemente e aqui está minha solução

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
  }]
};
Feiyu Chen
fonte
0

Código baseado na seguinte solicitação de pull :

datapoint.color = 'hsl(' + (360 * index / data.length) + ', 100%, 50%)';
voho
fonte
Idéia muito útil - muito mais do que apenas escolher cores aleatórias. Para melhorar ainda mais, quando há um grande número de barras, você também pode ajustar o valor de saturação, de modo que, em vez de apenas girar no círculo cromático, você faça uma espiral nele.
Martin CR
0

Se você sabe quais cores deseja, pode especificar as propriedades das cores em uma matriz, como:

    backgroundColor: [
    'rgba(75, 192, 192, 1)',
    ...
    ],
    borderColor: [
    'rgba(75, 192, 192, 1)',
    ...
    ],
frostbyyte
fonte
-1

o que fiz foi criar um gerador de cores aleatório, como muitos aqui sugeriram

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)";
    }

e então codifiquei isso

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,
        }
    });

Observe que não há parênteses na chamada da função Isso permite que o código chame a função todas as vezes, em vez de fazer uma matriz Isso também evita que o código use a mesma cor para todas as barras

Kapil
fonte
-9

Você pode gerar facilmente com gráficos livegap
Selecione Mulicolors no menu Bar


(fonte: livegap.com )

** biblioteca gráfico utilizado é chartnew.js versão de biblioteca chart.js modificados
com código chartnew.js será algo parecido com isto

var barChartData = {
        labels: ["001", "002", "003", "004", "005", "006", "007"],
        datasets: [
            {
                label: "My First dataset",
                fillColor: ["rgba(0,10,220,0.5)","rgba(220,0,10,0.5)","rgba(220,0,0,0.5)","rgba(120,250,120,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]
            }
        ]
    };
Omar Sedki
fonte
3
Comentar "livre-se de sua biblioteca e use esta outra" ignora completamente o ponto da questão.
jlh
chartnew.js é uma versão modificada de chart.js. nessa época, multicor não era compatível com chart.js, mas estava disponível em chartnew.js
Omar Sedki