[Chartjs]-How can I scale my dataset values as a percentage of the index in chart.js?

2👍

So, I figured it out. I needed to write a function to calculate the percentage area of the points in the index and then update the datasets with the calculated percentage values.

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 * 
 *  DS_update calculates the percentage area of the input datasets 
 * 
 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
function DS_update(dataset_in, ds_vis){
    // make a deep copy (no references to the source)
    var temp = jQuery.extend(true, [], dataset_in);

    // gets the sum of all datasets at a given index
    function getTotal(index){
        total = 0;
        // step through the datasets
        dataset_in.forEach(function(e, i){
            // inc total if the dataset is visible
            if(ds_vis[i]){
                total += e[index];
            }
            // do nothing if the dataset is hidden

        });
        return total;
    }

    // update temp array with calculated percentage values
    temp.forEach(function(el, ind){                                 

        var j = ind;
        el.forEach(function(e, i){      
            // calculate percentage to the hundredths place
            temp[j][i] = Math.round((e / getTotal(i))*10000)/100;
        }); 
    });

    return temp;
}

Once I tested the functions I had to run them before initial load of the chart or else the user would see the datasets as non area-percent (raw data). which looks something like this:

// Keep source array to use in the tool tips
var Src_ary = Input_data;    // multidimensional array of input data
// holds the percent-area calculations as datapoints
var Prod_ary = DS_update(Src_ary, Init_visible(Src_ary));

Next up was updating the onClick for the legend. I need this to update the calculations every time an item’s visibility is toggled:

legend: {
    position: 'bottom',
    usePointStyle: true,
    onClick: 

        function(e, legendItem){      
            var index = legendItem.datasetIndex;
            var ci    = this.chart;
            var meta  = ci.getDatasetMeta(index);
            var vis_ary = [];           
            var updatedSet = [];

            // See controller.isDatasetVisible comment
            meta.hidden = meta.hidden === null? !ci.data.datasets[index].hidden : null;

            // load the visible array
            for(var i = 0; i < (ci.data.datasets || []).length; i++){
                switch (ci.getDatasetMeta(i).hidden){
                    case null:
                        vis_ary.push(true);
                    break;     
                    default:
                        vis_ary.push(false);
                    break;
                }
            }  

            // update datasets using vis_ary to tell us which sets are visible
            updatedSet = DS_update(Prod_ary, vis_ary);
            myLine.data.datasets.forEach(function (e,i){
                e.data = updatedSet[i];
            });

            // We did stuff ... rerender the chart
            ci.update();

        }
    }

END RESULT

This is what I was trying to do: highchart fiddle

This is what I ended up with:fiddle

It took a few days and a lot of reading through chartjs.org’s documentation to put this together. In the end I think it came out pretty good considering I am new to chart.js and borderline illiterate with javascript.

Leave a comment