You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何缩小并固定Chart.js甜甜圈图表尺寸(含371个图例)

解决Chart.js甜甜圈图表固定尺寸及图例过多问题

一、固定甜甜圈图表尺寸

要让图表无论数据量多少都保持固定尺寸,核心是控制容器尺寸并配合Chart.js的响应式配置:

方法1:容器固定尺寸 + 禁用宽高比维护

给图表父容器设置固定宽高,同时开启响应式并关闭自动宽高比维护,让图表填满容器且不随数据变形:

<!-- 固定尺寸的图表容器 -->
<div id="chart-wrapper" style="width: 500px; height: 500px;">
  <canvas id="doughnut-chart"></canvas>
</div>
const chart = new Chart(document.getElementById('doughnut-chart'), {
  type: 'doughnut',
  data: { /* 你的数据集 */ },
  options: {
    responsive: true, // 让图表适配容器尺寸
    maintainAspectRatio: false, // 禁用自动宽高比,强制使用容器尺寸
    cutout: '70%' // 可选,调整甜甜圈空心占比
  }
});

方法2:直接指定Canvas原生尺寸

在<canvas>标签上定义固定宽高,同时关闭响应式,完全使用Canvas的原生尺寸:

<canvas id="doughnut-chart" width="500" height="500"></canvas>
const chart = new Chart(document.getElementById('doughnut-chart'), {
  type: 'doughnut',
  data: { /* 你的数据集 */ },
  options: {
    responsive: false // 关闭响应式,使用Canvas固定尺寸
  }
});

二、优化371个图例的显示问题

大量图例挤占空间是显示差的核心原因,推荐以下3种优化方案:

方案1:自定义滚动图例容器

隐藏Chart.js自带图例,将图例项渲染到带滚动条的独立容器中,分离图表与图例空间:

const chart = new Chart(document.getElementById('doughnut-chart'), {
  type: 'doughnut',
  data: {
    labels: [/* 371个标签 */],
    datasets: [{ data: [/* 对应数据 */] }]
  },
  options: {
    legend: { display: false }, // 隐藏默认图例
    // 保留图表区块点击交互
    onClick: (e, elements) => {
      if (elements.length) {
        const index = elements[0].index;
        // 可添加选中高亮等自定义逻辑
      }
    }
  }
});

// 手动生成滚动图例
const legendContainer = document.getElementById('legend-box');
chart.data.labels.forEach((label, index) => {
  const color = chart.data.datasets[0].backgroundColor[index];
  const legendItem = document.createElement('div');
  legendItem.style.display = 'flex';
  legendItem.style.alignItems = 'center';
  legendItem.style.padding = '2px 4px';
  
  // 颜色块
  const colorDot = document.createElement('span');
  colorDot.style.width = '12px';
  colorDot.style.height = '12px';
  colorDot.style.backgroundColor = color;
  colorDot.style.marginRight = '8px';
  
  // 标签文本
  const labelText = document.createElement('span');
  labelText.textContent = label;
  
  legendItem.appendChild(colorDot);
  legendItem.appendChild(labelText);
  legendContainer.appendChild(legendItem);
});

对应的HTML布局:

<div style="display: flex; gap: 16px;">
  <div id="chart-wrapper" style="width: 500px; height: 500px;">
    <canvas id="doughnut-chart"></canvas>
  </div>
  <div id="legend-box" style="width: 200px; height: 500px; overflow-y: auto;"></div>
</div>

方案2:合并小数据项为「其他」类别

把占比极低的项合并成一个类别,大幅减少图例数量:

const rawData = [/* 371个原始数据 */];
const rawLabels = [/* 371个原始标签 */];
const threshold = 0.5; // 占比低于0.5%的项合并

// 计算总数据量并筛选
const total = rawData.reduce((sum, val) => sum + val, 0);
let filteredData = [];
let filteredLabels = [];
let otherSum = 0;

rawData.forEach((val, index) => {
  const percentage = (val / total) * 100;
  if (percentage >= threshold) {
    filteredData.push(val);
    filteredLabels.push(rawLabels[index]);
  } else {
    otherSum += val;
  }
});

// 添加「其他」项
if (otherSum > 0) {
  filteredData.push(otherSum);
  filteredLabels.push('其他');
}

// 用处理后的数据初始化图表
const chart = new Chart(document.getElementById('doughnut-chart'), {
  type: 'doughnut',
  data: { labels: filteredLabels, datasets: [{ data: filteredData }] },
  options: { responsive: true, maintainAspectRatio: false }
});

方案3:使用图例插件增强功能

可以借助第三方插件(如chartjs-plugin-legend-paging)实现图例分页,或自己添加搜索框过滤图例项,进一步提升大量图例的可用性。

内容的提问来源于stack exchange,提问作者Mohsin Shaikh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 15:25:17