Search code examples
colorsamchartsamcharts4

How to conditionally set colors and make gradient to pie chart slices in amCharts v4?


EDIT: Here is a code pen.


There are two main goals:

  1. Set different colors for slices based on the specific conditions.
  2. Make the colors be gradient, based on the amount.

More info:

1. Set different colors for slices based on the specific conditions.

EDIT: As shown in the code pen, I managed to find a solution for this, but I don't know how good it is.

I want to set different colors for slices based on specific conditions, i.e. specific 'type' & 'ordering'.

For example:

if (ordering < 9999)                            => green
if (ordering >= 9999 && type === 'can-be-sold') => orange
if (type !== 'can-be-sold')                     => red

2) Make the colors be gradient, based on the amount.

Example:

There are 10 items that are green, each with a different amount. The slices with the biggest amount should have the color in its darker shade, whereas the slices with the smallest amount should have the color in its lightest shade.


I get the data through ajax:

 $.ajax({
            'url': '{$dataStockUrl}',
        }).done(function(data) {
            chart.data = data;
    });

The data I get from $dataStockUrl is in the format of:

[{
  "shop": "Lorem", 
  "type": "can-be-sold",
  "amount": "23",
  "ordering":"0"
},
{
  "shop": "Ipsum", 
  "type": "can-not-be-sold",
  "amount": "1",
  "ordering":"9999"
},
....etc....
]

Solution

  • You should use an adapter for that:

    pieSeries.slices.template.adapter.add('fill', (value, target, key) => {
        if (!target.dataItem || !target.dataItem.dataContext) {
            return value;
        }
        if (target.dataItem.dataContext.ordering < 9999) {
            return am4core.color('rgba(121, 153, 0, 1)');
        }
        if (target.dataItem.dataContext.ordering >= 9999 && target.dataItem.dataContext.type === 'can-be-sold') {
            return am4core.color('rgba(255, 165, 0, 1)');
        }
        if (target.dataItem.dataContext.type !== 'can-be-sold') {
            return am4core.color('rgba(255, 0, 0, 1)');
        }
        return value;
    });
    

    I forked your code pen to show the complete example.

    Here you can read more about colors and gradients in amcharts4. You can use .lighten() or .brighten() on the color, based on the amount value:

    pieSeries.slices.template.adapter.add('fill', (value, target, key) => {
        if (!target.dataItem || !target.dataItem.dataContext) {
            return value;
        }
        let color;
        if (target.dataItem.dataContext.ordering < 9999) {
            color = am4core.color('rgba(121, 153, 0, 1)');
        }
        if (target.dataItem.dataContext.ordering >= 9999 && target.dataItem.dataContext.type === 'can-be-sold') {
            color = am4core.color('rgba(255, 165, 0, 1)');
        }
        if (target.dataItem.dataContext.type !== 'can-be-sold') {
            color = am4core.color('rgba(255, 0, 0, 1)');
        }
        if (!color) {
            return value;        
        }
        if (minAmount !== undefined && maxAmount !== undefined) {
            const percent = target.dataItem.dataContext.amount / (maxAmount - minAmount);
            color = color.brighten(percent - 0.5);
        }
        return color;
    });
    

    Here is another code pen for the final result.

    The result looks like this:

    enter image description here