You need to enable JavaScript to run this app. 如何基于Chart.js实现从MySQL取数的无刷新实时更新折线图
优惠活动
大模型
产品
解决方案
定价
更多

如何基于Chart.js实现从MySQL取数的无刷新实时更新折线图

Chart.js 无刷新实时更新实现方案

核心实现逻辑

通过定时异步请求后端接口拉取最新数据库数据,直接修改已初始化的Chart实例属性并触发内置渲染方法,全程无需重载index.php页面。

第一步:拆分独立JSON数据接口

将原来嵌在JS里的数据库查询逻辑独立为纯数据接口文件,比如api/get_chart_data.php,用于输出结构化的图表JSON数据,避免把数据库逻辑硬编码在前端脚本生成流程中:

<?php
header("Content-Type: application/json; charset=UTF-8");
// 数据库连接配置
$koneksi = mysqli_connect("数据库用户名", "数据库密码", "数据库名");
if (!$koneksi) {
    die(json_encode(["error" => "数据库连接失败"]));
}
// 保留原有查询逻辑:取最近5条记录按时间正序排列,单次查询同时取时间和传感器值
$query = mysqli_query($koneksi, 'SELECT created_at, sensor1 FROM (SELECT * FROM modul1 ORDER BY id DESC LIMIT 5) Var1 ORDER BY id ASC');

$response = [
    'labels' => [],
    'values' => []
];
while ($row = mysqli_fetch_assoc($query)) {
    $response['labels'][] = $row['created_at'];
    $response['values'][] = floatval($row['sensor1']);
}
echo json_encode($response);
exit;
?>

第二步:改造图表初始化逻辑

将图表实例保存为全局可访问变量,修正原代码中存在的语法疏漏(原代码animation行无配置值、缺逗号,会导致JS解析失败):

// 全局存储图表实例,供后续更新调用
let myLineChart;

async function initChart() {
    const ctx = document.getElementById("GrafikRTU");
    // 首次加载拉取初始数据
    const res = await fetch('api/get_chart_data.php');
    const initialData = await res.json();

    myLineChart = new Chart(ctx, {
        type: 'line',
        data: {
            labels: initialData.labels,
            datasets: [{
                label: "传感器1数值",
                lineTension: 0.3,
                backgroundColor: "rgba(78, 115, 223, 0.05)",
                borderColor: "rgba(78, 115, 223, 1)",
                pointRadius: 3,
                pointBackgroundColor: "rgba(78, 115, 223, 1)",
                pointBorderColor: "rgba(78, 115, 223, 1)",
                pointHoverRadius: 3,
                pointHoverBackgroundColor: "rgba(78, 115, 223, 1)",
                pointHoverBorderColor: "rgba(78, 115, 223, 1)",
                pointHitRadius: 10,
                pointBorderWidth: 2,
                data: initialData.values,
            }]
        },
        options: {
            maintainAspectRatio: false,
            animation: {
                duration: 300 // 数据更新时的动画时长,避免界面闪烁
            },
            layout: {
                padding: {
                    left: 10,
                    right: 25,
                    top: 25,
                    bottom: 0
                }
            },
            scales: {
                xAxes: [{
                    time: {
                        unit: 'date'
                    },
                    gridLines: {
                        display: false,
                        drawBorder: false
                    },
                    ticks: {
                        maxTicksLimit: 7
                    }
                }],
                yAxes: [{
                    ticks: {
                        maxTicksLimit: 5,
                        padding: 10,
                        // 替换原示例中的美元符号逻辑,适配传感器数值展示
                        callback: function(value) {
                            return value;
                        }
                    },
                    gridLines: {
                        color: "rgb(234, 236, 244)",
                        zeroLineColor: "rgb(234, 236, 244)",
                        drawBorder: false,
                        borderDash: [2],
                        zeroLineBorderDash: [2]
                    }
                }],
            },
            legend: {
                display: false
            },
            tooltips: {
                backgroundColor: "rgb(255,255,255)",
                bodyFontColor: "#858796",
                titleMarginBottom: 10,
                titleFontColor: '#6e707e',
                titleFontSize: 14,
                borderColor: '#dddfeb',
                borderWidth: 1,
                xPadding: 15,
                yPadding: 15,
                displayColors: false,
                intersect: false,
                mode: 'index',
                caretPadding: 10
            }
        }
    });
}

第三步:实现定时数据刷新

通过定时器异步拉取最新数据,直接更新图表实例的数据集属性,调用Chart内置的update()方法完成视图刷新:

async function refreshChartData() {
    // 图表未初始化完成时跳过本次请求
    if (!myLineChart) return;
    try {
        const res = await fetch('api/get_chart_data.php');
        const newData = await res.json();
        // 更新图表的标签与数据
        myLineChart.data.labels = newData.labels;
        myLineChart.data.datasets[0].data = newData.values;
        // 触发图表重新渲染
        myLineChart.update();
    } catch (err) {
        console.warn('数据刷新失败:', err);
    }
}

// 页面DOM加载完成后执行初始化 + 开启定时任务
window.addEventListener('DOMContentLoaded', () => {
    initChart();
    // 可根据实际数据采集频率调整间隔,建议不低于3秒,避免增加数据库压力
    setInterval(refreshChartData, 5000);
});

优化建议

  • 不要将数据库账号密码硬编码在前端可见的脚本生成流程中,拆分独立接口后数据库逻辑全部运行在后端,不会被前端直接获取
  • 原代码对同一张表执行了两次重复查询取时间和传感器值,可合并为单次查询同时返回两个字段,降低数据库查询开销
  • 可增加数据对比判断:只有拉取的最新数据和当前图表数据不一致时,才触发update()方法,减少不必要的动画渲染
  • 定时刷新间隔不要设置过短,需和数据库的实际数据写入频率匹配,避免无效查询浪费服务器资源

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.01 09:45:06