我正在尝试使用 UIBezierPath
绘制一个简单的抛物线形状。我有一个 maxPoint
和一个 boundingRect
,我基于抛物线的宽度和拉伸(stretch)。
这是我绘制抛物线的函数(我在容器 View 中绘制抛物线,rect
将是 container.bounds
):
func addParabolaWithMax(maxPoint: CGPoint, inRect boundingRect: CGRect) {
let path = UIBezierPath()
let p1 = CGPointMake(1, CGRectGetMaxY(boundingRect)-1)
let p3 = CGPointMake(CGRectGetMaxX(boundingRect)-1, CGRectGetMaxY(boundingRect)-1)
path.moveToPoint(p1)
path.addQuadCurveToPoint(p3, controlPoint: maxPoint)
// Drawing code
...
}
我的问题是,我希望我在函数中发送的 maxPoint
是抛物线本身的实际极值点。因此,例如,如果我发送 (CGRectGetMidX(container.bounds), 0)
,最大点应该位于最顶部的中心。但是在这个特定点上使用这个函数,结果是这样的:
那么这里的路径到底是做什么的呢?或者换句话说,我怎样才能从 controlPoint
到达我需要的实际最大点?我已经尝试根据 boundingRect
的高度从 y
值中添加和减去不同的值,但我找不到正确的组合,因为在不同的点具有不同的 y
值,它的行为不同。好像加了个乘法器,怎么解决?
最佳答案
对于许多应用程序,adam.wulf 的解决方案很好,但它实际上并没有创建抛物线。要创建抛物线,我们需要计算给定二次曲线中点的控制点。贝塞尔路径只是数学;我们可以很容易地计算出来。我们只需要反转 Bézier 函数并求解 t=0.5。
0.5(中点)处的贝塞尔解决方案在 Draw a quadratic Bézier curve through three given points 处很好地导出.
2*Pc - P0/2 - P2/2
其中Pc
是我们要经过的点,P0
和P2
是终点。
(在其他点计算贝塞尔曲线不是很直观。t=0.25 处的值不是“路径的四分之一”。但幸运的是,就我们的目的而言,t=0.5 与我们的直觉非常吻合二次方程的“中点”。)
鉴于我们的解决方案,我们可以编写我们的代码。请原谅对 Swift 3 的翻译;我的 Xcode 7.3 副本对 iOS Playground 不是很满意,但应该很容易转换到 2.2。
func addParabolaWithMax(maxPoint: CGPoint, inRect boundingRect: CGRect) -> UIBezierPath {
func halfPoint1D(p0: CGFloat, p2: CGFloat, control: CGFloat) -> CGFloat {
return 2 * control - p0 / 2 - p2 / 2
}
let path = UIBezierPath()
let p0 = CGPoint(x: 0, y: boundingRect.maxY)
let p2 = CGPoint(x: boundingRect.maxX, y: boundingRect.maxY)
let p1 = CGPoint(x: halfPoint1D(p0: p0.x, p2: p2.x, control: maxPoint.x),
y: halfPoint1D(p0: p0.y, p2: p2.y, control: maxPoint.y))
path.move(to: p0)
path.addQuadCurve(to: p2, controlPoint: p1)
return path
}
halfPoint1D
函数是我们解决方案的一维实现。对于我们的二维 CGPoint
,我们只需调用它两次。
如果我只能推荐一种理解贝塞尔曲线的资源,那很可能是 "Constructing Bézier curves"来自维基百科的部分。研究显示曲线如何产生的小动画,我发现非常有启发性。 “特定案例”部分也很有用。为了深入探讨这个主题(我建议所有开发人员都熟悉这个主题),我喜欢 A Primer on Bézier Curves .可以略读一下,只阅读您目前感兴趣的部分。但是对这组函数的基本理解将大大有助于消除 Core Graphics 中绘图的魔力,并使 UIBezierPath 成为一个工具而不是一个黑盒子。
关于ios - 理解 UIBezierPath 曲线机制、controlPoint 和曲线点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38723031/