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

如何修复Chart.js折线图多数据笔实时数据添加位置异常问题

问题

我使用Chart.js折线图展示多笔随时间变化的数据,代码逻辑为:先给每笔数据添加30秒的历史数据,之后通过每秒执行的OnTimer()函数追加当前时间的实时数据点。
当仅启用1笔数据(const _PENS = 1;)时,实时数据会正确追加到历史数据的图表右侧,符合预期;但启用2笔数据(const _PENS = 2;)时,实时数据并未追加到历史数据之后,反而被添加到图表左侧。

以下是出现问题的代码:

<html>
<body>
    <canvas hidden="0" id="myLineChart"></canvas>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.4/moment.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment@1.0.1/dist/chartjs-adapter-moment.min.js"></script>
    <script>
        // --- define my data set
        var MyDataset = {
            datasets: [
                {
                    label: 'Red pen (seconds)',
                    borderColor: 'red',
                    backgroundColor: 'red',
                },
                {
                    label: 'Orange pen (seconds+1)',
                    borderColor: 'orange',
                    backgroundColor: 'orange',
                },
            ],
        };

        // --- define my chart configuration
        var MyChartConfig = {
            type: "line",
            data: MyDataset,
            options: {
                plugins: {
                    title: {
                        display: true,
                        text: 'My Line Chart'
                    }
                },
                scales: {
                    x: {
                        type: 'time',
                        time: {
                            unit: 'second',
                            displayFormats: {
                                second: 'YYYY-MM-DD, HH:mm:ss', // Format for the unit
                            }
                        },
                    },
                    y: {
                        position: 'left',
                        type: 'linear',
                        display: true,
                        title: {
                            display: true, // Set to true to display the title
                            text: 'Left axis', // The text content of the y-axis title
                        },
                    },
                },
            },
        };

        // --- set the number of pens to use
        //     using only 1 pen produces the desired and correct effect - realtime data is appended to the historical data on the right hand side of the chart
        //     using 2 pens gives a whacky result - realtime data is added to the left hand side of the chart !!!
        const _PENS = 2; // pens
        const _HISTORY = 30;  // seconds

        // --- add an OnTimer function to execute every second
        //     this function will add realtime data to the pens
        function OnTimer()
        {
            // --- add a new value to each pen at the current timestamp
            dt = new Date();
            MyLineChart.data.labels.push(dt);
            for (i = 0; i < _PENS; i++)
            {
                MyLineChart.data.datasets[i].data.push(dt.getSeconds()+i);
            }
            MyLineChart.update();
        }

        // --- create the chart
        var MyLineChart = new Chart(document.getElementById('myLineChart'), MyChartConfig);

        // --- add _HISTORY seconds of historical data to all pens on chart
        for (i = 0; i < _PENS; i++)
        {
            // --- get the time _HISTORY secs ago
            dt = new Date(new Date().getTime() - (_HISTORY*1000));
            for (j = 0; j < _HISTORY; j++)
            {
                // add one second
                dt = new Date(dt.getTime() + 1000);
                // add the new data point to the chart
                MyLineChart.data.labels.push(dt);
                MyLineChart.data.datasets[i].data.push(dt.getSeconds()+i);
            }
            MyLineChart.update();
        }

        // --- execute the OnTimer function every second
        setInterval(OnTimer, 1000);
    </script>
</body>
</html>
修复方案

问题原因

初始化历史数据时,你按数据集循环,给每个数据集单独往labels数组重复添加了30个时间戳。例如2笔数据时,labels数组会被塞入60个时间值(30*2),但每个数据集的data数组只有30个值。这种标签与数据长度不匹配的情况,会导致Chart.js在渲染时出现时间轴错位,后续新增的实时时间戳会被错误识别为更早的时间,从而显示在图表左侧。

修复步骤

  1. 统一生成历史时间标签:只生成一次30秒的连续时间戳数组,一次性赋值给labels,避免重复添加。
  2. 同步填充数据集数据:基于同一组时间标签,分别给每个数据集填充对应的数据点,确保每个数据集的data长度与labels完全一致。

修正后的完整代码

<html>
<body>
    <canvas hidden="0" id="myLineChart"></canvas>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.4/moment.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment@1.0.1/dist/chartjs-adapter-moment.min.js"></script>
    <script>
        // --- define my data set
        var MyDataset = {
            datasets: [
                {
                    label: 'Red pen (seconds)',
                    borderColor: 'red',
                    backgroundColor: 'red',
                },
                {
                    label: 'Orange pen (seconds+1)',
                    borderColor: 'orange',
                    backgroundColor: 'orange',
                },
            ],
        };

        // --- define my chart configuration
        var MyChartConfig = {
            type: "line",
            data: MyDataset,
            options: {
                plugins: {
                    title: {
                        display: true,
                        text: 'My Line Chart'
                    }
                },
                scales: {
                    x: {
                        type: 'time',
                        time: {
                            unit: 'second',
                            displayFormats: {
                                second: 'YYYY-MM-DD, HH:mm:ss', // Format for the unit
                            }
                        },
                    },
                    y: {
                        position: 'left',
                        type: 'linear',
                        display: true,
                        title: {
                            display: true, // Set to true to display the title
                            text: 'Left axis', // The text content of the y-axis title
                        },
                    },
                },
            },
        };

        // --- set the number of pens to use
        const _PENS = 2; // pens
        const _HISTORY = 30;  // seconds

        // --- add an OnTimer function to execute every second
        function OnTimer()
        {
            // --- add a new value to each pen at the current timestamp
            const dt = new Date();
            MyLineChart.data.labels.push(dt);
            for (let i = 0; i < _PENS; i++)
            {
                MyLineChart.data.datasets[i].data.push(dt.getSeconds()+i);
            }
            MyLineChart.update();
        }

        // --- create the chart
        var MyLineChart = new Chart(document.getElementById('myLineChart'), MyChartConfig);

        // --- add _HISTORY seconds of historical data to all pens on chart
        // 第一步:统一生成历史时间标签
        const historicalLabels = [];
        let dt = new Date(new Date().getTime() - (_HISTORY*1000));
        for (let j = 0; j < _HISTORY; j++)
        {
            dt = new Date(dt.getTime() + 1000);
            historicalLabels.push(dt);
        }
        // 一次性赋值给labels
        MyLineChart.data.labels = historicalLabels;

        // 第二步:给每个数据集填充对应历史数据
        for (let i = 0; i < _PENS; i++)
        {
            const datasetData = [];
            for (const time of historicalLabels)
            {
                datasetData.push(time.getSeconds() + i);
            }
            MyLineChart.data.datasets[i].data = datasetData;
        }
        MyLineChart.update();

        // --- execute the OnTimer function every second
        setInterval(OnTimer, 1000);
    </script>
</body>
</html>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 15:44:53