如何过滤堆积的条形图?

时间:2020-07-16 10:00:41

标签: bar-chart dc.js crossfilter stacked-chart

我发现了以下使用dc.js堆积条形图的示例: https://dc-js.github.io/dc.js/examples/stacked-bar.html

enter image description here 如果我单击一些(或几个)图例项,我希望图表

  • 仅显示相应的项目(例如红色和蓝色),并且

  • 调整总数以仅考虑所选项目

我已经设法在图例条目中添加一些点击事件:

chart.on('pretransition.hideshow', ()=> {
    chart.selectAll('.dc-legend-item')    
      .on('click', function (data, index, nodeList) {
        const stackName = data.name;
        if(data.hidden){
           chart.showStack(stackName);
        } else {
           chart.hideStack(stackName);
        }  
        dc.redrawAll();
      });
  });

这隐藏了一些堆栈,但是总和未按预期显示(相乘,显示了重叠的值)。

enter image description here

=>如何正确过滤数据?

我也尝试使用chart.filter(),但这似乎只能过滤x轴,而不能过滤堆栈。

当前,如果我将鼠标悬停在图例条目上,则该图表已经适应但未显示所需的行为。

1 个答案:

答案 0 :(得分:1)

感谢戈登,我找到了以下解决方案:

步骤1::为stack属性创建一个额外的维度:

const stackDimension = crossFilter.dimension(d => d.stackProperty);

步骤2:创建事件处理程序并在该维度上进行过滤:

  const selectedStackNames = [];

  const legendItemClickHandler = (data, index, nodeList) => {
   
    const stackName = data.name;       
    if(selectedStackNames.includes(stackName)){
       const index = selectedStackNames.indexOf(stackName);
       selectedStackNames.splice(index,1);          
    } else {
       selectedStackNames.push(stackName);          
    }

    if(selectedStackNames.length){
      stackDimension.filter((name)=>{
          return selectedStackNames.includes(name);
      });
    } else {
      stackDimension.filter(null);
    }  
    dc.redrawAll();
    
  };

  chart.on('pretransition.hideshow', ()=> {
    chart.selectAll('.dc-legend-item')
      .on('click', legendItemClickHandler);
  });

第3步:突出显示选定的图例项

 chart.on('pretransition.show', ()=> {
    chart.selectAll('.dc-legend-item')
      .on('click', legendItemClickHandler);

    const selectedStackNames = new Set(
      stackDimension.top(Infinity)
        .map(d=>d.stackProperty)
    );
    
    chart.selectAll('.dc-legend-item')
      .each((data, index, nodeList)=>{
        const node = nodeList[index];
        const colorRect = node.children[0];
        if(selectedStackNames.has(data.name)){
          colorRect.style.outline = "1px solid grey";
          colorRect.opacity="";
          data.hidden=false;
        } else {
          colorRect.style.outline = "";
          data.hidden=true;
          colorRect.opacity="0.3";
        }
      });
  });