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

如何用ChartJS实现带线性时间轴的多战队分数趋势折线图?

解决ChartJS游戏计分板折线图的线性时间轴+单战队单线问题

要实现带线性时间轴、每个战队对应一条线的折线图,核心是统一全局时间点并为每个战队补全对应时间的分数数据,以下是具体实现方案:

步骤1:预处理原始数据

原始数据是按战队分组的时间-分数数组,我们需要先提取所有时间点并统一排序,再为每个战队生成匹配全局时间轴的分数数组:

// 模拟原始数据源(按战队分组)
const rawData = [
  {
    team: "Team A",
    records: [
      { timestamp: 1690000000000, score: 10 },
      { timestamp: 1690200000000, score: 25 },
      { timestamp: 1690500000000, score: 40 }
    ]
  },
  {
    team: "Team B",
    records: [
      { timestamp: 1690100000000, score: 15 },
      { timestamp: 1690300000000, score: 30 },
      { timestamp: 1690600000000, score: 50 }
    ]
  },
  {
    team: "Team C",
    records: [
      { timestamp: 1690050000000, score: 8 },
      { timestamp: 1690400000000, score: 22 },
      { timestamp: 1690550000000, score: 35 }
    ]
  }
];

// 1. 提取所有时间戳并去重排序
const allTimestamps = [...new Set(rawData.flatMap(team => team.records.map(r => r.timestamp)))].sort((a, b) => a - b);

// 2. 为每个战队生成匹配全局时间轴的分数数组
const chartData = {
  labels: allTimestamps, // 全局统一的时间轴标签
  datasets: rawData.map(teamData => {
    // 将当前战队的记录转为时间-分数映射
    const scoreMap = new Map(teamData.records.map(r => [r.timestamp, r.score]));
    // 遍历全局时间轴,补全分数(无记录则用null)
    const scores = allTimestamps.map(ts => scoreMap.get(ts) || null);
    return {
      label: teamData.team,
      data: scores,
      borderColor: getRandomColor(), // 生成随机战队颜色
      fill: false,
      tension: 0.1
    };
  })
};

// 辅助函数:生成随机颜色
function getRandomColor() {
  const letters = '0123456789ABCDEF';
  let color = '#';
  for (let i = 0; i < 6; i++) {
    color += letters[Math.floor(Math.random() * 16)];
  }
  return color;
}

步骤2:配置ChartJS实例(启用时间轴)

需要引入ChartJS的时间适配器来正确解析时间戳,确保X轴线性排列:

<!-- 引入依赖 -->
<script 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>

<!-- 画布元素 -->
<canvas id="scoreChart" width="800" height="400"></canvas>

<script>
new Chart(document.getElementById('scoreChart'), {
  type: 'line',
  data: chartData,
  options: {
    responsive: true,
    scales: {
      x: {
        type: 'time', // 启用时间轴类型
        time: {
          unit: 'day', // 根据数据粒度调整时间单位(hour/day等)
          tooltipFormat: 'yyyy-MM-dd HH:mm' // 鼠标悬浮时的时间显示格式
        },
        title: {
          display: true,
          text: '时间'
        }
      },
      y: {
        title: {
          display: true,
          text: '分数'
        },
        beginAtZero: true
      }
    },
    plugins: {
      tooltip: {
        mode: 'index', // 鼠标悬浮时显示所有战队在该时间点的分数
        intersect: false
      }
    }
  }
});
</script>

关键说明

  • 空值处理:用null填充无记录的时间点,ChartJS会自动跳过空值,保持战队线条从最近的有效分数点连到下一个有效点,不会出现错误的插值或断裂。
  • 时间适配器:必须引入时间适配器,否则ChartJS无法将时间戳解析为线性的时间轴,会默认按字符串排序导致轴混乱。
  • 全局时间轴:统一的时间标签确保所有战队的折线都基于同一X轴渲染,能清晰展示分数反超的时间点。

内容的提问来源于stack exchange,提问作者Jonas-fr

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 02:12:26