apexcharts / apexcharts.js

📊 Interactive JavaScript Charts built on SVG
https://apexcharts.com
MIT License
14.37k stars 1.3k forks source link

Line chart colors based on series values #3723

Open hjelmdal opened 1 year ago

hjelmdal commented 1 year ago

Summary

It would be awesome to have the option to color code your line series based on their values like shown below. image

Intended Use Case

The example above shows a few Google Lighthouse metrics change over time - in this case it gives the user a great overview to see that a threshold is exceeded and therefore the chart series changes color subject to that threshold. In my case I work with 3 segments, a "good, "needs improvements" and "poor" - but there could be more segment thresholds to describe whether your data is good, medium og bad or whatever you want to show.

I really hope this would be considered because I find this very critical for my use, and I only see paid js libraries offering this option.

Thanks a lot in advance.

szigetinandor commented 1 year ago

Yes, it would be REALLY nice! Does any workaround exist? It's hard to believe it is impossible to do with this library :(

github-actions[bot] commented 1 year ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

hjelmdal commented 1 year ago

@junedchhipa , can you by any chance prioritize this one? :)

b0tm1nd commented 1 year ago

What about this https://codepen.io/webxtor/pen/ZEmgMMV ? I have achieved this simply with:

colors: ['#B72136'], fill: { type: "gradient", gradient: { type: 'vertical', gradientToColors:['#007B55'], stops: [80,0], }

When you put stops as 80,0 or actually 80,<80, where <80 any number below 80 there will be no gradient transition between colors! The way "stops" work seems to be very poorly documented, but it seem to work well this way!

Also more complex example with colorStops: https://github.com/apexcharts/apexcharts.js/issues/2220

github-actions[bot] commented 1 year ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

scott-wojan commented 1 year ago

This has been requested so many times. It's incredibly frustrating that you can'y so something a simple as color everything zero and above as green and everything below zero as red in both line an area charts.

github-actions[bot] commented 10 months ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

hjelmdal commented 10 months ago

Well… I guess I’ll have to stick with amcharts for these use cases instead, although I think it’s an over complex solution for such basic use cases… disappointing 🤷‍♂️

hjelmdal commented 10 months ago

Oops… I wanted to try once again to re open…

github-actions[bot] commented 8 months ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

hjelmdal commented 8 months ago

It is not completed! And it is still relevant…

svgr-slth commented 6 months ago

@hjelmdal Fully with you on this one, would love to have updates on this. Every related issue dies from inactivity. I can find traces of people asking for this up to four years ago.

https://github.com/apexcharts/apexcharts.js/issues/3980: relates to the issue https://github.com/apexcharts/apexcharts.js/issues/1853: Is precisely the same demand, 4y ago

This would give this feature a way more interesting impact as it would provide visual information about the data plotted, instead of just being something to make charts look fancy

@brianlagunas @joadan @junedchhipa any info about this would be greatly appreciated ! Thanks, best

guelweles commented 5 months ago

What about this https://codepen.io/webxtor/pen/ZEmgMMV ? I have achieved this simply with:

colors: ['#B72136'], fill: { type: "gradient", gradient: { type: 'vertical', gradientToColors:['#007B55'], stops: [80,0], }

When you put stops as 80,0 or actually 80,<80, where <80 any number below 80 there will be no gradient transition between colors! The way "stops" work seems to be very poorly documented, but it seem to work well this way!

Also more complex example with colorStops: #2220

What about this https://codepen.io/webxtor/pen/ZEmgMMV ? I have achieved this simply with:

colors: ['#B72136'], fill: { type: "gradient", gradient: { type: 'vertical', gradientToColors:['#007B55'], stops: [80,0], }

When you put stops as 80,0 or actually 80,<80, where <80 any number below 80 there will be no gradient transition between colors! The way "stops" work seems to be very poorly documented, but it seem to work well this way!

Also more complex example with colorStops: #2220

Your example almost worked for me but it lead me to another thinking and I got it working, in my case I wanted everything < 0 to be red and everything > 0 to be green.

So I initially thought to set stops: [50,0], it only works as long as your data is within the same range, like let's say my data lowest number is -150 and max is 150, the stops would work perfectly fine, but if your data contains for example min value -20 and max value 150, you have to find the appropriate value for the zero line.

In my case I mapped the range " -20 to 150" to" 0% - 100%", based on that I could find where the zero line sits in between the range 0% - 100%.

here's my solution in case anyone is interested.

const generateStop = (data) => {
    const max = Math.max(...data);
    const min = Math.min(...data);
    const zeroLine = mapRange(0, min, max, 0, 100);
    //console.log("max", max, "min", min, "zero line", zeroLine);
    return [100 - zeroLine, 0];
}

function mapRange(value, fromMin, fromMax, toMin, toMax, decimalPlaces = 0) {
    // Ensure the value is within the original range
    value = Math.min(Math.max(value, fromMin), fromMax);

    // Calculate the percentage of the value within the original range
    const percentage = (value - fromMin) / (fromMax - fromMin);

    // Map the percentage to the new range
    let newValue = toMin + percentage * (toMax - toMin);

    // Round the result to the specified number of decimal places
    newValue = decimalPlaces ? Number(newValue.toFixed(decimalPlaces)) : parseInt(newValue);

    return newValue;
}

// Options object from Apex
colors: ['#FD0E35'],
fill: {
    type: 'gradient',
    gradient: {
            type: 'vertical',
            gradientToColors: ['#29AB87'],
            stops: generateStop(data[0].data) // in my case data is an array of objects, if yours is just an object, pass it accordingly.
     }
 },

Thanks for your example, it was really helpful.