如何在React.js中实现符合要求的24小时ELD执勤状态图表
实现ELD 24小时执勤状态图表的方案
一、可用的图表库推荐
1. Recharts
Recharts无现成ELD专用组件,但可基于**堆叠条形图(Stacked Bar Chart)**自定义:
- 将X轴设为24小时刻度,Y轴作为单一执勤周期维度
- 用
Bar组件堆叠不同状态的时间段,通过fill属性绑定对应颜色 - 自定义
Tooltip或统计区域,计算并展示各状态总时长 - 核心思路:把每个状态的时间段转换为小时数长度,映射到Bar的宽度占比
2. Victory
Victory的堆叠条形图适配性强,适合这类时间分段展示需求:
- 用
VictoryStack包裹VictoryBar实现状态分段 - 配置X轴为24小时范围,自定义刻度显示
- 通过
style属性为不同状态设置颜色,添加VictoryLabel展示时长统计
3. D3.js(React环境适用)
追求完全自定义交互和样式时,D3.js是最优选择,React中可直接封装D3逻辑:
- 用D3比例尺将24小时映射到图表宽度
- 生成矩形元素对应各状态时间段,设置填充色
- 用D3轴生成器创建24小时网格刻度
- 计算各状态总时长,添加文本标签展示
二、React自定义实现方案(轻量版)
若不想依赖复杂库,可通过React+CSS快速实现核心功能:
import { useMemo } from 'react'; // 示例数据:包含状态类型、时间段、对应颜色 const dutyData = [ { type: 'off-duty', start: 0, end: 6, color: '#8884d8' }, { type: 'sleeper berth', start: 6, end: 10, color: '#82ca9d' }, { type: 'driving', start: 10, end: 16, color: '#ffc658' }, { type: 'on-duty', start: 16, end: 24, color: '#ff8042' }, ]; const EldChart = () => { // 预计算各状态总时长 const durationStats = useMemo(() => { return dutyData.map(item => ({ type: item.type, duration: item.end - item.start, color: item.color, })); }, []); return ( <div className="eld-chart-container" style={{ width: '100%', maxWidth: '800px', margin: '0 auto', padding: '20px' }}> {/* 24小时网格刻度 */} <div className="hour-grid" style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '8px' }}> {Array.from({ length: 25 }, (_, i) => ( <span key={i} style={{ fontSize: '12px', color: '#666' }}>{i}</span> ))} </div> {/* 状态分段条形图 */} <div className="status-bar" style={{ height: '60px', border: '1px solid #eee', borderRadius: '4px', position: 'relative', overflow: 'hidden' }}> {dutyData.map((item, idx) => { const widthPercent = ((item.end - item.start) / 24) * 100; const leftPercent = (item.start / 24) * 100; return ( <div key={idx} style={{ position: 'absolute', top: 0, left: `${leftPercent}%`, width: `${widthPercent}%`, height: '100%', backgroundColor: item.color, display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#fff', fontSize: '14px', fontWeight: '500', }} > {item.type} </div> ); })} </div> {/* 时长统计图例 */} <div className="stats-legend" style={{ display: 'flex', gap: '20px', marginTop: '16px', flexWrap: 'wrap' }}> {durationStats.map((stat, idx) => ( <div key={idx} style={{ display: 'flex', alignItems: 'center', gap: '8px' }}> <div style={{ width: '16px', height: '16px', borderRadius: '2px', backgroundColor: stat.color }}></div> <span>{stat.type}: {stat.duration}h</span> </div> ))} </div> </div> ); }; export default EldChart;
自定义实现扩展方向
- 添加交互:鼠标悬停显示详细时间段信息
- 支持多司机/多周期的对比展示
- 优化响应式布局,适配移动端
- 添加入场动画,增强视觉体验
内容的提问来源于stack exchange,提问作者Praveen Deshmane
相关产品推荐
相关产品推荐

