Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Chart.js: hiding series by clicking on legend

I'm developing a site that uses chart.js (www.chartjs.org).

I have to make a line chart that shows multiple series of data, that users can hide or show by clicking on the respective legend symbol (similar to this http://js.syncfusion.com/demos/web/#!/azure/chart/linechart).

Is there any way to do it with chartjs?

like image 445
pomarc Avatar asked Jan 22 '15 15:01

pomarc


4 Answers

You can try this
Create store for hidden datasets

window.chartName = new Chart(...

window.chartName.store = new Array();

Then use this function to update chart, must be handled by click on legend item

function updateDataset(legendLi, chart, label) {
      var store = chart.store;
      var exists = false;
      for (var i = 0; i < store.length; i++) {
        if (store[i][0] === label) {
          exists = true;
          chart.datasets.push(store.splice(i, 1)[0][1]);
          legendLi.fadeTo("slow", 1);
        }
      }
      if (!exists) {
        for (var i = 0; i < chart.datasets.length; i++) {
          if (chart.datasets[i].label === label) {
            chart.store.push([label, chart.datasets.splice(i, 1)[0]]);
            legendLi.fadeTo("slow", 0.33);
          }
        }
      }
      chart.update();
    }

Don't forget updated legend template in chart options

legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li class=\"legend-item\" onclick=\"updateDataset($(this), window.chartName, '<%=datasets[i].label%>')\"><span style=\"background-color:<%=datasets[i].strokeColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"

Shortly, i added this onclick handler for li component

<li class=\"legend-item\" onclick=\"updateDataset($(this), window.chartName , '<%=datasets[i].label%>')\"><

For example fiddle

like image 110
Igor Avatar answered Nov 09 '22 23:11

Igor


This is now available in Charts.js

From the documentation http://www.chartjs.org/docs/#chart-configuration-legend-configuration

Legend Configuration

The legend configuration is passed into the options.legend namespace. The global options for the chart legend is defined in Chart.defaults.global.legend.

onClick function(event, legendItem) {} A callback that is called when a 'click' event is registered on top of a label item

onHover function(event, legendItem) {} A callback that is called when a 'mousemove' event is registered on top of a label item

like image 28
benallansmith Avatar answered Nov 09 '22 22:11

benallansmith


An update to @benallansmith answer, the link to the documentation is now :

https://www.chartjs.org/docs/latest/configuration/legend.html

My version of the example code, to have datasets 2 and 3 hidden while clicking on legend for dataset 1 (datasets 2 and 3 have their legends hidden with the filter function):

public static readonly myChart: Chart.ChartConfiguration = {
    type: 'line',
    data: {
        datasets: [
            {
                label: 'A',
                borderColor: 'red',
                fill: false,
                lineTension: 0
            },
            {
                label: 'B',
                borderColor: 'blue',
                fill: false,
                lineTension: 0,
                pointRadius: 0
            },
            {
                borderColor: 'blue',
                borderDash: [5, 10],
                borderWidth: 1,
                fill: false,
                lineTension: 0,
                pointRadius: 0
            },
            {
                borderColor: 'blue',
                borderDash: [5, 10],
                borderWidth: 1,
                fill: false,
                lineTension: 0,
                pointRadius: 0
            }
       ]
   },
   options: {
       legend: {
           labels: {
               filter: function(legendItem, chartData) {
                    if (legendItem.datasetIndex > 1) {
                        return false;
                    }
                    return true;
                }
            },
            onClick: function(e, legendItem) {
                const index = legendItem.datasetIndex;
                if (index === 1) {
                    const ci = this.chart;
                    [
                        ci.getDatasetMeta(1),
                        ci.getDatasetMeta(2),
                        ci.getDatasetMeta(3)
                    ].forEach(function(meta) {
                        meta.hidden = meta.hidden === null ? !ci.data.datasets[1].hidden : null;
                    });
                    ci.update();
                } else {
                    // Do the original logic
                    Chart.defaults.global.legend.onClick.call(this, e, legendItem);
                }
            }
        },
        responsive: false,
        animation: {
            duration: 0
        },
    }
...
};
like image 37
Ailete619 Avatar answered Nov 10 '22 00:11

Ailete619


my version is v2.8.0 I find a work way, try it.

add

legend : {

                }

into option

var donutOptions     = {
                maintainAspectRatio : false,
                responsive : true,
                animation: {
                    animateScale: true,
                    animateRotate: true
                },
                tooltips: {
                    intersect: false,
                    callbacks: {
                        label: function (tooltipItem, data) {
                            ...
                        }
                    },
                },
                plugins: {
                    datalabels: {
                        ...
                        },
                    },
                },
                legend : {

                }

            };

and use this


donutChart.chart.getDatasetMeta(0).data[index].hidden = true;

donutChart.update();
like image 22
EZone Lai Avatar answered Nov 09 '22 23:11

EZone Lai