如何基于现有数据用C3.js生成指定样式的班次条形图?
使用C3.js实现目标班次堆叠柱状图
看了你提供的需求、数据和目标样式,你想要的应该是按日期分组的堆叠柱状图——每个日期下堆叠展示itemA、itemB、itemC的数量,同时附带班次时间信息。之前的示例可能没针对你的数据结构做适配,所以效果达不到预期,我来给你整理数据调整建议和完整的实现代码。
一、数据结构调整建议
你当前的dataItems结构里,每个日期的班次信息和物品数量是分散存储的,C3.js无法直接解析这种嵌套格式。我们需要把它转换成C3兼容的扁平结构:
- 提取所有日期作为x轴的分类标签
- 把每个物品的数量按日期整理成独立的数值数组
- 班次的起止时间可以作为元数据,用于tooltip或x轴标注
手动转换后的示例结构
// 转换后的C3兼容数据 var transformedData = { x: 'dates', columns: [ ['dates', '2017/02/04', '2017/04/04', '2017/05/04'], ['itemA', 600, 720, 450], ['itemB', 400, 1000, 800], ['itemC', 500, 850, 1000] ], // 存储班次时间元数据,用于tooltip展示 shiftTimes: { '2017/02/04': '05:30:00 - 05:30:00', '2017/04/04': '05:30:00 - 05:30:00', '2017/05/04': '05:30:00 - 05:30:00' } };
自动转换原始数据的函数
如果后续会新增数据,推荐用代码自动转换,避免手动整理:
// 从原始dataItems转换为C3格式的工具函数 function transformRawData(rawData) { const dates = []; const itemA = ['itemA']; const itemB = ['itemB']; const itemC = ['itemC']; const shiftTimes = {}; rawData.forEach(dateItem => { dates.push(dateItem.title); // 提取当前日期的班次时间(假设每个日期只有一个班次) const targetShift = dateItem.shifts[0]; shiftTimes[dateItem.title] = `${targetShift.startTime} - ${targetShift.endTime}`; // 提取每个物品的数量 targetShift.items.forEach(item => { if (item.quantities.itemA !== undefined) { itemA.push(item.quantities.itemA); } else if (item.quantities.itemB !== undefined) { itemB.push(item.quantities.itemB); } else if (item.quantities.itemC !== undefined) { itemC.push(item.quantities.itemC); } }); }); return { x: 'dates', columns: [['dates', ...dates], itemA, itemB, itemC], shiftTimes }; } // 调用函数转换原始数据 var c3Data = transformRawData(dataItems);
二、C3.js完整实现示例
基于转换后的数据,我们可以配置出匹配目标样式的堆叠柱状图:
// 初始化C3图表 var chart = c3.generate({ bindto: '#chart', // 绑定页面上的DOM元素ID data: { x: 'dates', columns: c3Data.columns, type: 'bar', groups: [['itemA', 'itemB', 'itemC']], // 设置堆叠分组 colors: { itemA: '#3366CC', itemB: '#DC3912', itemC: '#FF9900' }, tooltip: { // 自定义tooltip,添加班次时间显示 contents: function(d, defaultTitleFormat, defaultValueFormat, color) { const currentDate = d[0].x; const shiftTime = c3Data.shiftTimes[currentDate]; let tooltipHtml = `<table class="c3-tooltip"> <thead> <tr><th colspan="2">${currentDate}</th></tr> <tr><th colspan="2">班次时间:${shiftTime}</th></tr> </thead> <tbody>`; d.forEach(item => { tooltipHtml += `<tr> <td style="color:${color(item.id)}">${item.id}</td> <td class="value">${item.value}</td> </tr>`; }); tooltipHtml += '</tbody></table>'; return tooltipHtml; } } }, axis: { x: { type: 'category', tick: { rotate: 45, // 旋转日期标签避免重叠 multiline: false }, label: { text: '日期', position: 'outer-center' } }, y: { label: { text: '数量', position: 'outer-middle' } } }, legend: { position: 'right' // 图例放在右侧 }, bar: { width: { ratio: 0.6 // 调整柱子宽度,让布局更宽松 } } });
三、关键配置说明
- 堆叠效果:通过
data.groups将三个物品设置为同一组,实现柱状堆叠 - 自定义Tooltip:新增了班次时间的展示,让图表信息更完整
- 样式优化:设置了柱子颜色、宽度,旋转x轴标签,让视觉效果更接近目标样式
- 动态适配:自动转换函数支持后续新增数据,无需手动修改图表配置
内容的提问来源于stack exchange,提问作者n2lose
相关产品推荐
相关产品推荐

