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

基于Chart.js绘制无年份日期轴的跨季节累积折线图问题

解决X轴排序及日期对齐问题

核心问题是没给Chart.js提供固定的、按时间顺序排列的X轴基准标签,导致它自动按字符串排序(比如01-01会排在12-01前面),非共有日期也被追加到末尾。下面分PHP数据处理和Chart.js配置两步解决:

一、PHP端统一日期顺序

  1. 从PostgreSQL拉取数据时,直接用SQL把日期转成MM-DD格式,同时按时间排序:
    SELECT 
        TO_CHAR(date_col, 'MM-DD') AS month_day,
        season,
        cumulative_val
    FROM your_table
    WHERE EXTRACT(MONTH FROM date_col) IN (12,1,2,3)
    ORDER BY 
        CASE EXTRACT(MONTH FROM date_col) WHEN 12 THEN 0 ELSE EXTRACT(MONTH FROM date_col) END,
        EXTRACT(DAY FROM date_col);
    
  2. 生成一个完整的、按时间顺序排列的日期数组,覆盖12月到次年3月的所有日期:
    $orderedDates = [];
    // 生成12月日期
    for ($day = 1; $day <= 31; $day++) $orderedDates[] = sprintf('12-%02d', $day);
    // 生成1月日期
    for ($day = 1; $day <= 31; $day++) $orderedDates[] = sprintf('01-%02d', $day);
    // 生成2月日期(自动处理闰年)
    $febDays = date('L') ? 29 : 28;
    for ($day = 1; $day <= $febDays; $day++) $orderedDates[] = sprintf('02-%02d', $day);
    // 生成3月日期
    for ($day = 1; $day <= 31; $day++) $orderedDates[] = sprintf('03-%02d', $day);
    
  3. 按这个顺序整理每个季节的数据:没有对应日期的条目值设为null(Chart.js会自动跳过空值,但保留X轴位置):
    $seasonGroups = // 将SQL查询结果按season分组,比如用array_group_by
    $processedData = [];
    foreach ($seasonGroups as $seasonName => $rows) {
        $values = [];
        foreach ($orderedDates as $date) {
            $match = array_filter($rows, fn($row) => $row['month_day'] === $date);
            $values[] = $match ? reset($match)['cumulative_val'] : null;
        }
        $processedData[] = [
            'label' => $seasonName,
            'values' => $values,
            'color' => // 给每个季节分配专属颜色,比如#ff5733、#33ff57等
        ];
    }
    // 输出JSON供前端调用
    echo json_encode(['dates' => $orderedDates, 'datasets' => $processedData]);
    

二、Chart.js配置X轴

  1. 解析PHP输出的JSON,用预设日期数组作为X轴标签,强制使用原始顺序:
    fetch('your_php_data_script.php')
        .then(res => res.json())
        .then(data => {
            const ctx = document.getElementById('seasonChart').getContext('2d');
            new Chart(ctx, {
                type: 'line',
                data: {
                    labels: data.dates,
                    datasets: data.datasets.map(set => ({
                        label: set.label,
                        data: set.values,
                        borderColor: set.color,
                        backgroundColor: set.color + '40',
                        fill: false,
                        tension: 0.1
                    }))
                },
                options: {
                    scales: {
                        x: {
                            type: 'category',
                            // 关键:禁用自动排序,严格遵循labels的顺序
                            ticks: {
                                autoSkip: true,
                                maxRotation: 45,
                                minRotation: 45
                            }
                        }
                    }
                }
            });
        });
    
  2. 如果用散点图,需要把日期映射到数组索引保证位置对齐:
    // 散点图的数据集处理
    datasets: data.datasets.map(set => ({
        label: set.label,
        data: data.dates.map((date, idx) => set.values[idx] !== null ? {
            x: idx,
            y: set.values[idx]
        } : null).filter(Boolean),
        pointBackgroundColor: set.color
    }))
    

处理后,所有相同MM-DD日期会对应X轴同一位置,X轴严格按12月→1月→2月→3月顺序排列,非共有日期也会留在正确的时间节点上。

内容的提问来源于stack exchange,提问作者erik-stengel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 18:38:20