Xcode动态实时更新折线图
Xcode dynamic live update line chart
我正在尝试创建一个折线图,我将在其中连续绘制数据,以便可以在实时更新中观察图表,将绘制大约 5 个点左右的一秒钟。我正在寻找的图表类似于此处显示的图表
https://www.vanmil.org/live-heart-rate-with-ios-and-meteor/
或
http://www.highcharts.com/demo/dynamic-update
我一直在研究几种不同的图表框架,例如 iOS 图表,但我似乎无法获得我正在寻找的确切图表,其中可以使用不断发展的 X-轴.
使用 iOS 图表,我设法创建了一种不断发展的图表,示例代码如下。
@IBOutlet weak var chartView: LineChartView!
var xAxisArray : [String]?
var yAxisArray : [Double]?
var date : NSDate?
var dateFormatter : NSDateFormatter?
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Live Graph"
let stringArray = NSMutableArray()
let numberArray = NSMutableArray()
dateFormatter = NSDateFormatter()
dateFormatter!.dateFormat = "HH:mm:ss"
date = NSDate()
//Insert random values into chart
for(var i = 0; i < 40; i++)
{
date = date!.dateByAddingTimeInterval(0.3)
let stringDate = dateFormatter?.stringFromDate(date!)
stringArray.addObject(stringDate!)
let randomNum = self.randomBetweenNumbers(0.0005, secondNum: 0.0015)
numberArray.addObject(randomNum)
}
xAxisArray = stringArray as NSArray as? [String]
yAxisArray = numberArray as NSArray as? [Double]
configureChart()
setData()
NSTimer.scheduledTimerWithTimeInterval(0.2, target: self, selector: "updateChart", userInfo: nil, repeats: true)
}
func configureChart()
{
//Chart config
chartView.descriptionText = ""
chartView.noDataTextDescription = "Add Data"
chartView.drawGridBackgroundEnabled = false
chartView.dragEnabled = true
chartView.rightAxis.enabled = false
chartView.doubleTapToZoomEnabled = false
chartView.legend.enabled = false
//Configure xAxis
let chartXAxis = chartView.xAxis as ChartXAxis
chartXAxis.labelPosition = .Bottom
chartXAxis.setLabelsToSkip(5)
//configure yAxis
chartView.zoom(1.0, scaleY: 1.0, x: 0.0, y: 0.0)
}
func randomBetweenNumbers(firstNum: CGFloat, secondNum: CGFloat) -> CGFloat{
return CGFloat(arc4random()) / CGFloat(UINT32_MAX) * abs(firstNum - secondNum) + min(firstNum, secondNum)
}
func updateChart()
{
let mutableArray = NSMutableArray()
for(var i = 1; i < xAxisArray?.count; i++)
{
mutableArray.addObject(xAxisArray![i])
}
date = date!.dateByAddingTimeInterval(1.0)
let str = dateFormatter!.stringFromDate(date!)
mutableArray.addObject(str)
xAxisArray = mutableArray as NSArray as? [String]
//Numbers
let numberArray = NSMutableArray()
for(var i = 1; i < yAxisArray?.count; i++)
{
numberArray.addObject(yAxisArray![i])
}
let randomNum = self.randomBetweenNumbers(0.0005, secondNum: 0.0015)
let convertToDouble = Double(randomNum)
numberArray.addObject(convertToDouble)
yAxisArray = numberArray as NSArray as? [Double]
setData()
}
func setData()
{
// 1 - creating an array of data entries
var yVals1 : [ChartDataEntry] = [ChartDataEntry]()
for var i = 0; i < xAxisArray!.count; i++ {
yVals1.append(ChartDataEntry(value: yAxisArray![i], xIndex: i))
}
// 2 - create a data set with our array
let set1: LineChartDataSet = LineChartDataSet(yVals: yVals1, label: "")
set1.axisDependency = .Left // Line will correlate with left axis values
set1.setColor(UIColor.blueColor().colorWithAlphaComponent(0.5)) // our line's opacity is 50%
set1.setCircleColor(UIColor.blueColor()) // our circle will be dark red
set1.lineWidth = 2.0
set1.circleRadius = 6.0 // the radius of the node circle
set1.fillAlpha = 65 / 255.0
set1.fillColor = UIColor.blueColor()
set1.highlightColor = UIColor.whiteColor()
set1.drawCircleHoleEnabled = true
set1.drawFilledEnabled = true
//3 - create an array to store our LineChartDataSets
var dataSets : [LineChartDataSet] = [LineChartDataSet]()
dataSets.append(set1)
//4 - pass our months in for our x-axis label value along with our dataSets
let data: LineChartData = LineChartData(xVals: xAxisArray, dataSets: dataSets)
//5 - finally set our data
self.chartView.data = data
//Clear text color
chartView.data?.setValueTextColor(UIColor.clearColor())
}
但如果你尝试一下,你会发现它相当不稳定,加上每次 x 轴标签更新,我希望 X 轴继续发展,并随着绘图的继续让它在屏幕上动画就像示例中显示的那样。
有谁知道任何图表软件可以让我复制这种类型的图表,或者是否可以使用 iOS 图表来实现这种效果?
编辑:
我正在尝试实现这种绘图示例
http://www.code4app.net/ios/Dynamic-plot-curve-line-like-stock-chart/52d68b75cb7e84802f8b5340
只是希望更顺利,
如果您找不到合适的第三方,我建议您使用以下方法:
- 使用逆时针旋转 90˚ 的表格视图。
- 实施您的自定义
UIView
,其中包含要绘制的代码(您的 graph/chart 顶点),然后添加到单元格的根视图中。
- 每秒动态插入 5 个单元格到表视图的数据源中。
我知道实现这个引擎很耗时,但这会 100% 有效。
我打算为此创建一个开源项目。但遗憾的是我还没有任何好的代码可以分享。
我刚做了a small that does exactly what you need。它每秒插入 4 个点,自动将图表滚动到新数据。 (滚动很流畅,新数据重新绘制得很好,说真的,我不知道你为什么不想给这种方法一个机会)你可以向后滚动图表以查看它之前的所有点。图表 cells/slices 正在重复使用,因此您可以将其用于无限图表,例如显示几个小时的心跳图。
请看一看,告诉我你的想法。
您可以使用 iOS 图表执行此操作:
override func viewDidLoad() {
super.viewDidLoad()
//charts
self.lineChartView.delegate = self
let set_a: LineChartDataSet = LineChartDataSet(yVals: [ChartDataEntry](), label: "a")
set_a.drawCirclesEnabled = false
set_a.setColor(UIColor.blueColor())
let set_b: LineChartDataSet = LineChartDataSet(yVals: [ChartDataEntry](), label: "b")
set_b.drawCirclesEnabled = false
set_b.setColor(UIColor.greenColor())
self.lineChartView.data = LineChartData(xVals: [String](), dataSets: [set_a, set_b])
timer = NSTimer.scheduledTimerWithTimeInterval(0.010, target:self, selector: #selector(ViewController.updateCounter), userInfo: nil, repeats: true)
}
// add point
var i = 0
func updateCounter() {
self.lineChartView.data?.addEntry(ChartDataEntry(value: reading_a[i], xIndex: i), dataSetIndex: 0)
self.lineChartView.data?.addEntry(ChartDataEntry(value: reading_b[i], xIndex: i), dataSetIndex: 1)
self.lineChartView.data?.addXValue(String(i))
self.lineChartView.setVisibleXRange(minXRange: CGFloat(1), maxXRange: CGFloat(50))
self.lineChartView.notifyDataSetChanged()
self.lineChartView.moveViewToX(CGFloat(i))
i = i + 1
}
我已经将 Chris Code 更新到 Charts 3.0
override func viewDidLoad() {
super.viewDidLoad()
//charts
self.chartView.delegate = self
let set_a: LineChartDataSet = LineChartDataSet(values:[ChartDataEntry(x: Double(0), y: Double(0))], label: "voice")
set_a.drawCirclesEnabled = false
set_a.setColor(UIColor.blue)
let set_b: LineChartDataSet = LineChartDataSet(values: [ChartDataEntry(x: Double(0), y: Double(0))], label: "flow")
set_b.drawCirclesEnabled = false
set_b.setColor(UIColor.green)
self.chartView.data = LineChartData(dataSets: [set_a,set_b])
timer = Timer.scheduledTimer(timeInterval: 0.010, target: self, selector: #selector(updateCounter), userInfo: nil, repeats: true)
}
// add point
var i = 1
func updateCounter() {
self.chartView.data?.addEntry(ChartDataEntry(x: Double(i), y: reading_a![i]), dataSetIndex: 0)
self.chartView.data?.addEntry(ChartDataEntry(x:Double(i) , y:reading_b![i] ), dataSetIndex: 1)
self.chartView.setVisibleXRange(minXRange: Double(1), maxXRange: Double(1000))
self.chartView.notifyDataSetChanged()
self.chartView.moveViewToX(Double(i))
i = i + 1
}
我正在尝试创建一个折线图,我将在其中连续绘制数据,以便可以在实时更新中观察图表,将绘制大约 5 个点左右的一秒钟。我正在寻找的图表类似于此处显示的图表
https://www.vanmil.org/live-heart-rate-with-ios-and-meteor/
或
http://www.highcharts.com/demo/dynamic-update
我一直在研究几种不同的图表框架,例如 iOS 图表,但我似乎无法获得我正在寻找的确切图表,其中可以使用不断发展的 X-轴.
使用 iOS 图表,我设法创建了一种不断发展的图表,示例代码如下。
@IBOutlet weak var chartView: LineChartView!
var xAxisArray : [String]?
var yAxisArray : [Double]?
var date : NSDate?
var dateFormatter : NSDateFormatter?
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Live Graph"
let stringArray = NSMutableArray()
let numberArray = NSMutableArray()
dateFormatter = NSDateFormatter()
dateFormatter!.dateFormat = "HH:mm:ss"
date = NSDate()
//Insert random values into chart
for(var i = 0; i < 40; i++)
{
date = date!.dateByAddingTimeInterval(0.3)
let stringDate = dateFormatter?.stringFromDate(date!)
stringArray.addObject(stringDate!)
let randomNum = self.randomBetweenNumbers(0.0005, secondNum: 0.0015)
numberArray.addObject(randomNum)
}
xAxisArray = stringArray as NSArray as? [String]
yAxisArray = numberArray as NSArray as? [Double]
configureChart()
setData()
NSTimer.scheduledTimerWithTimeInterval(0.2, target: self, selector: "updateChart", userInfo: nil, repeats: true)
}
func configureChart()
{
//Chart config
chartView.descriptionText = ""
chartView.noDataTextDescription = "Add Data"
chartView.drawGridBackgroundEnabled = false
chartView.dragEnabled = true
chartView.rightAxis.enabled = false
chartView.doubleTapToZoomEnabled = false
chartView.legend.enabled = false
//Configure xAxis
let chartXAxis = chartView.xAxis as ChartXAxis
chartXAxis.labelPosition = .Bottom
chartXAxis.setLabelsToSkip(5)
//configure yAxis
chartView.zoom(1.0, scaleY: 1.0, x: 0.0, y: 0.0)
}
func randomBetweenNumbers(firstNum: CGFloat, secondNum: CGFloat) -> CGFloat{
return CGFloat(arc4random()) / CGFloat(UINT32_MAX) * abs(firstNum - secondNum) + min(firstNum, secondNum)
}
func updateChart()
{
let mutableArray = NSMutableArray()
for(var i = 1; i < xAxisArray?.count; i++)
{
mutableArray.addObject(xAxisArray![i])
}
date = date!.dateByAddingTimeInterval(1.0)
let str = dateFormatter!.stringFromDate(date!)
mutableArray.addObject(str)
xAxisArray = mutableArray as NSArray as? [String]
//Numbers
let numberArray = NSMutableArray()
for(var i = 1; i < yAxisArray?.count; i++)
{
numberArray.addObject(yAxisArray![i])
}
let randomNum = self.randomBetweenNumbers(0.0005, secondNum: 0.0015)
let convertToDouble = Double(randomNum)
numberArray.addObject(convertToDouble)
yAxisArray = numberArray as NSArray as? [Double]
setData()
}
func setData()
{
// 1 - creating an array of data entries
var yVals1 : [ChartDataEntry] = [ChartDataEntry]()
for var i = 0; i < xAxisArray!.count; i++ {
yVals1.append(ChartDataEntry(value: yAxisArray![i], xIndex: i))
}
// 2 - create a data set with our array
let set1: LineChartDataSet = LineChartDataSet(yVals: yVals1, label: "")
set1.axisDependency = .Left // Line will correlate with left axis values
set1.setColor(UIColor.blueColor().colorWithAlphaComponent(0.5)) // our line's opacity is 50%
set1.setCircleColor(UIColor.blueColor()) // our circle will be dark red
set1.lineWidth = 2.0
set1.circleRadius = 6.0 // the radius of the node circle
set1.fillAlpha = 65 / 255.0
set1.fillColor = UIColor.blueColor()
set1.highlightColor = UIColor.whiteColor()
set1.drawCircleHoleEnabled = true
set1.drawFilledEnabled = true
//3 - create an array to store our LineChartDataSets
var dataSets : [LineChartDataSet] = [LineChartDataSet]()
dataSets.append(set1)
//4 - pass our months in for our x-axis label value along with our dataSets
let data: LineChartData = LineChartData(xVals: xAxisArray, dataSets: dataSets)
//5 - finally set our data
self.chartView.data = data
//Clear text color
chartView.data?.setValueTextColor(UIColor.clearColor())
}
但如果你尝试一下,你会发现它相当不稳定,加上每次 x 轴标签更新,我希望 X 轴继续发展,并随着绘图的继续让它在屏幕上动画就像示例中显示的那样。
有谁知道任何图表软件可以让我复制这种类型的图表,或者是否可以使用 iOS 图表来实现这种效果?
编辑:
我正在尝试实现这种绘图示例
http://www.code4app.net/ios/Dynamic-plot-curve-line-like-stock-chart/52d68b75cb7e84802f8b5340
只是希望更顺利,
如果您找不到合适的第三方,我建议您使用以下方法:
- 使用逆时针旋转 90˚ 的表格视图。
- 实施您的自定义
UIView
,其中包含要绘制的代码(您的 graph/chart 顶点),然后添加到单元格的根视图中。 - 每秒动态插入 5 个单元格到表视图的数据源中。
我知道实现这个引擎很耗时,但这会 100% 有效。 我打算为此创建一个开源项目。但遗憾的是我还没有任何好的代码可以分享。
我刚做了a small that does exactly what you need。它每秒插入 4 个点,自动将图表滚动到新数据。 (滚动很流畅,新数据重新绘制得很好,说真的,我不知道你为什么不想给这种方法一个机会)你可以向后滚动图表以查看它之前的所有点。图表 cells/slices 正在重复使用,因此您可以将其用于无限图表,例如显示几个小时的心跳图。
请看一看,告诉我你的想法。
您可以使用 iOS 图表执行此操作:
override func viewDidLoad() {
super.viewDidLoad()
//charts
self.lineChartView.delegate = self
let set_a: LineChartDataSet = LineChartDataSet(yVals: [ChartDataEntry](), label: "a")
set_a.drawCirclesEnabled = false
set_a.setColor(UIColor.blueColor())
let set_b: LineChartDataSet = LineChartDataSet(yVals: [ChartDataEntry](), label: "b")
set_b.drawCirclesEnabled = false
set_b.setColor(UIColor.greenColor())
self.lineChartView.data = LineChartData(xVals: [String](), dataSets: [set_a, set_b])
timer = NSTimer.scheduledTimerWithTimeInterval(0.010, target:self, selector: #selector(ViewController.updateCounter), userInfo: nil, repeats: true)
}
// add point
var i = 0
func updateCounter() {
self.lineChartView.data?.addEntry(ChartDataEntry(value: reading_a[i], xIndex: i), dataSetIndex: 0)
self.lineChartView.data?.addEntry(ChartDataEntry(value: reading_b[i], xIndex: i), dataSetIndex: 1)
self.lineChartView.data?.addXValue(String(i))
self.lineChartView.setVisibleXRange(minXRange: CGFloat(1), maxXRange: CGFloat(50))
self.lineChartView.notifyDataSetChanged()
self.lineChartView.moveViewToX(CGFloat(i))
i = i + 1
}
我已经将 Chris Code 更新到 Charts 3.0
override func viewDidLoad() {
super.viewDidLoad()
//charts
self.chartView.delegate = self
let set_a: LineChartDataSet = LineChartDataSet(values:[ChartDataEntry(x: Double(0), y: Double(0))], label: "voice")
set_a.drawCirclesEnabled = false
set_a.setColor(UIColor.blue)
let set_b: LineChartDataSet = LineChartDataSet(values: [ChartDataEntry(x: Double(0), y: Double(0))], label: "flow")
set_b.drawCirclesEnabled = false
set_b.setColor(UIColor.green)
self.chartView.data = LineChartData(dataSets: [set_a,set_b])
timer = Timer.scheduledTimer(timeInterval: 0.010, target: self, selector: #selector(updateCounter), userInfo: nil, repeats: true)
}
// add point
var i = 1
func updateCounter() {
self.chartView.data?.addEntry(ChartDataEntry(x: Double(i), y: reading_a![i]), dataSetIndex: 0)
self.chartView.data?.addEntry(ChartDataEntry(x:Double(i) , y:reading_b![i] ), dataSetIndex: 1)
self.chartView.setVisibleXRange(minXRange: Double(1), maxXRange: Double(1000))
self.chartView.notifyDataSetChanged()
self.chartView.moveViewToX(Double(i))
i = i + 1
}