Chart.js+React实现项目工时展示 解决Y轴时间12小时上限问题
问题根源
time类型坐标轴是为真实日历时间场景设计的,你配置的HH:mm格式属于单日时间格式化规则,底层会按24小时为周期做进位处理,天然不支持无上限的累计时长展示,不管怎么调整time轴的配置,都没法突破日期时间的循环逻辑,完全不适合工时统计这种累计值场景。
解决方案
直接放弃time轴,改用linear线性轴,自行处理时长数值和展示格式的转换,即可实现无上限的工时展示,原有堆叠、30分钟步长的效果都可以完全保留:
- 数据层统一把所有工时值转成总分钟数的纯数值格式存储/传入图表,比如13小时15分就传
13*60 +15 = 795,不要传时间格式字符串。如果你的存量数据是HH:mm格式,可以用这个函数转换:const parseDuration = (timeStr) => { const [h, m] = timeStr.split(':').map(Number); return h * 60 + m; }; - 替换Y轴配置,用线性轴+自定义刻度回调实现和之前一致的
HH:mm展示效果,支持任意小时数:scales: { x: { stacked: true, }, y: { stacked: true, type: "linear", beginAtZero: true, ticks: { stepSize: 30, // 保持原配置30分钟一个刻度 callback: (val) => { const hours = Math.floor(val / 60); const mins = val % 60; return `${hours}:${mins.toString().padStart(2, '0')}`; } }, }, } - 补充tooltip的格式化配置,替换原time轴自带的tooltip格式:
options: { // 上述scales配置放在此处 plugins: { tooltip: { callbacks: { label: (ctx) => { const totalMins = ctx.parsed.y; const hours = Math.floor(totalMins / 60); const mins = totalMins % 60; return `${ctx.dataset.label}: ${hours}小时${mins.toString().padStart(2, '0')}分钟`; } } } } }
这个方案没有时长上限,不管是十几小时还是上百小时的累计工时都能正常渲染,不会出现时间循环、数值截断的问题。
内容的提问来源于stack exchange,提问作者Med EL
相关产品推荐
相关产品推荐

