Chart.js: Waterfall Charts

Created on 2 Aug 2016  ·  14Comments  ·  Source: chartjs/Chart.js

Can you please help me to create a waterfall chart by extending bar charts in chart.js?
The approach could be changing the height of the y axis for implementing the changes in chart values in the alternate bars.

e.g 10 , 30 is my dataset.

so the waterfall chart will have :
[10, a bar here with a hieght of 20 (30-10) and starting at the end of the first bar, 30]

implement externally support

Most helpful comment

Waterfall Chart

@Sabyasachi18 @snd1 using the dummy dataset is a good option if you don't want to change the library internals.

If you are okay with changing the code and rebuilding chart.js, you could try modifying the bar controller. The bar controller, calculateBarBase method determines where the base of the bar will be (the side that does not animate). It is defined at https://github.com/chartjs/Chart.js/blob/master/src/controllers/controller.bar.js#L100-L124

Right now, the loop only considers negative numbers if the current value is negative and vice versa. All if would have to do for a waterfall chart is to sum up all the values before the one being plotted. A similar change would need to be made in calculateBarY.

Labelling

Lots of discussion here: https://github.com/chartjs/Chart.js/issues/327
There is a sample file that shows this (text color is pretty bad for some reason) https://github.com/chartjs/Chart.js/blob/master/samples/data_label_combo-bar-line.html

Bar Color

You can set the background color of the dataset to an array of colours. The 2nd color would be used for the 2nd bar. Alternatively, you can find the bar you want red and do

bar.custom = bar.custom || {};
bar.custom.backgroundColor = 'rgb(255, 0, 0)';
bar.custom.hoverBackgroundColor = // custom hover background color
chart.update(); // forces re-render

The custom element for bars has the following properties
backgroundColor, borderColor, borderWidth, hoverBackgroundColor, hoverBorderColor, and hoverBorderWidth

All 14 comments

Hi,
I just finished my first waterfall chart with the new chart.js.
I did it pretty simple. 3 Bars:
1 Bar: white bar which covers the others, with Math.min(bar_x-1, bar_x)
2 Bar: red bar with value of bar_x-1
3 Bar: with value of bar_x
only the third bar has starting and ending values to make the waterfall rise and fall again.
Sorry I don't know if you can follow my thinking. It'll just give you a waterfall chart with green bar, when the bar rises, red when the bar falls.

If you need further explanation I'll help you, but I'm kinda in a hurry now.

cheers

Ok, I just saw that you have a dummy dataset. Let's do the following, you want the starting bar to start from 30, fall to 20, rise again to 30.

datasets: [
{
data[0,20,0],
backgroundColor: "rgba(250,250,250,1)"
}, {
data[0, 30, 20],
backgroundColor: "rgba(250,0,0,1)"
},{
data[30,10,30],
backgroundColor: "rgba(0,250,0,1)"
}

This will give you three bars, a green starting bar from 30, a red falling bar from 30 to 20, and a green bar rising from 20 to 30...

Hope this makes my idea clearer...

@snd1 Thanks for your comment..Ok....I am getting a hang of your imlementation....I just had a question.....Could you provide me a image or Pic of how this looks once implemented?

@Sabyasachi18
Nice if you get the hang of my worst description of an idea.
Here's a screenshot with a little more data in it...
Waterfall
Hope i could help you... I gotta just hide the borders behind the white bar, and it'll look decent with some nice coloring...

@snd1 Thanks....It looks pretty nice...However, I have to display the values also on the charts, as shown in below image. for e.g, a red bar will show the -ve value on the bar
image

@Sabyasachi18 I'm pretty new to JS and Chart.js, so I might not be the best reference. But how about you iterate afterwards through the bars and just add the wanted label onto it? It's always the difference between the green bar and the red bar. As far as I can see it.

Waterfall Chart

@Sabyasachi18 @snd1 using the dummy dataset is a good option if you don't want to change the library internals.

If you are okay with changing the code and rebuilding chart.js, you could try modifying the bar controller. The bar controller, calculateBarBase method determines where the base of the bar will be (the side that does not animate). It is defined at https://github.com/chartjs/Chart.js/blob/master/src/controllers/controller.bar.js#L100-L124

Right now, the loop only considers negative numbers if the current value is negative and vice versa. All if would have to do for a waterfall chart is to sum up all the values before the one being plotted. A similar change would need to be made in calculateBarY.

Labelling

Lots of discussion here: https://github.com/chartjs/Chart.js/issues/327
There is a sample file that shows this (text color is pretty bad for some reason) https://github.com/chartjs/Chart.js/blob/master/samples/data_label_combo-bar-line.html

Bar Color

You can set the background color of the dataset to an array of colours. The 2nd color would be used for the 2nd bar. Alternatively, you can find the bar you want red and do

bar.custom = bar.custom || {};
bar.custom.backgroundColor = 'rgb(255, 0, 0)';
bar.custom.hoverBackgroundColor = // custom hover background color
chart.update(); // forces re-render

The custom element for bars has the following properties
backgroundColor, borderColor, borderWidth, hoverBackgroundColor, hoverBorderColor, and hoverBorderWidth

@etimberg ...Thanks a lot for your help....I will get working on your suggestions, and let you know if I face any issues while doing it!

@etimberg Hi Evert...I tried to change the CalculateBarBase function....Here is my changed function code - ```
calculateBarBase: function(datasetIndex, index) {
var me = this;
var meta = me.getMeta();
var yScale = me.getScaleForId(meta.yAxisID);
var base = 0;

        if (yScale.options.stacked) {
            var chart = me.chart;
            var datasets = chart.data.datasets;
            var value = Number(datasets[datasetIndex].data[index]);

            for (var i = 0; i < datasetIndex; i++) {
                var currentDs = datasets[i];
                var currentDsMeta = chart.getDatasetMeta(i);
                if (currentDsMeta.bar && currentDsMeta.yAxisID === yScale.id && chart.isDatasetVisible(i)) 
                {
                    var currentVal = Number(currentDs.data[index]);
                    //base += value < 0 ? Math.min(currentVal, 0) : Math.max(currentVal, 0);
                    base += Number(100);
                    //currentDs.data[index]
                }
            }

            return yScale.getPixelForValue(base);
        }

        return yScale.getBasePixel();
    },
Based on the above function, the Bar Base has been set to 100.
But it makes no difference to the bar-chart in this URL: http://localhost:8000/samples/bar.html

Can you please take a look into this?? Thanks in advance

Posting local links doesn't really make sense ;) Upload an image :)

Since I have changed the base variable value as 100 for every bar, should the bar base be 100 for every bar now? I dont see that happening
image

Is the Y axis stacked? Also, you are adding 100 for every previous item, so the base for February is 100, the base for march is 200, etc.

Closing as resolved.

Added waterfall chart plugin package. See https://github.com/MartinDawson/chartjs-plugin-waterfall

@etimberg Can I add my package to the chartjs repository please? And can you review my code to see if it's what you expect? Thanks.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

HeinPauwelyn picture HeinPauwelyn  ·  3Comments

lizbanach picture lizbanach  ·  3Comments

longboy picture longboy  ·  3Comments

lbowers picture lbowers  ·  3Comments

JewelsJLF picture JewelsJLF  ·  3Comments