如何使用 Highcharts.js 动态生成堆叠柱状图

2次阅读

如何使用 Highcharts.js 动态生成堆叠柱状图

本文详解如何将数据库返回的透视表格式数据(如按月份分组、多厂商计数)转换为 highcharts 叠柱状图,涵盖数据结构映射、系列配置、堆叠启用及完整初始化代码。

在使用 highcharts 构建堆叠柱状图(Stacked column Chart)时,关键在于将“宽格式”(wide-format)的透视数据正确转换为 Highcharts 所需的 series 数组结构。你从数据库通过 PIVOT 查询获取的数据形如:

const rawData = [   { MonthsName: 'April', AUTOLIV: 0, Continental: 0, 'Herman miller': 0, REL: 0 },   { MonthsName: 'July',  AUTOLIV: 0, Continental: 4, 'Herman miller': 0, REL: 0 },   { MonthsName: 'June',  AUTOLIV: 1, Continental: 0, 'Herman miller': 0, REL: 0 },   { MonthsName: 'May',   AUTOLIV: 1, Continental: 0, 'Herman miller': 1, REL: 1 } ];

该结构中,MonthsName 是分类维度(X 轴),其余字段(如 AUTOLIV、Continental 等)代表不同图例项的数值——这正是堆叠柱状图所需的「每个系列对应一列」模式。

✅ 正确的数据转换逻辑

Highcharts 的 series 要求每个对象包含 name(图例名称)和 data 数组,其中 data 可为数值数组(隐式按索引对齐 X 轴),但为确保月份顺序可控且语义清晰,推荐显式使用对象形式 { name: ‘April’, y: 0 }

以下转换函数可稳健处理任意数量的厂商列(无需硬编码列名):

function transformToStackedSeries(data, xKey = 'MonthsName') {   const seriesMap = {};    data.forEach((row, rowIndex) => {     Object.keys(row).forEach(key => {       if (key === xKey) return; // 跳过 X 轴字段        // 初始化系列(仅首次出现时)       if (!seriesMap[key]) {         seriesMap[key] = { name: key, data: [] };       }        // 推入 { name: 'April', y: 0 } 格式数据点       seriesMap[key].data.push({         name: row[xKey],         y: number(row[key]) || 0 // 安全转数字,容错 null/undefined       });     });   });    return Object.values(seriesMap); }  // 使用示例 const chartSeries = transformToStackedSeries(rawData);

? Highcharts 初始化配置要点

堆叠功能需在 plotOptions.column.stacking 中显式启用(值为 ‘normal’),同时建议设置 xAxis.type = ‘category’ 以支持字符串类目,并启用 dataLabels 提升可读性:

Highcharts.chart('container', {   chart: {     type: 'column',     backgroundColor: '#ffffff'   },   title: {     text: '各厂商月度订单数量(堆叠统计)'   },   xAxis: {     type: 'category',     title: { text: '月份' }   },   yAxis: {     min: 0,     title: { text: '数量' }   },   plotOptions: {     column: {       stacking: 'normal', // ? 关键:启用堆叠       dataLabels: {         enabled: true,         formatter() {           return this.y > 0 ? this.y : ''; // 隐藏 0 值标签         }       }     }   },   series: chartSeries,   tooltip: {     shared: true,     valueSuffix: ' 件'   } });

⚠️ 注意事项与最佳实践

  • 月份顺序问题:原始数据中 MonthsName 顺序可能非自然月序(如 ‘April’, ‘July’, ‘June’, ‘May’)。若需严格按日历排序,应在 transformToStackedSeries 前对 rawData 按月份做预排序(例如借助 new date(month + ‘ 1, 2024’).getMonth() 映射)。
  • 空值/非法值处理:示例中使用 Number(row[key]) || 0 防止 NaN 导致图表渲染失败;生产环境建议增加类型校验。
  • 动态更新:如需后续刷新数据,应调用 chart.update({ series: newSeries }) 或 chart.series[i].setData(newData),避免重复初始化。
  • 性能优化:当数据量较大(>1000 条)时,可考虑关闭动画 chart: { animation: false } 或启用 boost 模块。

通过以上结构化转换与配置,即可将任意 PIVOT 结果无缝驱动为专业、交互式的堆叠柱状图,真正实现「数据即图表」的敏捷可视化。

text=ZqhQzanResources