基于数组创建Chart.js堆叠图表的技术咨询
基于每日奶瓶喂养数据构建Chart.js堆叠图表的问题解答
a. 当前数据格式是否正确?
严格来说,你的JSON数据格式虽然能被JavaScript解析,但并不规范,还会给后续处理添不少麻烦。核心问题有两个:
- 对象的键包含空格和冒号(比如
"2017-12-19 22:46:00"),虽然JS允许这种键,但不符合常规结构化数据的规范,读写和操作都很别扭; - 喂养记录和日期字段混在同一个对象里,没有统一的结构化嵌套,提取数据时需要额外做过滤处理。
更合理的格式应该把每个日期的喂养记录整理成嵌套数组/对象,比如:
const formattedData = [ { date: "2017-12-19", feedings: [ { time: "2017-12-19 22:46:00", amount: 341 } ] }, { date: "2017-12-30", feedings: [ { time: "2017-12-30 10:30:00", amount: 199 }, { time: "2017-12-30 14:00:00", amount: 142 }, { time: "2017-12-30 17:00:00", amount: 200 }, { time: "2017-12-30 19:18:00", amount: 199 } ] }, { date: "2017-12-31", feedings: [ { time: "2017-12-31 15:43:00", amount: 341 }, { time: "2017-12-31 16:30:00", amount: 199 } ] }, { date: "2018-01-01", feedings: [ { time: "2018-01-01 06:00:00", amount: 170 }, { time: "2018-01-01 09:00:00", amount: 170 }, { time: "2018-01-01 11:30:00", amount: 170 }, { time: "2018-01-01 19:09:00", amount: 199 } ] } ];
这种结构清晰直观,后续处理数据时会轻松很多。
b. 如何将该数据动态导入Chart.js?能否通过循环批量添加?
当然可以通过循环批量处理数据,不管你用原始格式还是上面推荐的结构化格式,都能实现动态生成堆叠图表。下面分两种情况说明:
情况1:基于你提供的原始数据处理
首先需要把原始数据转换成Chart.js堆叠柱状图需要的结构(x轴标签、多个堆叠数据集),代码示例如下:
// 你的原始数据 const rawData = [ {date: "2017-12-19", "2017-12-19 22:46:00": 341}, {date: "2017-12-30", "2017-12-30 10:30:00": 199, "2017-12-30 14:00:00": 142, "2017-12-30 19:18:00": 199, "2017-12-30 17:00:00": 200}, {date: "2017-12-31", "2017-12-31 15:43:00": 341, "2017-12-31 16:30:00": 199}, {date: "2018-01-01", "2018-01-01 19:09:00": 199, "2018-01-01 06:00:00": 170, "2018-01-01 11:30:00": 170, "2018-01-01 09:00:00": 170} ]; // 1. 提取x轴标签(所有日期) const labels = rawData.map(item => item.date); // 2. 整理每日喂养量,先按时间排序再提取数值 const dailyFeedings = rawData.map(item => { // 过滤掉date字段,提取所有喂养记录 const feedEntries = Object.entries(item).filter(([key]) => key !== 'date'); // 按时间排序(避免原始数据中时间顺序混乱) feedEntries.sort(([timeA], [timeB]) => new Date(timeA) - new Date(timeB)); // 只保留喂养量数值 return feedEntries.map(([_, amount]) => amount); }); // 3. 找出单日最多喂养次数,确定需要多少个数据集 const maxFeedCount = Math.max(...dailyFeedings.map(feeds => feeds.length)); // 4. 循环生成堆叠数据集 const datasets = []; for (let i = 0; i < maxFeedCount; i++) { datasets.push({ label: `第${i+1}次喂养`, // 对每个日期,取第i次喂养量,没有则填0 data: dailyFeedings.map(feeds => feeds[i] || 0), // 随机生成背景色(也可以自定义固定颜色) backgroundColor: `rgba(${Math.floor(Math.random()*255)}, ${Math.floor(Math.random()*255)}, ${Math.floor(Math.random()*255)}, 0.7)`, stack: 'feed-stack' // 关键:所有需要堆叠的数据集必须用同一个stack值 }); } // 5. 初始化Chart.js图表 const ctx = document.getElementById('feedingChart').getContext('2d'); new Chart(ctx, { type: 'bar', data: { labels: labels, datasets: datasets }, options: { responsive: true, scales: { x: { stacked: true }, // x轴堆叠 y: { stacked: true, // y轴堆叠 title: { display: true, text: '喂养量' } } } } });
情况2:基于推荐的结构化数据处理
如果用我之前推荐的formattedData格式,代码会更简洁,因为不需要额外过滤和排序:
// 推荐的结构化数据 const formattedData = [/* 内容同上 */]; const labels = formattedData.map(item => item.date); const dailyFeedings = formattedData.map(item => item.feedings.map(feed => feed.amount)); const maxFeedCount = Math.max(...dailyFeedings.map(feeds => feeds.length)); const datasets = []; for (let i = 0; i < maxFeedCount; i++) { datasets.push({ label: `第${i+1}次喂养`, data: dailyFeedings.map(feeds => feeds[i] || 0), backgroundColor: `rgba(${Math.floor(Math.random()*255)}, ${Math.floor(Math.random()*255)}, ${Math.floor(Math.random()*255)}, 0.7)`, stack: 'feed-stack' }); } // 初始化图表的代码和上面完全一致
不管哪种方式,都能轻松支持30个甚至更多日期的数据,循环会自动处理所有的喂养记录,不需要手动逐个添加。
内容的提问来源于stack exchange,提问作者Matchew
相关产品推荐
相关产品推荐

