【问题标题】:Chart.js change legend toggle behaviourChart.js 更改图例切换行为
【发布时间】:2017-03-02 12:26:16
【问题描述】:

我有一个来自 chart.js 的雷达图。目前,它加载所有运行良好的数据,并且支持图例通过单击图例标签来关闭与图例关联的数据。我希望能够单击图例标签,然后将所有其他标签关​​闭,并可能引入“全部”选项?这对 chart.js 可行吗?

这是我的图表现在的样子:

var chartata = { 
labels: [ 
"Strategic Development and Ownership", 
"Driving change through others", 
"Exec Disposition", 
"Commercial Acumen", 
"Develops High Performance Teams", 
"Innovation and risk taking", 
"Global Leadership", 
"Industry Leader" 
]}; 

var ctx = $("#allRadarData"); 

var config = { 
    type: 'radar', 
    data: chartata,     
    animationEasing: 'linear',
        options: {           
         legend: {
            fontSize: 10,
            display: true,
            itemWidth: 150,
            position: 'bottom',
            fullWidth: true,
            labels: {
                fontColor: 'rgb(0,0,0)',
                boxWidth: 10,
                padding: 20
            },
        },
         tooltips: {
            enabled: true
        },
        scale: {
            ticks: {
                fontSize: 15,
                beginAtZero: true,
                stepSize: 1,
                max: 5
            }
        } 

    },
}, 

LineGraph = new Chart(ctx, config); 

var colorArray = [

    ["#f44336", false],
    ["#E91E63", false],
    ["#9C27B0", false],
    ["#673AB7", false],
    ['#3F51B5', false],
    ["#607D8B", false]
];


for (var i in data) { 
    tmpscore=[]; 
    tmpscore.push(data[i].score1); 
    tmpscore.push(data[i].score2); 
    tmpscore.push(data[i].score3); 
    tmpscore.push(data[i].score4); 
    tmpscore.push(data[i].score5); 
    tmpscore.push(data[i].score6); 
    tmpscore.push(data[i].score7); 
    tmpscore.push(data[i].score8); 

    var color, done = false;
    while (!done) {
        var test = colorArray[parseInt(Math.random() * 10)];
        if (!test[1]) {
            color = test[0];
            colorArray[colorArray.indexOf(test)][1] = true;
            done = !done;
        }
    }


newDataset = { 
    label: data[i].firstName+' '+data[i].lastName, 
     borderColor: color,
    backgroundColor: "rgba(0,0,0,0)", 
    data: tmpscore, 
}; 

config.data.datasets.push(newDataset); 

} 

LineGraph.update(); 
},  
}); 

});

【问题讨论】:

  • 显示所有功能?请给出显示所有标签的想法

标签: javascript jquery chart.js


【解决方案1】:

要反转图例标签的点击行为,您可以使用图例onClick 选项来实现新的点击逻辑。下面是一个示例,它将为您提供所需的行为。请注意,在此实现中,如果您单击一个已经隐藏的标签,它将取消隐藏它,并隐藏所有其他标签。

function(e, legendItem) {
  var index = legendItem.datasetIndex;
  var ci = this.chart;
  var alreadyHidden = (ci.getDatasetMeta(index).hidden === null) ? false : ci.getDatasetMeta(index).hidden;

  ci.data.datasets.forEach(function(e, i) {
    var meta = ci.getDatasetMeta(i);

    if (i !== index) {
      if (!alreadyHidden) {
        meta.hidden = meta.hidden === null ? !meta.hidden : null;
      } else if (meta.hidden === null) {
        meta.hidden = true;
      }
    } else if (i === index) {
      meta.hidden = null;
    }
  });

  ci.update();
};

这里也是working example

但是,如果您想要一个更复杂的逻辑,在至少一个其他标签当前可见时取消隐藏当前隐藏的标签,那么您可以使用以下实现。

function(e, legendItem) {
  var index = legendItem.datasetIndex;
  var ci = this.chart;
  var alreadyHidden = (ci.getDatasetMeta(index).hidden === null) ? false : ci.getDatasetMeta(index).hidden;       
  var anyOthersAlreadyHidden = false;
  var allOthersHidden = true;

  // figure out the current state of the labels
  ci.data.datasets.forEach(function(e, i) {
    var meta = ci.getDatasetMeta(i);

    if (i !== index) {
      if (meta.hidden) {
        anyOthersAlreadyHidden = true;
      } else {
        allOthersHidden = false;
      }
    }
  });

  // if the label we clicked is already hidden 
  // then we now want to unhide (with any others already unhidden)
  if (alreadyHidden) {
    ci.getDatasetMeta(index).hidden = null;
  } else { 
    // otherwise, lets figure out how to toggle visibility based upon the current state
    ci.data.datasets.forEach(function(e, i) {
      var meta = ci.getDatasetMeta(i);

      if (i !== index) {
        // handles logic when we click on visible hidden label and there is currently at least
        // one other label that is visible and at least one other label already hidden
        // (we want to keep those already hidden still hidden)
        if (anyOthersAlreadyHidden && !allOthersHidden) {
          meta.hidden = true;
        } else {
          // toggle visibility
          meta.hidden = meta.hidden === null ? !meta.hidden : null;
        }
      } else {
        meta.hidden = null;
      }
    });
  }

  ci.update();
}

这里还有一个 working example 用于此替代实现。

要在您的特定代码中使用它,只需使用 onClick 属性将其放置在图表的图例配置中。

var config = { 
  type: 'radar', 
  data: chartata,   
  animationEasing: 'linear',
    options: {       
     legend: {
      fontSize: 10,
      display: true,
      itemWidth: 150,
      position: 'bottom',
      fullWidth: true,
      labels: {
        fontColor: 'rgb(0,0,0)',
        boxWidth: 10,
        padding: 20
      },
      onClick: function(e, legendItem) {
        var index = legendItem.datasetIndex;
        var ci = this.chart;
        var alreadyHidden = (ci.getDatasetMeta(index).hidden === null) ? false : ci.getDatasetMeta(index).hidden;

        ci.data.datasets.forEach(function(e, i) {
          var meta = ci.getDatasetMeta(i);

          if (i !== index) {
            if (!alreadyHidden) {
              meta.hidden = meta.hidden === null ? !meta.hidden : null;
            } else if (meta.hidden === null) {
              meta.hidden = true;
            }
          } else if (i === index) {
            meta.hidden = null;
          }
        });

        ci.update();
      },
    },
     tooltips: {
      enabled: true
    },
    scale: {
      ticks: {
        fontSize: 15,
        beginAtZero: true,
        stepSize: 1,
        max: 5
      }
    }
  },
}, 

不清楚您希望“全部”选项具有什么行为,但您可能能够使用 legend.labels.generateLabels 选项欺骗 Chart.js 添加“全部”标签(你必须修改上面的onClick 逻辑来处理这个想法。

但是,我认为更好的解决方案是在 chart.js 画布之外实现您自己的链接或按钮,以显示/隐藏所有数据集。查看Chart.js radar sample page,了解它们如何将按钮与图表操作绑定。

【讨论】:

  • 首先感谢您提供详细解释的答案。我可以看到你理解我的需求。从这个例子中我唯一需要的是当你选择一个标签时,它会删除所有其他标签,只显示所选标签,如果你继续点击另一个标签,它会添加它而不是删除原来点击的标签并替换它点击新的。我对唱 chart.js 还很陌生,所以有点混乱。
  • 啊,好吧...我不知道你想怎么处理。稍后我会在使用计算机时更新我的​​答案。
  • 非常感谢。你能说明一下我上面的代码吗?
  • 这将与我在问题中提供的代码一起使用?
  • 是的,只需使用 onClick 属性将其放入图表的图例配置中。我会在我的回答中更新这个
【解决方案2】:

请尝试此代码用于单个数据集的饼图,以切换 chart.js 饼图的行为。

onClick:function(e, legendItem){
                var index = legendItem.index;
                var ci = this.chart;
                var meta = ci.getDatasetMeta(0);
                var CurrentalreadyHidden = (meta.data[index].hidden==null) ? false : (meta.data[index].hidden);
                var allShown=true;
                $.each(meta.data,function(ind0,val0){
                    if(meta.data[ind0].hidden){
                        allShown=false;
                        return false; 
                    }else{
                        allShown=true;
                    }
                });
                if(allShown){
                    $.each(meta.data,function(ind,val){
                        if(meta.data[ind]._index===index){
                            meta.data[ind].hidden=false;
                        }else{
                            meta.data[ind].hidden=true;
                        }
                    });
                }else{
                    if(CurrentalreadyHidden){
                        $.each(meta.data,function(ind,val){
                            if(meta.data[ind]._index===index){
                                meta.data[ind].hidden=false;
                            }else{
                                meta.data[ind].hidden=true;
                            }
                        });
                    }else{
                        $.each(meta.data,function(ind,val){
                            meta.data[ind].hidden=false;
                        }); 
                     }
                 }
                ci.update();

            }

【讨论】:

    【解决方案3】:

    legend.onClick 解决方案的更短代码

    // this.chart.options
    legend: {
        onClick: (_, item: LegendItem) => {
            if (!this.chart) {
                return;
            }
            const currentHidden: boolean = this.chart.data.datasets[item.datasetIndex].hidden ?? false;
            if (currentHidden) {
                this.chart.data.datasets.forEach(ds => {
                    ds.hidden = true;
                });
                this.chart.data.datasets[item.datasetIndex].hidden = false;
            } else {
                this.chart.data.datasets.forEach(ds => {
                    ds.hidden = currentHidden == (ds.hidden ?? false);
                });
                this.chart.data.datasets[item.datasetIndex].hidden = false;
            }
            this.chart?.update();
        },
    },
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-23
      相关资源
      最近更新 更多