Show/hide/toggle 通过单击图例在 Google 图表上的数据系列

Show/hide/toggle Data Series on Google Chart by clicking Legend

我有一个显示 11 个不同系列数据的 Google 折线图。我希望用户能够通过单击图例中的相关系列来 show/hide 一个系列。我在 Whosebug 的其他地方找到了 个类似的问题和解决方案。但是,当我在合并我认为是上述解决方案中的适用代码后单击图例中的系列时,没有任何反应。我在下面的代码末尾评论了解决方案中修改后的代码的开始位置。

非常感谢您的帮助。

<html>
  <head>
    <script src="https://www.gstatic.com/charts/loader.js"></script>
    <script type="text/javascript">
  
  google.charts.load('current', {packages: ['controls']}).then(initialize);
  
  function initialize() {
    var query = new google.visualization.Query('https://docs.google.com/spreadsheets/d/1001YnF8LCwKyzpS4pgmZnwFVigL-LlnqwWn6xjnso2k/edit#gid=0&range=A:BT');
        query.send(drawDashboard);
  }
  
  function drawDashboard(response) {
  
    var data = response.getDataTable();
    //Asign units of 'mm' to data.
    var formatMS = new google.visualization.NumberFormat({pattern: '# mm'});
  
    // format data into mm.
    for (var colIndex = 1; colIndex < data.getNumberOfColumns(); colIndex++) {formatMS.format(data, colIndex);}
    var dataView = new google.visualization.DataView(data);
    dataView.setColumns([0,1,2,{sourceColumn: 3, role: 'interval'}, {sourceColumn: 4, role: 'interval'}, 5,{sourceColumn: 6, 'type': 'string', role: 'tooltip', 'p': {'html': true}},7,8,9,10,11,12,13,14,15,{sourceColumn: 16, role: 'interval'}, {sourceColumn: 17, role: 'interval'}, 18,{sourceColumn: 19, 'type': 'string', role: 'tooltip', 'p': {'html': true}},20,21,22,23,24,25,26,27,28,{sourceColumn: 29, role: 'interval'}, {sourceColumn: 30, role: 'interval'},31,{sourceColumn: 32, 'type': 'string', role: 'tooltip', 'p': {'html': true}},33,34,35,36,37,38,39,40,41,{sourceColumn: 42, role: 'interval'}, {sourceColumn: 43, role: 'interval'}, 44,{sourceColumn: 45, 'type': 'string', role: 'tooltip', 'p': {'html': true}},46,47,48,49,50,51,52,53,54,{sourceColumn: 55, role: 'interval'}, {sourceColumn: 56, role: 'interval'}, 57,{sourceColumn: 58, 'type': 'string', role: 'tooltip', 'p': {'html': true}},59,60,61,62,63,64,65,66,67,68,69,70,71]);
  
    var YearPicker = new google.visualization.ControlWrapper({
      controlType: 'NumberRangeFilter',
      containerId: 'filter_div',
      options: {
        maxValue: 2150,
        minValue: 1891,
        filterColumnLabel: 'Year',
        ui: {
          cssClass: 'filter-date',
          format: {pattern: '0000'},
          labelStacking: 'vertical',
          allowTyping: true,
          allowMultiple: false
        }
      },
      state: {lowValue: 1891, highValue: 2150},
    });
  
    google.visualization.events.addListener(YearPicker, 'statechange', function () {
      var state = YearPicker.getState();
      state.lowValue = Math.min(2021, state.lowValue);
      YearPicker.setState({
        lowValue: state.lowValue,
        highValue: state.highValue
      });
      YearPicker.draw();
    });
  
    var MSLChart = new google.visualization.ChartWrapper({
      chartType: 'LineChart',
      containerId: 'chart_div',
      dataTable: dataView,
      options: {
        fontSize: '20',
        title: 'NZ Annual Relative Mean Sea Level Summary',
        hAxis: {title: 'Year', format: '0000'},
        vAxis: {title: 'Height above 1986-2005 IPCC Baseline (mm)', format:'###0'},
        height: 600,
        chartArea: {height: '81%', width: '85%', left: 100},
        legend: {position: 'top', maxLines: 5, alignment: 'start', textStyle: {fontSize: 9}},
        colors: ['blue'],
        tooltip: {
          isHtml: true
        },
        trendlines: {
          9: {
            type: 'linear',
            color: 'black',
            visibleInLegend: true,
            showR2: true,
          },
          10: {
            type: 'polynomial',
            color: 'purple',
            degree: 2,
            visibleInLegend: true,
            showR2: true,
          },
        },
        series: {
          0: {color:'navy', visibleInLegend: true}, //Auckland
          1: {color:'green', visibleInLegend: true }, //Taranaki
          2: {color:'gold', visibleInLegend: true}, //Wellington
          3: {color:'red', visibleInLegend: true}, //Lyttelton
          4: {color:'DeepSkyBlue', visibleInLegend: true}, //Dunedin
          5: {color:'#47d045', visibleInLegend: true}, //NZ RCP2.6 M
          6: {color:'#0e038d', visibleInLegend: true}, //NZ RCP4.5 M
          7: {color:'#b8bb62', visibleInLegend: true}, //NZ RCP8.5 M
          8: {color:'#b22123', visibleInLegend: true}, //NZ RCP8.5 H
          9: {color:'blue', visibleInLegend: true}, //NZ Mean
          10: {color:'blue', visibleInLegend: false}, //NZ Mean
        },
        intervals: { 'style':'bars','color': '#6292dc' },
        interpolateNulls: 'True',  
      },
      view: {columns: [0,7,20,33,46,59,66,67,68,69,70,71]}
    });
  
var dashboard = new google.visualization.Dashboard(document.getElementById('dashboard_div')).bind(YearPicker, MSLChart).draw(dataView);

 //Code taken from above solution begins here: 
  var columns = [];
  var series = {};
  for (var i = 0; i < data.getNumberOfColumns(); i++) {
    columns.push(i);
    if (i > 0) {
      series[i - 1] = {};
    }
  }
  google.visualization.events.addListener(MSLChart, 'select', function () {

    var sel = MSLChart.getChart().getSelection();
    // if selection length is 0, we deselected an element
    if (sel.length > 0) {
       // if row is undefined, we clicked on the legend
       if (sel[0].row === null) {
           var col = sel[0].column;
           if (columns[col] == col) {
              // hide the data series
              columns[col] = {
                 label: data.getColumnLabel(col),
                 type: data.getColumnType(col),
                 calc: function () {
                     return null;
                 }
              };
              // grey out the legend entry
              series[col - 1].color = '#CCCCCC';
          } else {
              // show the data series
              columns[col] = col;
              series[col - 1].color = null;
          }
          var view = new google.visualization.DataView(data);
          view.setColumns(columns);
          MSLChart.draw();
       }
  }
});
  }
  </script>
  </head>
  <body>
      <div id="dashboard_div" >
         <div id="filter_div"></div>
         <div id="chart_div"></div>
       </div>
  </body>
</html>

首先,需要在绘制图表之前分配图表事件,
只需要将 select 事件移动到 dashboard.draw

上方

接下来,由于您要在图表包装器上设置特定的视图列,
我们在更改系列时需要考虑这些因素。
我们将保存对视图列的引用...

var viewColumns = [0,7,20,33,46,59,66,67,68,69,70,71];

然后在隐藏/显示系列时使用该参考...

var col = viewColumns[sel[0].column];

接下来,设置新列并且图表将 re-drawn、
我们必须用新视图更新图表的数据表...

var view = new google.visualization.DataView(dataView);
view.setColumns(columns);
MSLChart.setDataTable(view);  // <-- here

引用的答案中不起作用的内容,
正在使该系列的图表图例变灰。
一旦我们更改了系列颜色,
我们必须重置系列选项...

MSLChart.setOption('series', series);

最后,我添加了另一个例程,以防止 y-axis 发生变化,
当一个系列被删除并且图表是 re-drawn.
我们可以使用图表方法 getVAxisValue 从初始绘制中确定 y-axis 的最小值和最大值。

var chartArea = MSLChart.getChart().getChartLayoutInterface().getChartAreaBoundingBox();
var vAxisTop = MSLChart.getChart().getChartLayoutInterface().getVAxisValue(chartArea.top);
var vAxisBtm = MSLChart.getChart().getChartLayoutInterface().getVAxisValue(chartArea.top + chartArea.height);

MSLChart.setOption('vAxis.viewWindow.max', vAxisTop);
MSLChart.setOption('vAxis.viewWindow.min', vAxisBtm);

以下是更新后的代码...

google.charts.load('current', {packages: ['controls']}).then(initialize);

function initialize() {
  var query = new google.visualization.Query('https://docs.google.com/spreadsheets/d/1001YnF8LCwKyzpS4pgmZnwFVigL-LlnqwWn6xjnso2k/edit#gid=0&range=A:BT');
      query.send(drawDashboard);
}

function drawDashboard(response) {

    var data = response.getDataTable();
    //Asign units of 'mm' to data.
    var formatMS = new google.visualization.NumberFormat({pattern: '# mm'});

    // format data into mm.
    for (var colIndex = 1; colIndex < data.getNumberOfColumns(); colIndex++) {formatMS.format(data, colIndex);}
    var dataView = new google.visualization.DataView(data);
    dataView.setColumns([0,1,2,{sourceColumn: 3, role: 'interval'}, {sourceColumn: 4, role: 'interval'}, 5,{sourceColumn: 6, 'type': 'string', role: 'tooltip', 'p': {'html': true}},7,8,9,10,11,12,13,14,15,{sourceColumn: 16, role: 'interval'}, {sourceColumn: 17, role: 'interval'}, 18,{sourceColumn: 19, 'type': 'string', role: 'tooltip', 'p': {'html': true}},20,21,22,23,24,25,26,27,28,{sourceColumn: 29, role: 'interval'}, {sourceColumn: 30, role: 'interval'},31,{sourceColumn: 32, 'type': 'string', role: 'tooltip', 'p': {'html': true}},33,34,35,36,37,38,39,40,41,{sourceColumn: 42, role: 'interval'}, {sourceColumn: 43, role: 'interval'}, 44,{sourceColumn: 45, 'type': 'string', role: 'tooltip', 'p': {'html': true}},46,47,48,49,50,51,52,53,54,{sourceColumn: 55, role: 'interval'}, {sourceColumn: 56, role: 'interval'}, 57,{sourceColumn: 58, 'type': 'string', role: 'tooltip', 'p': {'html': true}},59,60,61,62,63,64,65,66,67,68,69,70,71]);
    var viewColumns = [0,7,20,33,46,59,66,67,68,69,70,71];

    var YearPicker = new google.visualization.ControlWrapper({
      controlType: 'NumberRangeFilter',
      containerId: 'filter_div',
      options: {
        maxValue: 2150,
        minValue: 1891,
        filterColumnLabel: 'Year',
        ui: {
          cssClass: 'filter-date',
          format: {pattern: '0000'},
          labelStacking: 'vertical',
          allowTyping: true,
          allowMultiple: false
        }
      },
      state: {lowValue: 1891, highValue: 2150},
    });

    google.visualization.events.addListener(YearPicker, 'statechange', function () {
      var state = YearPicker.getState();
      state.lowValue = Math.min(2021, state.lowValue);
      YearPicker.setState({
        lowValue: state.lowValue,
        highValue: state.highValue
      });
      YearPicker.draw();
    });

    var series = {
      0: {color:'navy', visibleInLegend: true}, //Auckland
      1: {color:'green', visibleInLegend: true }, //Taranaki
      2: {color:'gold', visibleInLegend: true}, //Wellington
      3: {color:'red', visibleInLegend: true}, //Lyttelton
      4: {color:'DeepSkyBlue', visibleInLegend: true}, //Dunedin
      5: {color:'#47d045', visibleInLegend: true}, //NZ RCP2.6 M
      6: {color:'#0e038d', visibleInLegend: true}, //NZ RCP4.5 M
      7: {color:'#b8bb62', visibleInLegend: true}, //NZ RCP8.5 M
      8: {color:'#b22123', visibleInLegend: true}, //NZ RCP8.5 H
      9: {color:'blue', visibleInLegend: true}, //NZ Mean
      10: {color:'blue', visibleInLegend: false}, //NZ Mean
    };

    // save series colors
    var seriesColors = {};
    for (var column in series) {
      if (series.hasOwnProperty(column)) {
        seriesColors[column] = series[column].color;
      }
    }


    var MSLChart = new google.visualization.ChartWrapper({
      chartType: 'LineChart',
      containerId: 'chart_div',
      dataTable: dataView,
      options: {
        fontSize: '20',
        title: 'NZ Annual Relative Mean Sea Level Summary',
        hAxis: {title: 'Year', format: '0000'},
        vAxis: {title: 'Height above 1986-2005 IPCC Baseline (mm)', format:'###0'},
        height: 600,
        chartArea: {height: '81%', width: '85%', left: 100},
        legend: {position: 'top', maxLines: 5, alignment: 'start', textStyle: {fontSize: 9}},
        colors: ['blue'],
        tooltip: {
          isHtml: true
        },
        trendlines: {
          9: {
            type: 'linear',
            color: 'black',
            visibleInLegend: true,
            showR2: true,
          },
          10: {
            type: 'polynomial',
            color: 'purple',
            degree: 2,
            visibleInLegend: true,
            showR2: true,
          },
        },
        series: series,
        intervals: { 'style':'bars','color': '#6292dc' },
        interpolateNulls: 'True',
      },
      view: {columns: viewColumns}
    });

    //Code taken from above solution begins here:
    var columns = [];
    for (var i = 0; i < dataView.getNumberOfColumns(); i++) {
      columns.push(i);
    }
    google.visualization.events.addListener(MSLChart, 'select', function () {
      var chartArea = MSLChart.getChart().getChartLayoutInterface().getChartAreaBoundingBox();
      var vAxisTop = MSLChart.getChart().getChartLayoutInterface().getVAxisValue(chartArea.top);
      var vAxisBtm = MSLChart.getChart().getChartLayoutInterface().getVAxisValue(chartArea.top + chartArea.height);

      var sel = MSLChart.getChart().getSelection();

      // if selection length is 0, we deselected an element
      if (sel.length > 0) {
         // if row is undefined, we clicked on the legend
         if ((sel[0].row === null) && (sel[0].column > 0)) {
             // get actual column number from view
             var col = viewColumns[sel[0].column];
             if (columns[col] == col) {
                // hide the data series
                columns[col] = {
                   label: dataView.getColumnLabel(col),
                   type: dataView.getColumnType(col),
                   calc: function () {
                      return null;
                   }
                };

                // grey out the legend entry
                series[sel[0].column - 1].color = '#CCCCCC';
            } else {
                // show the data series
                columns[col] = col;
                series[sel[0].column - 1].color = seriesColors[sel[0].column - 1];
            }

            // set new view columns
            var view = new google.visualization.DataView(dataView);
            view.setColumns(columns);
            MSLChart.setDataTable(view);

            // prevent y-axis from changing when series is removed
            MSLChart.setOption('series', series);
            MSLChart.setOption('vAxis.viewWindow.max', vAxisTop);
            MSLChart.setOption('vAxis.viewWindow.min', vAxisBtm);

            // re-draw chart
            MSLChart.draw();
         }
      }
    });

    var dashboard = new google.visualization.Dashboard(document.getElementById('dashboard_div')).bind(YearPicker, MSLChart).draw(dataView);
}