如何实现Highcharts蜡烛图实时更新(PHP+MySQL数据源)
实现Highstock蜡烛图每秒实时更新的方法
一、先做后端增量数据接口
单独写一个PHP接口(比如get_latest_ohlc.php),只返回最新一条K线数据,避免全量返回历史数据浪费性能:
<?php // 连接MySQL $conn = mysqli_connect("你的主机地址", "数据库用户名", "数据库密码", "目标数据库名"); if (!$conn) { die(json_encode(['error' => '数据库连接失败'])); } // 查询最新的K线数据(根据你的表结构调整字段和表名) $sql = "SELECT time, open, high, low, close FROM kline_table ORDER BY time DESC LIMIT 1"; $result = mysqli_query($conn, $sql); if ($row = mysqli_fetch_assoc($result)) { // 转成Highcharts要求的格式:[毫秒时间戳, 开盘价, 最高价, 最低价, 收盘价] $data = [ strtotime($row['time']) * 1000, (float)$row['open'], (float)$row['high'], (float)$row['low'], (float)$row['close'] ]; echo json_encode($data); } else { echo json_encode([]); } mysqli_close($conn); ?>
二、修改前端代码实现实时更新
在你现有代码的基础上,修改图表的load事件,添加定时器每秒请求接口并更新数据:
var data = '<?php echo $text;?>'; data = JSON.parse(data); // 拆分历史ohlc数据 var ohlc = [], dataLength = data.length, i = 0; for (i; i < dataLength; i += 1) { ohlc.push([ data[i][0], // 时间 data[i][1], // 开盘 data[i][2], // 最高 data[i][3], // 最低 data[i][4] // 收盘 ]); } // 初始化图表并保存实例 var chart = Highcharts.stockChart('container', { chart: { events: { load: function () { addPopupEvents(this); // 获取蜡烛图系列(第一个系列) var candleSeries = this.series[0]; // 设置每秒更新的定时器 setInterval(function () { // 请求后端接口获取最新数据 fetch('get_latest_ohlc.php') .then(response => response.json()) .then(newData => { if (newData.length === 0) return; // 避免重复添加相同时间的数据 var lastPoint = candleSeries.data[candleSeries.data.length - 1]; if (lastPoint && newData[0] === lastPoint.x) return; // 添加新数据点,自动重绘图表 // 第三个参数设为true时,会自动移除最旧的点(可控制数据量) candleSeries.addPoint(newData, true, false); }) .catch(error => console.error('数据更新失败:', error)); }, 1000); // 每秒执行一次 } } }, // 以下为你原有的配置,保持不变 title: { text: '<?php echo strtoupper($title);?>' }, yAxis: [{ labels: { align: 'left' }, height: '80%', resize: { enabled: true } }, { labels: { align: 'left' }, top: '80%', height: '20%', offset: 0 }], <?php if($_COOKIE['fut'] == 299){ ?> tooltip: { enabled: true }, <?php } ?> navigationBindings: { events: { selectButton: function (event) { var newClassName = event.button.className + ' highcharts-active', topButton = event.button.parentNode.parentNode; if (topButton.classList.contains('right')) { newClassName += ' right'; } if (!topButton.classList.contains('highcharts-menu-wrapper')) { topButton.className = newClassName; } this.chart.activeButton = event.button; }, deselectButton: function (event) { event.button.parentNode.parentNode.classList.remove('highcharts-active'); this.chart.activeButton = null; }, showPopup: function (event) { if (!this.indicatorsPopupContainer) { this.indicatorsPopupContainer = document .getElementsByClassName('highcharts-popup-indicators')[0]; } if (!this.annotationsPopupContainer) { this.annotationsPopupContainer = document .getElementsByClassName('highcharts-popup-annotations')[0]; } if (event.formType === 'indicators') { this.indicatorsPopupContainer.style.display = 'block'; } else if (event.formType === 'annotation-toolbar') { if (!this.chart.activeButton) { this.chart.currentAnnotation = event.annotation; this.annotationsPopupContainer.style.display = 'block'; } } }, closePopup: function () { this.indicatorsPopupContainer.style.display = 'none'; this.annotationsPopupContainer.style.display = 'none'; } } }, stockTools: { gui: { enabled: false } }, series: [{ type: 'candlestick', id: 'aapl', name: '<?php echo $names[0].'/'.$names[1];?>', data: ohlc, color: '#f23645', // 下跌蜡烛颜色 upColor: '#089981', // 上涨蜡烛颜色 }, { type: 'bb', linkedTo: 'aapl', params:{ period:200, standardDeviation: 2, } }, { type: 'bb', linkedTo: 'aapl', params:{ period:200, standardDeviation: 3, } }, { type: 'bb', linkedTo: 'aapl', params:{ period:200, standardDeviation: 4, } }], responsive: { rules: [{ condition: { maxWidth: 800 }, chartOptions: { rangeSelector: { inputEnabled: false } } }] } });
关键说明
- 你配置的布林带(BB指标)因为设置了
linkedTo: 'aapl',会自动跟随蜡烛图数据更新,无需额外处理 - 如果要限制图表显示的数据量(比如只保留最近200条),可以把
candleSeries.addPoint(newData, true, false)改成candleSeries.addPoint(newData, true, candleSeries.data.length >= 200),超过数量时自动移除最旧的点 - 后端接口返回的时间戳必须是毫秒级,否则Highcharts无法识别
- 可根据实际需求调整更新频率,不一定非要每秒一次,降低频率能减少服务器压力
内容的提问来源于stack exchange,提问作者Ринат Ауди
相关产品推荐
相关产品推荐

