You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Chart.js绘制基于时间轴的单行彩色条形图

实现方案

要实现这种时间轴分段状态的单行条形图,你需要调整Chart.js的配置和数据结构,核心思路是将每个状态的时间间隔转换成条形的区间范围,用水平条形图配合时间轴完成可视化,具体步骤如下:

1. 预处理数据

先把原始的时间-状态数据转换为时间段区间——每个状态从当前时间点持续到下一个状态的时间点:

  • 7am up → 持续到9am,时长2小时
  • 9am down → 持续到10:45am,时长1小时45分
  • 10:45am out → 持续到17:35,时长6小时50分
  • 17:35 up → 可设置到当天结束(比如23:59)

将这些时间点转换为时间戳,明确每个状态的起始和结束时间。

2. 配置Chart.js

核心配置调整:

  • Y轴使用分类轴,仅设置一个分类(比如['状态 timeline']),保证条形是单行
  • X轴使用时间轴,设置覆盖所有数据的时间范围
  • 利用Chart.js v3+新增的xEnd属性定义条形的结束位置,替代堆叠配置

完整示例代码:

private createChart(): void {
  if (this.chart) return;

  // 注册必要组件
  Chart.register(BarController, BarElement, Tooltip, Legend, TimeScale, CategoryScale);

  // 预处理数据:转换为时间区间
  const baseDate = '2023-02-13T'; // 统一日期基准
  const timeStateList = [
    { time: '07:00:00', state: 'up', color: 'red' },
    { time: '09:00:00', state: 'down', color: 'yellow' },
    { time: '10:45:00', state: 'out', color: 'green' },
    { time: '17:35:00', state: 'up', color: 'red' },
    { time: '23:59:59', state: 'end', color: 'transparent' } // 新增结束点
  ];

  // 生成数据集
  const datasets = [];
  for (let i = 0; i < timeStateList.length - 1; i++) {
    const startTime = new Date(baseDate + timeStateList[i].time).getTime();
    const endTime = new Date(baseDate + timeStateList[i+1].time).getTime();

    datasets.push({
      label: timeStateList[i].state,
      data: [{
        y: '状态 timeline', // Y轴唯一分类
        x: startTime,
        xEnd: endTime // 定义条形的结束时间
      }],
      backgroundColor: timeStateList[i].color,
      borderWidth: 0
    });
  }

  const options = {
    plugins: {
      legend: { display: true },
      tooltip: {
        callbacks: {
          label: (context) => {
            const state = context.dataset.label;
            const start = new Date(context.raw.x).toLocaleTimeString();
            const end = new Date(context.raw.xEnd).toLocaleTimeString();
            return `${state}: ${start} - ${end}`;
          }
        }
      }
    },
    indexAxis: 'y', // 水平条形图
    responsive: true,
    maintainAspectRatio: false,
    scales: {
      y: {
        type: 'category',
        labels: ['状态 timeline'],
        stacked: false,
        ticks: { display: true }
      },
      x: {
        type: 'time',
        time: {
          unit: 'hour',
          displayFormats: { hour: 'h:mm a' }
        },
        min: new Date(baseDate + '06:00:00').getTime(), // 提前显示起始区域
        max: new Date(baseDate + '23:59:59').getTime()
      }
    }
  };

  this.chart = new Chart(this.canvasRef.nativeElement, {
    type: 'bar',
    data: {
      labels: ['状态 timeline'],
      datasets: datasets
    },
    options: options
  });
}

3. 关键注意点

  • 必须使用Chart.js v3及以上版本,xEnd属性是v3新增的,用于定义条形的结束位置
  • 时间轴的min和max要覆盖所有数据的时间范围,避免图表显示不全
  • 每个状态对应一个独立数据集,每个数据集仅包含一个数据点,通过x和xEnd确定时间区间

问题原文(翻译)

我有一组基于时间的数据,希望使用Chart.js将其可视化。数据格式如下:

Time    State   
--------------
7am     up
9am     down
10.45am out
17.35   up

每个状态对应特定颜色:

up =    red
down =  yellow
out =   green

我想要实现的最终效果是单行条形图。我尝试使用Chart.js的水平堆叠条形图,但始终无法实现,以下是我的实验代码(无法正常显示图表):

private createChart(): void {
    if (this.chart !== undefined) {
      return;
    }

    Chart.register(BarController, PointElement, Tooltip, Legend, TimeScale, LinearScale, CategoryScale, LinearScale, BarElement);
    const options: ChartOptions = {
      plugins: {
        legend: {
          display: false,
        },
        title: {
          display: false,
        },
      },

      indexAxis: 'y',
      responsive: true,
      maintainAspectRatio: false,
      scales: {
        y: {
          stacked: true,
          type: 'time',
          display: true,
          time: {
            unit: 'minute',
            displayFormats: {
              minute: 'h:mm a'
            }
          }
        },
        x: {
          stacked: false,
          
         }
      }    
    };

    this.chart = new Chart(this.canvasRef.nativeElement, {
      type: 'bar',
      data: this.chartData,
      options
    });

    this.chart.config.options.scales.y.min = new Date('2023-02-13T06:19:31.842Z').getTime();
     
    const labels = [
      'up',
      'down'
    ];

    
    const d1 = new Date('2023-02-13T06:20:32.842Z').getTime();
    const d2 = new Date('2023-02-13T06:21:33.842Z').getTime();
    this.chartData = {
      labels,
      datasets: [{
        label: 'up',
        data: [{x: 10, y: d1}],
        backgroundColor: 'red',
      },
      {
         label: 'down',
         data: [{x: 20, y: d2}],
          backgroundColor: 'green',
       }
    ]
    };

    this.chart.update();
  }

我尝试了多种标签、坐标轴值和数据结构组合,但始终显示空图表。后续参考示例代码修改后,仍无法按日期长度绘制条形。请问如何使用Chart.js实现该需求?

内容的提问来源于stack exchange,提问作者peterc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 14:06:56