Chart.js如何对数据集图例分组,实现单个开关控制多个数据集?
Chart.js 按数据集标签分组控制显隐实现方案
需求说明
需要将6个不同的数据集按标签分组,实现单个开关即可控制所有标签为-15、15、25的同类数据集的显隐,效果参考下图:
实现思路
Chart.js原生没有直接提供分组图例的配置,我们可以通过自定义外部图例+官方提供的显隐接口实现需求:
- 关闭图表自带的默认图例
- 手动编写HTML结构作为自定义图例
- 绑定图例点击事件,批量修改对应标签所有数据集的显隐状态,最后刷新图表即可
完整实现代码
HTML 部分
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.2.1/chart.min.js"></script> <!-- 自定义图例区域 --> <div id="custom-legend" style="margin-bottom: 10px;"> <span class="legend-item" data-label="-15" style="margin-right: 20px;cursor: pointer;"> <span style="display: inline-block;width: 12px;height: 2px;background: red;margin-right: 4px;"></span> -15 </span> <span class="legend-item" data-label="15" style="margin-right: 20px;cursor: pointer;"> <span style="display: inline-block;width: 12px;height: 2px;background: blue;margin-right: 4px;"></span> 15 </span> <span class="legend-item" data-label="25" style="cursor: pointer;"> <span style="display: inline-block;width: 12px;height: 2px;background: yellow;margin-right: 4px;"></span> 25 </span> </div> <canvas id="elm-chart" width="640" height="480"></canvas>
JS 部分
var labels = []; for (let index = 0; index < 12; index++) { labels.push(index); } let myLineChart = null; window.onload = function () { var canvas = document.getElementById('elm-chart'), ctx = canvas.getContext('2d'); myLineChart = new Chart(ctx, { type: 'line', data: { labels: labels, datasets: [ { label: '-15', data: [ {x: 0,y: 10,},{x: 1,y: 20,},], borderColor: 'red', }, { label: '15', data: [ {x: 1,y: 20,},{x: 2,y: 30,},], borderColor: 'blue', }, { label: '25', data: [ {x: 2,y: 30,},{x: 3,y: 35,},], borderColor: 'yellow', }, { label: '-15', data: [ {x: 6,y: -10,},{x: 7,y: -20,},], borderColor: 'red', }, { label: '15', data: [ {x: 7,y: -20,},{x: 8,y: -30,},], borderColor: 'blue', }, { label: '25', data: [ {x: 8,y: -30,},{x: 9,y: -35,},], borderColor: 'yellow', }, ], }, options: { responsive: true, plugins: { // 关闭默认图例 legend: { display: false } }, scales: { x: { type: 'linear', suggestedMin: labels.reduce((pv, cv) => Math.min(pv, cv)), suggestedMax: labels.reduce((pv, cv) => Math.max(pv, cv)), ticks: { stepSize: 30, }, }, }, } }); // 绑定自定义图例点击事件 document.querySelectorAll('.legend-item').forEach(item => { item.addEventListener('click', function() { const targetLabel = this.dataset.label; // 遍历所有数据集获取当前分组的显隐状态,取第一个作为切换基准 const currentVisible = myLineChart.data.datasets.find(d => d.label === targetLabel).hidden !== true; // 批量修改同标签所有数据集的显隐 myLineChart.data.datasets.forEach((dataset, index) => { if(dataset.label === targetLabel) { myLineChart.setDatasetVisibility(index, !currentVisible); // 同步修改样式,选中状态加删除线 this.style.textDecoration = !currentVisible ? 'none' : 'line-through'; } }); // 更新图表 myLineChart.update(); }) }) }
功能说明
- 点击对应标签的图例就会同时隐藏/展示所有相同标签的数据集
- 图例点击后会增加删除线样式标识当前处于隐藏状态,和原生图例操作逻辑一致
内容的提问来源于stack exchange,提问作者Marcel
相关产品推荐
相关产品推荐

