Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assign specific color to specific segment in D3 Pie Chart

I have built a pie/doughnut chart using D3js (v4) as an Ember component and I am trying to have segments with specific labels be filled with a specific color but it is proving difficult.

To color the charts I have the following code:

marc = arc().outerRadius(radius - 10).innerRadius(radius - donutwidth),
color = scaleOrdinal().range(['#49b6d6', '#f59c1a', '#ff5b57',  '#00acac',]),

gEnter.append("path")
      .attr("d", marc)
      .attr("fill", (d, i) => {
        return color(i);
      })

The above works fine and fills the arcs with the selected colors but not the color I want per arc. The index of the array is consistent so I tried to simply re-arrange the order of the colors with no effect.

I also tried using an if statement based on the index like:

gEnter.append("path")
          .attr("d", marc)
          .attr("fill", (d, i) => {
            if (i === 0 { return color([0]) }
       })

This does fill in the segment which is index 0 but not with the selected color from the list. Changing the number in color([0]) actually produces no change at all. This is also true if I try to use a conditional based on the string of the Label instead of the index of the array.

EDIT

As part of the Ember Computed Property that formats data for the chart, the data is re-ordered so that each label is presented in the same order every time. THe computed property is as follows:

//takes the ember model 'referralsource' and groups it as needed   
sourceData: groupBy('referralsource', 'label'),

//ember computed property that provides data to chart
  pieData: Ember.computed('sourceData', function() {

    let objs = this.get('sourceData')
    let sortedObjs = _.sortBy(objs, 'value')
    let newArray = []

    sortedObjs.forEach(function(x) {
      let newLabel = x.value
      let count = x.items.length
      let newData = {
        label: newLabel,
        count: count
      }
      newArray.push(newData)
    })
    return newArray
  }),
like image 910
Sorvah Avatar asked Dec 12 '25 18:12

Sorvah


1 Answers

in your first example, try changing this:

color = scaleOrdinal().range(['#49b6d6', '#f59c1a', '#ff5b57',       '#00acac',]),

for this:

color = scaleOrdinal().range([0,4]),
color.domain(['#49b6d6', '#f59c1a', '#ff5b57', '#00acac']),

the range you use to indicate the size of your scale (in this case 4 because you put 4 colors) and the domain specifies what things are in each position of that scale

like image 51
Thiago Outeiro Pereira Damasce Avatar answered Dec 15 '25 19:12

Thiago Outeiro Pereira Damasce



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!