所以我有自定义 View ,我正在尝试在那里绘制折线图。首先我绘制 xGrid、yGrid 和中间线。这是我执行此操作的功能:
var width: CGFloat = 400
var height: CGFloat = 200
var xLines: CGFloat = 20
var yLines: CGFloat = 10
let color = NSColor.blackColor()
func drawMiddleLine() {
let middleHeight = height / 2
var context = NSGraphicsContext.currentContext()?.CGContext
CGContextSetStrokeColorWithColor(context, color.CGColor)
CGContextSetLineWidth(context, 2)
CGContextMoveToPoint(context, 0, middleHeight)
CGContextAddLineToPoint(context, width, middleHeight)
CGContextStrokePath(context)
}
func drawYGrid() {
let space = height / yLines
var context = NSGraphicsContext.currentContext()?.CGContext
CGContextSetStrokeColorWithColor(context, color.CGColor)
for index in 0...Int(yLines) {
CGContextMoveToPoint(context, width, (CGFloat(index) * space))
CGContextAddLineToPoint(context, 0, (CGFloat(index) * space))
}
CGContextStrokePath(context)
}
func drawXGrid() {
let space = width / xLines
var context = NSGraphicsContext.currentContext()?.CGContext
CGContextSetStrokeColorWithColor(context, color.CGColor)
for index in 0...Int(xLines) {
CGContextMoveToPoint(context, (CGFloat(index) * space), self.bounds.height)
CGContextAddLineToPoint(context, CGFloat(index) * space, 0)
}
CGContextStrokePath(context)
}
现在我有了宽度是高度两倍的基本网格。现在我想缩放我的 y 轴,所以我要缩放我的数据(在这个例子中,我只取最大正数):
func getMaxValue(data: Array<CGFloat>) ->CGFloat {
let max = maxElement(data)
return max
}
现在我缩放我的 y 轴:
func scaleYAxis(data: Array<CGFloat>) ->Array<CGFloat> {
let maxValue = getMaxValue(data)
var factor = height / maxValue / 4
var scaledY = data.map({datum -> CGFloat in
var newValue = datum * factor
return newValue
})
return scaledY
}
但是当我用太多数据点画线时,我的画会变得一团糟,因为数据点太多了。当有大约 50 个数据点时就可以了。
例如,我想在结果中得到这样的东西:JavaScript linechart with many many datapoints
有什么想法可以在 Swift 中实现吗?
我的画法是这样的:
func drawLine(data: Array<CGFloat>) {
var path = CGPathCreateMutable()
var middleHeight = height / 2
CGPathMoveToPoint(path, nil, 0, middleHeight)
var scaledY = sclaleYAxis(data)
for index in 0..<data.count {
var xSpot = data[index]
var ySpot = middleHeight + scaledY[index]
CGPathAddLineToPoint(path, nil, xSpot, ySpot)
}
var layer = CAShapeLayer()
layer.frame = self.bounds
layer.path = path
layer.strokeColor = NSColor.greenColor().CGColor
layer.fillColor = nil
layer.lineWidth = 3
self.layer?.addSublayer(layer)
// I Have lineLayerStore and I delete all lines when it is needed
lineLayerStore.append(layer)
}
最佳答案
如果不看屏幕截图,我无法理解确切的问题是什么,但数据点的可见性取决于屏幕上的像素数。
如果不让某些数据点共享相同的像素列或对数据进行下采样,则不能显示比像素数量更多的数据点。
您有 3 个选择:
使 X 轴可滚动并将 ScrollView 的 contentSize 宽度设置为 数量数据点。
保持 X 轴宽度固定,对数据进行下采样以减少 要显示的数据点,然后绘制有关的图表 下采样数据。
什么都不做,尝试在固定宽度内绘制所有数据点, 如果你的计算是正确的,一些数据点会重叠并且 在图表中共享相同的像素列。
第三个选项的解释编辑:
要在 200 像素宽的 X 轴上显示 1000 个数据点,每个像素将有 5 个数据点。所以;
数据点 0、1、2、3 和 4 将绘制在第一个像素列上。
数据点 5、6、7、8 和 9 将绘制在第二个像素列上。
数据点 10、11、12、13 和 14 将绘制在第 3 个像素列上。
等等。
对于您的示例,有 400 个像素和 1000 个数据点,这意味着每个像素有 2.5 个数据点。所以;
数据点 0、1、2 将绘制在第一个像素列上。
数据点 3、4 将绘制在第二个像素列上。
数据点 5、6、7 将绘制在第 3 个像素列上。
数据点 8、9 将绘制在第 4 个像素列上。
然后就这样继续下去。
关于xcode - 使用 1000 多个数据点在 Swift 中绘制折线图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27942773/