如何在PHP+MySQL环境下实现不规则间隔时序折线图
不规则时间间隔技能成长折线图可落地方案
问题核心原因
你搜到的大部分Chart.js入门案例把X轴设为了分类类目轴,所有数据点会按顺序等距排列,自然无法适配时间间隔不固定的记录场景。只要把X轴切换为Chart.js原生支持的时间类型轴,就能自动按真实时间差计算点间距,完全覆盖单日多条记录、跨周跨月无记录的场景。
后端(PHP+MySQL)实现步骤
你的业务表只需要保留基础字段即可:user_id(用户ID)、skill_id(技能ID)、score(0-100的整数/浮点评分数值)、record_time(datetime类型,记录提交时间)。
后端不需要做时间维度的聚合计算,直接按时间正序拉取原始记录,输出为前端可识别的JSON格式即可,示例代码:
<?php // 自行替换为你的数据库连接逻辑 $pdo = new PDO('mysql:host=localhost;dbname=你的库名;charset=utf8mb4', '数据库账号', '数据库密码'); $userId = intval($_GET['user_id']); $skillId = intval($_GET['skill_id']); $stmt = $pdo->prepare("SELECT record_time, score FROM skill_records WHERE user_id = ? AND skill_id = ? ORDER BY record_time ASC"); $stmt->execute([$userId, $skillId]); $records = $stmt->fetchAll(PDO::FETCH_ASSOC); $chartData = []; foreach ($records as $row) { $chartData[] = [ 'x' => date('c', strtotime($row['record_time'])), // 转为ISO8601标准时间格式 'y' => floatval($row['score']) ]; } header('Content-Type: application/json'); echo json_encode($chartData); ?>
前端实现(代码可直接复用)
不需要掌握复杂JavaScript逻辑,只要引入Chart.js及配套的时间轴适配器,替换接口地址即可直接使用,Y轴会固定为0-100的评分区间,和你需要的效果完全匹配。
首先在页面中加入画布容器和依赖资源:
<!-- 折线图画布容器 --> <div style="width: 90%;max-width: 1000px;margin: 2rem auto;"> <canvas id="skillChart"></canvas> </div> <!-- 引入静态资源,可自行下载到本地替换路径 --> <script src="/static/chart.umd.min.js"></script> <script src="/static/luxon.min.js"></script> <script src="/static/chartjs-adapter-luxon.umd.min.js"></script>
然后加入初始化代码,核心是把X轴类型设为time,自动适配不规则时间间隔:
<script> // 替换为你上面写的PHP接口地址,传入对应用户和技能ID const fetchUrl = `/api/get_skill_record.php?user_id=1&skill_id=3`; fetch(fetchUrl) .then(res => res.json()) .then(pointData => { const chartIns = new Chart(document.getElementById('skillChart'), { type: 'line', data: { datasets: [{ label: '技能成长曲线', data: pointData, borderColor: '#165DFF', backgroundColor: 'rgba(22,93,255,0.1)', fill: true, tension: 0.25, pointRadius: 3, pointHoverRadius: 6 }] }, options: { responsive: true, scales: { x: { type: 'time', // 核心配置:启用真实时间轴,自动按时间差计算点间距 time: { tooltipFormat: 'yyyy-MM-dd HH:mm', displayFormats: { hour: 'MM-dd HH:mm', day: 'yyyy-MM-dd', week: 'yyyy-MM-dd', month: 'yyyy-MM' } }, title: { display: true, text: '记录时间' } }, y: { min: 0, max: 100, // 固定Y轴区间匹配0-100评分体系 ticks: { stepSize: 10 }, title: { display: true, text: '技能评分' } } } } }); }) </script>
效果说明
- 自动适配任意时间间隔的记录:单日提交10条记录时点会按当天的小时维度排布,间隔数周无记录时两点之间的距离会对应拉长,不会出现等距排列的问题
- 时间刻度会根据数据总跨度自动调整显示密度,不会出现文字重叠
- 鼠标悬停时会显示对应记录的精确时间和评分数值,交互逻辑和同类成长曲线网站一致
- 如果需要展示同一用户多个技能的对比曲线,只需要在
datasets数组中新增对应数据集即可,不需要修改核心配置
参考效果逻辑同GPLRank的成长曲线,仅将Y轴维度替换为0-100的技能评分。
内容的提问来源于stack exchange,提问作者Danny
相关产品推荐
相关产品推荐

