2

I am trying to change the opacity of the last clicked bar in ChartJS, and for it then to be 'unhighlighted' the next time another bar is clicked. Basically the default behaviour for hover. Please note this is a stacked bar chart, and I wish for the entire bar columns opacity to change, not each individual section.

I have got as far as being able to change the background colour (not sure how to change the opacity) to black on click, but it does not unset when the next item is clicked. So the entire chart ends up being black once everything has been clicked on.

This is the onclick code I am currently using:

            var myChart = new Chart(ctx, {
            type: 'bar',
            data: data,
            options: {
                onClick: function(e){
                    myChart.update();
                    var element = this.getElementAtEvent(event)[0];
                    element.custom = element.custom || {};
                    element.custom.backgroundColor = '#000';
                    },
                }
            });

Stacked data :

            var data = {
                "labels":["2011","2012","2013","2014","2015"],
                "datasets":[
                            {
                                "label":"Total Fishermen",
                                "backgroundColor":"#518936",
                                "data":[991,1020,731,850,851]
                            },
                            {
                                "label":"Total Processing Employees",
                                "backgroundColor":"#82c6d4",
                                "data":[0,0,130,0,0]
                            },
                            {
                                "label":"Total Aquaculture Employees",
                                "backgroundColor":"#c0136b",
                                "data":[0,134,130,119,0]
                            }
                        ]
                    };

Any help will be greatly appreciatted!

Kevin Smith
  • 139
  • 3
  • 18

1 Answers1

4

... but it does not unset when the next item is clicked.

You may use the active property in order to get the active group elements and use the current backgroundColor adding a 50% of transparency:

this.active.forEach(function(ele, idx) {
    ele.custom = ele.custom || {};
    if (ele.custom.backgroundColor == undefined) {
        var color = ele._model.backgroundColor.replace(')', ', 0.5)');
        ele.custom.backgroundColor = color;
    } else {
        delete ele.custom.backgroundColor;
    }
});

In order to reset last clicked element you can do that in your onClick handler looping on all elements:

for(i=0; i<this.data.datasets.length; i++) {
    this.getDatasetMeta(i).data.forEach(function(ele, idx) {
        if (ele.custom != undefined)
            delete ele.custom.backgroundColor;
    });
}

Chart.pluginService.register({
    afterInit: function (chart, options) {
        chart.pluginInitialized = true;
    },
    afterDraw: function (chart, options) {
        if (chart.pluginInitialized) {
            var centerIndex = Math.floor(chart.data.labels.length/2);
            for(var i=0; i<chart.data.datasets.length; i++) {
                chart.getDatasetMeta(i).data.forEach(function(ele, idx) {
                    var opacity = ' 0.3)';
                    if (idx == centerIndex) {
                        opacity = ' 1)';
                    }
                    ele.custom = ele.custom || {};
                    if (ele.custom.backgroundColor == undefined) {
                        var rgb = ele._model.backgroundColor;
                        var match = null;
                        if (match = rgb.match(/^#([a-fA-F0-9]{6})$/i)) {
                            rgb = 'rgb(';
                            match = match[1];
                            for (var j = 0; j < 3; j++) {
                                rgb += parseInt(match.slice(j * 2, j * 2 + 2), 16) + ',';
                            }
                            rgb += opacity;
                        }
                        ele.custom.backgroundColor = rgb;
                    }
                });
            }
            chart.pluginInitialized = false;
            chart.update(true);
        }
    }
});

var ctx = document.getElementById('ctx').getContext('2d');
var data = {
    "labels":["2011","2012","2013","2014","2015"],
    "datasets":[
        {
            "label":"Total Fishermen",
            "backgroundColor":"#518936",
            "data":[991,1020,731,850,851]
        },
        {
            "label":"Total Processing Employees",
            "backgroundColor":"#82c6d4",
            "data":[0,0,130,0,0]
        },
        {
            "label":"Total Aquaculture Employees",
            "backgroundColor":"#c0136b",
            "data":[0,134,130,119,0]
        }
    ]
};
var myChart = new Chart(ctx, {
    type: 'bar',
    data: data,
    options: {
        onClick: function (e) {
            // remove old background opacity....
            for(i=0; i<this.data.datasets.length; i++) {
                this.getDatasetMeta(i).data.forEach(function(ele, idx) {
                    var rgx = /(rgba*\(\d{1,3}), *(\d{1,3}), *(\d{1,3}), *[0-9.]+(\))/;
                    ele._model.backgroundColor = ele._model.backgroundColor.replace(rgx, "$1, $2, $3$4");
                    if (ele.custom != undefined)
                        delete ele.custom.backgroundColor;
                });
            }
            // set backgrounf opacity....
            this.active.forEach(function(ele, idx) {
                ele.custom = ele.custom || {};
                if (ele.custom.backgroundColor == undefined) {
                    var color = ele._model.backgroundColor.replace(')', ', 0.5)');
                    ele.custom.backgroundColor = color;
                } else {
                    delete ele.custom.backgroundColor;
                }
            });
            myChart.update(true);
        }
    }
});
.graph {
    height: 500px;
    width: 500px;
    text-align: center;
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>

<div class="graph">
    <canvas id="ctx"></canvas>
</div>
gaetanoM
  • 41,594
  • 6
  • 42
  • 61