我有一些像 (x1,y1), (x2,y2), (x3,y3)...
现在我想绘制一个曲线平滑的图表?
我正在尝试绘制如下
-(void)drawPrices
{
NSInteger count = self.prices.count;
UIBezierPath *path = [UIBezierPath bezierPath];
path.lineCapStyle = kCGLineCapRound;
for(int i=0; i<count-1; i++)
{
CGPoint controlPoint[2];
CGPoint p = [self pointWithIndex:i inData:self.prices];
if(i==0)
{
[path moveToPoint:p];
}
CGPoint nextPoint, previousPoint, m;
nextPoint = [self pointWithIndex:i+1 inData:self.prices];
previousPoint = [self pointWithIndex:i-1 inData:self.prices];
if(i > 0) {
m.x = (nextPoint.x - previousPoint.x) / 2;
m.y = (nextPoint.y - previousPoint.y) / 2;
} else {
m.x = (nextPoint.x - p.x) / 2;
m.y = (nextPoint.y - p.y) / 2;
}
controlPoint[0].x = p.x + m.x * 0.2;
controlPoint[0].y = p.y + m.y * 0.2;
// Second control point
nextPoint = [self pointWithIndex:i+2 inData:self.prices];
previousPoint = [self pointWithIndex:i inData:self.prices];
p = [self pointWithIndex:i + 1 inData:self.prices];
m = zeroPoint;
if(i < self.prices.count - 2) {
m.x = (nextPoint.x - previousPoint.x) / 2;
m.y = (nextPoint.y - previousPoint.y) / 2;
} else {
m.x = (p.x - previousPoint.x) / 2;
m.y = (p.y - previousPoint.y) / 2;
}
controlPoint[1].x = p.x - m.x * 0.2;
controlPoint[1].y = p.y - m.y * 0.2;
[path addCurveToPoint:p controlPoint1:controlPoint[0] controlPoint2:controlPoint[1]];
}
CAShapeLayer *lineLayer = [CAShapeLayer layer];
lineLayer.path = path.CGPath;
lineLayer.lineWidth = LINE_WIDTH;
lineLayer.strokeColor = _priceColor.CGColor;
lineLayer.fillColor = [UIColor clearColor].CGColor;
[self.layer addSublayer:lineLayer];
}
Run Code Online (Sandbox Code Playgroud)
有没有更好的方法来做到这一点?
iSp*_*n17 11
我为您提供了另一个我曾经成功的解决方案。它需要 SpriteKit,它有一个很棒的工具,叫做SKKeyFrameSequence它能够进行样条插值,如Apple 提供的本教程所示。
所以我们的想法是,您将像这样创建正确的 SKKeyFrameSequence 对象(假设您的数据位于(CGFloat, CGFloat)(x, y) 元组的数组中):
let xValues = data.map { $0.0 }
let yValues = data.map { $0.1 }
let sequence = SKKeyFrameSequence(keyFrameValues: yValues,
times: xValues.map { NSNumber($0) })
sequence.interpolationMode = .spline
let xMin = xValues.min()!
let xMax = xValues.max()!
Run Code Online (Sandbox Code Playgroud)
然后,如果您将插值样条分成 200 条(如果您愿意,可以更改此值,但对我而言,这会导致人眼看到平滑的波浪),您可以绘制一条由小线组成的路径。
var splinedValues = [(CGFloat, CGFloat)]()
stride(from: xMin, to: xMax, by: (xMax - xMin) / 200).forEach {
splinedValues.append((CGFloat($0),
sequence.sample(atTime: CGFloat($0)) as! CGFloat))
}
Run Code Online (Sandbox Code Playgroud)
最后是路径(我将使用 SwiftUI,但您也可以以相同的方式使用 UIKit。):
Path { path in
path.move(to: CGPoint(x: splinedValues[0].0, y: splinedValues[0].1))
for splineValue in splinedValues.dropFirst() {
path.addLine(to: CGPoint(x: splineValue.0, y: splineValue.1))
}
}
Run Code Online (Sandbox Code Playgroud)
对于值
[(1, 4), (2, 6), (3, 7), (4, 5), (5, 3), (6, -1), (7, -2), (8, -2.5), (9, -2), (10, 0), (11, 4)]
Run Code Online (Sandbox Code Playgroud)
我用上面描述的方法得到了这样的图:(我也添加了点以更好地评估结果)
| 归档时间: |
|
| 查看次数: |
2750 次 |
| 最近记录: |