buydadip
buydadip

Reputation: 9427

How to specify the color scale within the data object in Victory Pie

I used VictoryChart to implement a pie graph and it works fine...

render() {

    const data_distribution = this.state.pie_keys.map((d) => ({x:d, y:this.state.pie_data[d], label:d }));

    return (
      <div className="App">
        <div className="pie_wrapper">
          <VictoryPie
            labelComponent={<VictoryTooltip cornerRadius={0} />}   
            padAngle={0.5}
            innerRadius={100}
            width={400} height={400}
            style={{ 
              labels: { fontSize: 15, fill: "black"},
              data: {
                  fillOpacity: 0.9, stroke: "white", strokeWidth: 3
              }
            }}
            labelRadius={90}
            data = {data_distribution}
          />
        </div>
      </div>
    );
  }

It is important to note that data_distribution simply looks as follows...

data={[
    { x: "Fac of Engineering & Appl Sci", y: 8.557902403495994 },
    { x: "Faculty of Arts and Science", y: 53.775188152464196 },
    { x: "Faculty of Education", y: 13.085700412721534 },
    ...
    ...
  ]}

So I'm wondering if I can set the color for each piece of the pie within the data object. The documentation specifies that...

color scales: "grayscale", "qualitative", "heatmap", "warm", "cool", "red", "green", "blue". VictoryPie will assign a color to each slice by index, unless they are explicitly specified in the data object.

This says that you can but I cannot figure out how. I tried the following...

data={[
    { x: "Fac of Engineering & Appl Sci", y: 8.557902403495994, colorScale:"red" },
    { x: "Faculty of Arts and Science", y: 53.775188152464196, colorScale:"red" },
    { x: "Faculty of Education", y: 13.085700412721534, colorScale:"red" },
    ...
    ...
]}

which translates to...

const data_distribution = this.state.pie_keys.map((d) => ({x:d, y:this.state.pie_data[d], label:d, colorScale:"red"}));

However, they do not turn red. I cannot find an example online. Is this possible to do or not?

I know that I can define colorScale: {[...]} but that is not what I'm asking. I want to be able to set each piece of the pie from within the data object.

Upvotes: 7

Views: 7905

Answers (6)

pors
pors

Reputation: 4054

For the current version

"victory": "^35.4.0",
"victory-native": "^35.3.1"

you can do:

 <VictoryPie
        data={[
            { x: "Cats", y: 35, fill: "gold" },
            { x: "Dogs", y: 40, fill: "tomato" },
            { x: "Birds", y: 55, fill: "navy" }
        ]}
        style={{
            data: {
                fill: ({datum}) => datum.fill
            }
        }}
   />

See https://formidable.com/open-source/victory/docs/common-props/#data

Upvotes: 6

WOLVERTRON
WOLVERTRON

Reputation: 131

You can derive the fill color based on your data, but you have to provide that logic. Your accepted answer applies color based on y value, however you can also specify the color in the data itself so long as you set the style to do so:

<VictoryPie
  data={[
    { x: "Cats", y: 35, yourAttribute: "#0000FF" },
    { x: "Dogs", y: 40, yourAttribute: "#00FF00" },
    { x: "Birds", y: 55, yourAttribute:"#FF0000" }
  ]}
  style={{
    data: {
      fill: (d) => d.yourAttribute
    }
  }}
/>

Upvotes: 7

Jon Hieb
Jon Hieb

Reputation: 780

I know this question has been "answered", but the answer is unsatisfactory to me. Since I came here and left frustrated, I've decided to post my solution in the hopes that others might get some use out of it.

You can override the colors for individual slices using the style prop:

<VictoryPie
  data={[
    { x: "Cats", y: 35 },
    { x: "Dogs", y: 40 },
    { x: "Birds", y: 55 }
  ]}
  style={{
    data: {
      fill: ({ y }) =>
        y > 49 ? 'green'
        : y > 39 ? 'yellow'
        : 'tomato'
    }
  }}
/>

In this case, you should not use colorScale at all. I've read the source, and far as I can tell, this is the only way to do a data-based color mapping in VictoryPie.

Upvotes: 9

feralislatr
feralislatr

Reputation: 21

I think instead of colorScale: "red", you want fill: "red" in the data object since Victory's Slice primitives are just svg <Path> elements.

Upvotes: 2

pageNotfoUnd
pageNotfoUnd

Reputation: 666

I manually added a function to generate randomly try if this helps you `var stats = this.state.statistics;

var stat = this.state.statistic;
        if (stats.length>0) {
            if(this.colors.length<stats.length){
                for(let i=0;i<stats.length;i++){
                    this.colors.push(getRandomColor());
                }
            }
        }
        const color = ['#9167f1', '#f26893', '#99cfef', '#99ef9a'];
        const colors = this.colors;`

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

Upvotes: 3

pageNotfoUnd
pageNotfoUnd

Reputation: 666

If you know the data rendering order then you can use the colors in same order it will automatically take the color in order

<VictoryPie
  colorScale={["black", "red", "green", "#4cc9ff", "navy" ]}
  data={sampleData}
/>

Upvotes: 2

Related Questions