JavaScript导入CSV生成Chart.js图表:日期未转毫秒致筛选失效求助
解决CSV导入Chart.js后的日期筛选问题
我用JavaScript导入CSV文件生成Chart.js图表,已经成功导入CSV,但日期筛选功能失效,排查后发现是日期没转成毫秒数。自己是JS新手,查了帖子也没解决,附上CSV数据和代码:
CSV数据
2022-08-13,2119 2022-08-14,2163 2022-08-15,2171 2022-08-16,2191 2022-08-17,2205 2022-08-18,2205 2022-08-19,2231 2022-08-20,2244 2022-08-21,2244 2022-08-22,2249 2022-08-23,2256
现有JavaScript代码
// global variable getNumbDocMonth(); const years = []; const values = []; console.log(years); // setup const DATE = [ "2022-08-16", "2022-08-17", "2022-08-18", "2022-08-19", "2022-08-20", "2022-08-21", "2022-08-22", "2022-08-23", ]; // console.log(DATES); const datapoints = [18, 12, 6, 9, 12, 3, 9]; const convertedDates = DATE.map((date) => new Date(date).setHours(0, 0, 0, 0) ); console.log(convertedDates); // console.log(datapoints); const data = { labels: DATE, datasets: [{ label: "Global Document Tracker", data: datapoints, backgroundColor: ["rgba(255, 26, 104, 0.2)"], borderWidth: 1, }, ], }; // console.log(data.labels); // config const config = { type: "bar", data, options: { scales: { x: { type: "time", time: { unit: "day", }, }, y: { beginAtZero: true, }, }, }, }; // render init block const myChart = new Chart(document.getElementById("myChart"), config); function filterDate() { const start1 = new Date(document.getElementById("start").value); const start = start1.setHours(0, 0, 0, 0); //converting to ms const end1 = new Date(document.getElementById("end").value); const end = end1.setHours(0, 0, 0, 0); const filteredDates = convertedDates.filter( (date) => date >= start && date <= end ); myChart.config.data.labels = filteredDates; const startArray = convertedDates.indexOf(filteredDates[0]); const endArray = convertedDates.indexOf( filteredDates[filteredDates.length - 1] ); const copydatapoints = [...datapoints]; copydatapoints.splice(endArray + 1, filteredDates.length); copydatapoints.splice(0, startArray); // console.log(copydatapoints); myChart.config.data.datasets[0].data = copydatapoints; myChart.update(); } function resetDate() { myChart.config.data.labels = convertedDates; myChart.config.data.datasets[0].data = datapoints; myChart.update(); } async function getNumbDocMonth() { const response = await fetch("Stats_Docs_Total_By_Day.csv"); const data = await response.text(); // console.log(data); const table = data.split("\n").slice(0); // console.log(table); table.forEach((row) => { const columns = row.split(","); const year = columns[0]; const totalDocCount = columns[1]; years.push(year); // console.log(year, totalDocCount); }); } // END OF BAR CHART DOC PER MONTH
现有HTML代码
<div class="chartMenu"></div> <div class="chartCard"> <div class="chartBox"> <canvas id="myChart"></canvas> Start: <input id="start" type="date" value="2022-08-15" /> End: <input id="end" type="date" value="2022-08-21" /> <button onclick="filterDate()">Filter</button> <button onclick="resetDate()">Reset</button> </div> </div> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/chart.js"></script> <script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns/dist/chartjs-adapter-date-fns.bundle.min.js"></script>
解决方案
核心问题有两个:一是CSV导入的数据未被实际使用(当前用的是硬编码数组),二是日期筛选逻辑错误,以及Chart.js时间轴对数据格式的要求。
1. 修正CSV数据导入逻辑,保存转换后的日期和数值
修改数据导入函数,同时等待数据加载完成后再初始化图表:
// 全局变量存储转换后的日期和数值 let convertedDates = []; let datapoints = []; let myChart; // 初始化流程:先加载数据,再创建图表 async function init() { await getNumbDocMonth(); initChart(); } async function getNumbDocMonth() { const response = await fetch("Stats_Docs_Total_By_Day.csv"); const data = await response.text(); // 过滤空行,避免解析错误 const table = data.split("\n").filter(row => row.trim() !== ""); convertedDates = []; datapoints = []; table.forEach((row) => { const columns = row.split(","); const dateStr = columns[0].trim(); const totalDocCount = parseInt(columns[1].trim()); // 将日期转为毫秒数,并统一设置为0点 const dateMs = new Date(dateStr).setHours(0, 0, 0, 0); convertedDates.push(dateMs); datapoints.push(totalDocCount); }); } function initChart() { const data = { labels: convertedDates, // 用毫秒数作为时间轴标签 datasets: [{ label: "Global Document Tracker", data: datapoints, backgroundColor: ["rgba(255, 26, 104, 0.2)"], borderWidth: 1, }], }; const config = { type: "bar", data, options: { scales: { x: { type: "time", time: { unit: "day", tooltipFormat: "yyyy-MM-dd", // 鼠标悬浮时的日期格式 displayFormats: { day: "yyyy-MM-dd" // X轴显示的日期格式 } }, title: { display: true, text: "日期" } }, y: { beginAtZero: true, title: { display: true, text: "文档总数" } }, }, }, }; myChart = new Chart(document.getElementById("myChart"), config); } // 页面加载时启动初始化 init();
2. 修正日期筛选逻辑
避免用indexOf取索引(重复日期会出错),直接遍历匹配日期和对应数值:
function filterDate() { const start1 = new Date(document.getElementById("start").value); const start = start1.setHours(0, 0, 0, 0); const end1 = new Date(document.getElementById("end").value); const end = end1.setHours(0, 0, 0, 0); // 同时筛选日期和对应的数值,保证数据对应 const filteredData = convertedDates.map((date, index) => ({ date, value: datapoints[index] })).filter(item => item.date >= start && item.date <= end); // 更新图表数据 myChart.config.data.labels = filteredData.map(item => item.date); myChart.config.data.datasets[0].data = filteredData.map(item => item.value); myChart.update(); } function resetDate() { myChart.config.data.labels = convertedDates; myChart.config.data.datasets[0].data = datapoints; myChart.update(); }
关键注意点
- Chart.js的时间轴
type: "time"兼容毫秒数格式,用转换后的毫秒数作为标签能确保日期匹配准确。 - 必须等待CSV数据加载完成后再初始化图表,否则会因数据为空导致图表异常。
- 筛选时要同时处理日期和数值,避免数据错位。
内容的提问来源于stack exchange,提问作者safalstha
相关产品推荐
相关产品推荐

