如何使用带有饼图的 Google 图表(可视化)过滤器保持一致的颜色?

How to maintain consistent colors using a Google charts (visualisation) filter with a pie chart?

我想要一个像 this example 这样带有饼图的仪表板,但要保持颜色一致。例如。在示例中,如果将过滤器从 None 设置为女性,Margreth 的颜色会从粉红色变为橙色。

不幸的是,{ role: 'style' } 选项不适用于饼图。相反,必须在选项中提供颜色列表。使用过滤器时,将使用列表中的第一个可用颜色。因此,与 this (unfortenately) accepted answer 不同,提供大小等于未过滤数据集总数的颜色列表无济于事。

相反,我认为需要定义一个函数来动态创建与过滤数据对齐的颜色列表,例如:

function getColors () {
        // build colors array
        var colors = [];
        for (var i = 0; i < data.getNumberOfRows(); i++) {
            colors.push(data.getValue(i, 2)); // color is in the 3nd column of the datatable
        }
        return colors; }

'options':{
          colors: getColors()  },

仅供参考 jsfiddle

但是,如果我这样做,getColors return 是完整数据集的颜色。

=> 我该怎么做?:

  1. 只有 return 过滤后的行,因此只有颜色列表可以显示?我注意到一个方法“getFilteredRows”,但这似乎更像是一种构建您自己的过滤器的方法,我不明白。
  2. 确保每次更改滤镜时更新并应用颜色列表?上面的 fiddle 是在单击按钮时完成的。我不知道如何使用 google 图表过滤器来做到这一点。我尝试使用过滤器、select 或仪表板等值准备好 addListener(见下文)。但是 none 这些工作。

仅供参考,我的仪表板代码:

HTML:

<div id = "dashboard_TK_stemmen">
<div id="filter_TK_stemmen"></div>
<p id = "pie_TK_stemmen"></p>
</div>

JS:

google.charts.setOnLoadCallback(Dashboard);
function Dashboard()  {
      var data = google.visualization.arrayToDataTable([ ['Partij', 'Aantal', { role: 'style' }, 'Datum'], ['PvdA', 20105, '#E30613', '20 maart 2019'], ['VVD', 9919, '#F47621', '20 maart 2019'], ['CDA', 6480, '#007B5F', '20 maart 2019'], ['PvdA', 13303, '#E30613', '18 maart 2015'], ['VVD', 8096, '#F47621', '18 maart 2015'], ['CDA', 5896, '#007B5F', '18 maart 2015'] ]);
      var dashboard = new google.visualization.Dashboard(document.getElementById('dashboard_TK_stemmen'));
      var filter = new google.visualization.ControlWrapper({
        'controlType': 'CategoryFilter',
        'containerId': 'filter_TK_stemmen',
        'options': {
        'filterColumnLabel': 'Datum',
        'ui': {'caption': 'Kies een verkiezingsuitslag', 'label': 'Uitslag van: ', 'allowNone': false, 'allowMultiple': false,
         'sortValues':false,'allowTyping':false} } });
     function getColors () {
        // build colors array
        var colors = [];
        for (var i = 0; i < data.getNumberOfRows(); i++) {
            colors.push(data.getValue(i, 2));
        }
        return colors; }
      var pie = new google.visualization.ChartWrapper({
        'chartType': 'PieChart',
        'containerId': 'pie_TK_stemmen',
        'options':{
          pieHole: 0.3,
          chartArea: {bottom: 0, width: '100%', height: '85%'},
          hAxis: {textPosition: 'in'}, vAxis: {textPosition: 'in'},
          legend: {position: 'top',  maxLines: 3},
          colors: getColors()  },
          'view': {'columns': [0, 1]}
        });
  dashboard.bind(filter, pie);
  dashboard.draw(data); 
  google.visualization.events.addListener(pie, 'ready', function() {
  pie.setOption('colors', getColors());
  });     
      }; 

我们可以独立绘制过滤器和饼图,
而不是使用仪表板。

我们使用过滤器上的 'ready''statechange' 事件来知道何时绘制饼图。

当这些事件中的任何一个被触发时,我们都会从过滤器中获取选定的值。

var filterValue = filter.getState().selectedValues[0];

由于您在过滤器上设置了以下选项,
我们可以确定 selectedValues 数组中始终只有一个值...

    allowNone: false,
    allowMultiple: false,

使用过滤器的值,我们可以使用 getFilteredRows

找到符合过滤器的行
var visibleRows = data.getFilteredRows([{
  column: 3,
  value: filterValue
}]);

然后我们可以使用可见行在原始数据上构建数据视图 table。

var dataView = new google.visualization.DataView(data);
dataView.setRows(visibleRows);

然后我们可以从数据视图中的样式列中提取颜色。

var colors = [];
for (var i = 0; i < dataView.getNumberOfRows(); i++) {
  colors.push(dataView.getValue(i, 2));
}

并将颜色和数据视图应用于饼图并绘制...

pie.setDataTable(dataView);
pie.setOption('colors', colors);
pie.draw();

请参阅以下工作片段...

看起来每个过滤器值都有相同的颜色集,
所以出于示例目的,我更改了第二组颜色...

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

function Dashboard()  {
  // build data table
  var data = google.visualization.arrayToDataTable([
    ['Partij', 'Aantal', { role: 'style' }, 'Datum'],
    ['PvdA', 20105, '#E30613', '20 maart 2019'],
    ['VVD', 9919, '#F47621', '20 maart 2019'],
    ['CDA', 6480, '#007B5F', '20 maart 2019'],
    ['PvdA', 13303, 'cyan', '18 maart 2015'],
    ['VVD', 8096, 'magenta', '18 maart 2015'],
    ['CDA', 5896, 'yellow', '18 maart 2015']
  ]);

  // build filter
  var filter = new google.visualization.ControlWrapper({
    controlType: 'CategoryFilter',
    containerId: 'filter_TK_stemmen',
    dataTable: data,  // <-- assign data table to filter
    options: {
      filterColumnLabel: 'Datum',
      ui: {
        caption: 'Kies een verkiezingsuitslag',
        label: 'Uitslag van: ',
        allowNone: false,
        allowMultiple: false,
        sortValues: false,
        allowTyping: false
      }
    }
  });

  // build pie chart
  var pie = new google.visualization.ChartWrapper({
    chartType: 'PieChart',
    containerId: 'pie_TK_stemmen',
    options: {
      pieHole: 0.3,
      chartArea: {bottom: 0, width: '100%', height: '85%'},
      legend: {position: 'top',  maxLines: 3},
    },
    view: {
      columns: [0, 1]
    }
  });

  // assign filter event listeners
  google.visualization.events.addListener(filter, 'statechange', drawPie);
  google.visualization.events.addListener(filter, 'ready', drawPie);

  // draw filter
  filter.draw();

  // draw pie chart, called from filter events
  function drawPie() {
    // get selected filter value
    var filterValue = filter.getState().selectedValues[0];

    // get visible rows for filter value
    var visibleRows = data.getFilteredRows([{
      column: 3,
      value: filterValue
    }]);

    // build data view over original data table
    var dataView = new google.visualization.DataView(data);
    dataView.setRows(visibleRows);

    // get colors from style column in data view
    var colors = [];
    for (var i = 0; i < dataView.getNumberOfRows(); i++) {
      colors.push(dataView.getValue(i, 2));
    }

    // assign data view, colors, and draw pie chart
    pie.setDataTable(dataView);
    pie.setOption('colors', colors);
    pie.draw();
  }
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id = "dashboard_TK_stemmen">
  <div id="filter_TK_stemmen"></div>
  <p id = "pie_TK_stemmen"></p>
</div>