How to customize color in pie chart of NVD3
Asked Answered
P

7

35

I am trying to use NVD3 http://nvd3.org/livecode/#codemirrorNav a pie chart. But i want to change the default color. How do i change the color. i am not able to do it.

Paradrop answered 24/4, 2013 at 12:4 Comment(1)
What did you try already?Caithness
S
27

To use your own colours you will have to override the existing colours, I prefer not to tinker around with the original code.

So this is what I did.

    var myColors = ["#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd", "#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf"];
    d3.scale.myColors = function() {
        return d3.scale.ordinal().range(myColors);
    };

    nv.addGraph(function() {
      var chart = nv.models.pieChart()
          .x(function(d) { return d.label })
          .y(function(d) { return d.value })
          .showLabels(true).color(d3.scale.myColors().range());

        d3.select("#chart svg")
            .datum(data)
          .transition().duration(1200)
            .call(chart);

      return chart;
    });

All I did was add .color(d3.scale.myColors().range())


UPDATE :

Check answer by Christopher Chiche, for the perfect solution.

.color(['blue', 'green', 'yellow'])

Hope this helps.

Subtle answered 24/4, 2013 at 12:42 Comment(5)
i am using this, but i have a problem, when i change the metrics of the chart and redraw it (with new colors, i have a function that computes colors based on the label), the chart draws wrong colors. when i click to show/hide some values, sometimes are redrawn like they should be, sometimes are redrawn wrong. Do you have some idea why that is so?this happens only on pie charts.Wilkison
I'll try my best to explain this, say for example you have 5 categories at load, the chart takes the first 5 colours of the array. So your clour 1 will always be assigned to the first element of the data. This may not the the best way, but try having an array and map the color against the pies, so you can use the onclick functions on the ledgend and get which elements are active and which are not, its returns an array with the positions, you can use that to filter out what colours you need to be pass when you redraw the chart.Subtle
no no the problem is that i want to do smth else, for example i a set of data with different fields in it for ex. (ip, country, and some more), when i show the ip metric (i have 4 different ips) i group the data, create the colors for the pie and render it. when i change from ip metric to country, i again aggregate the data ( i get 10 different countries) i create the colors for them, and then redraw the pie, at first render its ok, it takes the new colors (these colors have nothing to do with the colors of the ip pie), but when i hide or show parts of the pie, colors from the ip pie are shownWilkison
I don't understand why you are creating a d3.scale instead of just use the original array as the argument for the colors method.Trilemma
@PauloScardine - I agree with you, when I replied to this, I did not have much knowledge, Christopher Chiche has the perfect answer. I have upvoted his answer. Will update mine.Subtle
O
50

If you want to use specific color for pie

chart.color(function(d){
    return d.data.color
});

Then, organize your data as:

[
  {
    key: "Cumulative Return",
    values: [
      { 
        "label": "One",
        "value" : 29.765957771107,
        "color" : "#8c564b"
      } ,
      { 
        "label": "Three",
        "value" : 32.807804682612,
        "color" : "#e377c2"
      } 
    ]
  }
]
Overweening answered 4/10, 2013 at 10:38 Comment(1)
This is the best answer, it utilized d3 functionality and because in my particular case, the color values are stored on a database, so I can't hard code them on my js file like in Christopher's answer.Linalool
S
44

You can add colors by passing an array to the 'color()' option. So just add:

.color(['blue', 'green', 'yellow'])

If you want to use these colors for 3 elements.

Note: if you have more than 3 elements, then some colors will be used multiple times.

Sakai answered 24/4, 2013 at 16:18 Comment(2)
Where do we need to add color();?Uncouple
@Uncouple You need to add color() to chart. So it gives chart.color(['blue','green','red']).Sakai
S
27

To use your own colours you will have to override the existing colours, I prefer not to tinker around with the original code.

So this is what I did.

    var myColors = ["#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd", "#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf"];
    d3.scale.myColors = function() {
        return d3.scale.ordinal().range(myColors);
    };

    nv.addGraph(function() {
      var chart = nv.models.pieChart()
          .x(function(d) { return d.label })
          .y(function(d) { return d.value })
          .showLabels(true).color(d3.scale.myColors().range());

        d3.select("#chart svg")
            .datum(data)
          .transition().duration(1200)
            .call(chart);

      return chart;
    });

All I did was add .color(d3.scale.myColors().range())


UPDATE :

Check answer by Christopher Chiche, for the perfect solution.

.color(['blue', 'green', 'yellow'])

Hope this helps.

Subtle answered 24/4, 2013 at 12:42 Comment(5)
i am using this, but i have a problem, when i change the metrics of the chart and redraw it (with new colors, i have a function that computes colors based on the label), the chart draws wrong colors. when i click to show/hide some values, sometimes are redrawn like they should be, sometimes are redrawn wrong. Do you have some idea why that is so?this happens only on pie charts.Wilkison
I'll try my best to explain this, say for example you have 5 categories at load, the chart takes the first 5 colours of the array. So your clour 1 will always be assigned to the first element of the data. This may not the the best way, but try having an array and map the color against the pies, so you can use the onclick functions on the ledgend and get which elements are active and which are not, its returns an array with the positions, you can use that to filter out what colours you need to be pass when you redraw the chart.Subtle
no no the problem is that i want to do smth else, for example i a set of data with different fields in it for ex. (ip, country, and some more), when i show the ip metric (i have 4 different ips) i group the data, create the colors for the pie and render it. when i change from ip metric to country, i again aggregate the data ( i get 10 different countries) i create the colors for them, and then redraw the pie, at first render its ok, it takes the new colors (these colors have nothing to do with the colors of the ip pie), but when i hide or show parts of the pie, colors from the ip pie are shownWilkison
I don't understand why you are creating a d3.scale instead of just use the original array as the argument for the colors method.Trilemma
@PauloScardine - I agree with you, when I replied to this, I did not have much knowledge, Christopher Chiche has the perfect answer. I have upvoted his answer. Will update mine.Subtle
S
0

Here is a note that got me, I was setting chart.color inside of nv.addGraph, this was not working correctly and would instead use the defaults. I then set it outside of this and it worked fine.

Sweitzer answered 9/1, 2014 at 18:45 Comment(0)
S
0

I use .color(function(d) {return [d.value > 0 ? 'blue' : 'red']}); to make it change color depending on data value.

Hope this help someone.

Sedgemoor answered 22/10, 2015 at 13:54 Comment(0)
U
0

Here is the Typescript solution which is similar to the JS version. Let's say you want a Top 10 of your results with 10 different colors :

Here i'll give you the example that work for my PieChart or MultiBarChart

  • Create a global array of color like colors = ["#D9D9D9", "#4B11A6", ....];
  • The data has to be formatted in an Object : myGraph { key: "Title", values : { streams to push }}
  • Then when creating your data table just push the color for each stream :

let stream = {}; let data = []; let i=0;

dataTable.forEach((period) => {
    stream = { 'label': period.key, 'value': period.value, 'color': this.colors[i] };

if(period.value !== 0) {
 data.push(stream);}
 i++;
});
this.myGraph = data;

The if condition is just there to prevent empty piece in the graph

Urethra answered 19/7, 2017 at 12:59 Comment(0)
C
0

I have used below concept to add custom color:

// for define variable of custom colors 
var colors = ["red", "green", "blue"];
...
chart {
    color: function(d,i){
        return (d.data && d.data.color) || colors[i % colors.length]
    }
}

For dynamic color based on JSON Data just add New json obj color such as below concept..

// or set custom colors directly in the data
data = [{
        key: "One",
        y: 5,
        color: "yellow"
    },{
        key: "Two",
        y: 2,
        color: "gray"
    },{
        key: "Three",
        y: 9
    },
     ...
];
Curry answered 13/12, 2017 at 13:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.