实现图表末尾追加数据点不重绘及X轴动态更新需求
Highcharts iOS 图表优化:批量追加数据不重绘+无数据时自动更新X轴
问题背景
使用Highcharts开发iOS图表时,每次添加数据点都会触发图表重绘,引发性能问题。需实现两个核心需求:
- 在图表末尾批量追加新数据点,不立即触发重绘
- 当无新数据更新时,每秒自动更新X轴并展示当前数值
解决方案代码
import UIKit import Highcharts import Firebase import FirebaseFirestore import Charts class LiveTableViewCell: UITableViewCell { @IBOutlet weak var Aitime: UILabel! @IBOutlet weak var time: UILabel! @IBOutlet weak var nowusdt: UILabel! @IBOutlet weak var nowq8: UILabel! @IBOutlet weak var inusdt: UILabel! @IBOutlet weak var liveContainer: UIView! // 改用普通UIView作为容器,规避与Charts库类名冲突 @IBOutlet weak var Number: UILabel! let db = Firestore.firestore() var number: Int = 0 { didSet { Number.text = "#" + String(number) } } var quantityArray: [Double] = [] private var chartView: HIChartView! private var chartOptions: HIOptions! private var updateTimer: Timer? private var lastUpdateTimestamp: Int = 0 // 记录最后一次数据更新时间戳 override func awakeFromNib() { super.awakeFromNib() // 仅初始化一次图表配置 setupChart() // 启动无数据时的自动更新定时器 startAutoUpdateTimer() } override func setSelected(_ selected: Bool, animated: Bool) { super.setSelected(selected, animated: animated) } // 初始化图表基础配置 private func setupChart() { chartView = HIChartView(frame: liveContainer.bounds) liveContainer.addSubview(chartView) chartOptions = HIOptions() let chart = HIChart() chart.type = "spline" chart.marginRight = 10 chartOptions.chart = chart let time = HITime() time.useUTC = true chartOptions.time = time let title = HITitle() title.text = "Live random data" chartOptions.title = title let accessibility = HIAccessibility() accessibility.announceNewData = HIAnnounceNewData() accessibility.announceNewData.enabled = true accessibility.announceNewData.minAnnounceInterval = 15000 accessibility.announceNewData.announcementFormatter = HIFunction(jsFunction: "function (allSeries, newSeries, newPoint) { if (newPoint) { return 'New point added. Value: ' + newPoint.y; } return false; }") chartOptions.accessibility = accessibility let xAxis = HIXAxis() xAxis.type = "datetime" xAxis.tickPixelInterval = 150 chartOptions.xAxis = [xAxis] let yAxis = HIYAxis() yAxis.title = HITitle() yAxis.title.text = "Value" let plotLines = HIPlotLines() plotLines.value = 0 plotLines.width = 1 plotLines.color = HIColor(hexValue: "808080") yAxis.plotLines = [plotLines] chartOptions.yAxis = [yAxis] let tooltip = HITooltip() tooltip.headerFormat = "<b>{series.name}</b><br/>" tooltip.pointFormat = "{point.x:%Y-%m-%d %H:%M:%S}<br/>{point.y:.2f}" chartOptions.tooltip = tooltip let legend = HILegend() legend.enabled = false chartOptions.legend = legend let exporting = HIExporting() exporting.enabled = false chartOptions.exporting = exporting let spline = HISpline() spline.name = "Random data" spline.data = [] chartOptions.series = [spline] chartView.options = chartOptions } // 追加数据点(不立即触发重绘) func appendDataPoint(quantity: Double, timestamp: Int) { quantityArray.append(quantity) lastUpdateTimestamp = timestamp // 添加数据点时设置redraw为false,避免立即重绘 let point = ["x": timestamp, "y": quantity] chartView.options.series.first?.addPoint(point, redraw: false) // 可在批量添加完成后手动调用以下代码触发一次重绘 // chartView.redraw() } // 启动无数据时的自动更新定时器 private func startAutoUpdateTimer() { updateTimer?.invalidate() updateTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] _ in guard let self = self else { return } // 若最近1秒内有数据更新,跳过本次自动更新 let currentTimestamp = Int(Date().timeIntervalSince1970) if currentTimestamp - self.lastUpdateTimestamp < 1 { return } // 更新X轴范围,保持展示最近60秒数据 if let xAxis = self.chartOptions.xAxis.first as? HIXAxis { let now = Int(Date().timeIntervalSince1970) * 1000 // Highcharts使用毫秒时间戳 xAxis.max = now xAxis.min = now - 60000 } // 展示最后一个数据点的数值 if let lastValue = self.quantityArray.last { self.nowusdt.text = String(format: "%.2f", lastValue) } // 触发重绘更新X轴 self.chartView.redraw() } } // 手动触发图表重绘(批量添加数据后调用) func triggerChartRedraw() { chartView.redraw() } deinit { updateTimer?.invalidate() } }
关键优化说明
- 复用图表实例:将
HIChartView和HIOptions设为类属性,仅在awakeFromNib中初始化一次,避免重复创建图表导致的频繁重绘。 - 无重绘追加数据:使用Highcharts原生的
addPoint(_:redraw:)方法,设置redraw: false实现批量添加数据后统一重绘,减少重绘次数。 - 无数据自动更新:通过定时器每秒检查数据状态,无新数据时自动更新X轴时间范围,同时刷新数值展示,保持图表活跃性。
- 规避命名冲突:将原
LineChartView类型的控件改为普通UIView容器,避免与Charts库类名冲突。
内容的提问来源于stack exchange,提问作者Saurabh Pathak
相关产品推荐
相关产品推荐

