以三階爲例:設P0、P0二、P2是一條拋物線上順序三個不一樣的點。過P0和P2點的兩切線交於P1點,在P02點的切線交P0P1和P2P1於P01和P11,則以下比例成立:git
這是所謂拋物線的三切線定理。github
當P0,P2固定,引入參數t,令上述比值爲t:(1-t),即有:web
當P0,P2固定,引入參數t,令上述比值爲t:(1-t),即有:swift
t從0變到1,第1、二式就分別表示控制二邊形的第1、二條邊,它們是兩條一次Bezier曲線。將1、二式代入第三式得:微信
而且代表:ide
這二次Bezier曲線P02能夠定義爲分別由前兩個頂點(P0,P1)和後兩個頂點(P1,P2)決定的一次Bezier曲線的線性組合。工具
依次類推,性能
由四個控制點定義的三次Bezier曲線P03可被定義爲分別由(P0,P1,P2)和(P1,P2,P3)肯定的二條二次Bezier曲線的線性組合,由(n+1)個控制點Pi(i=0,1,...,n)定義的n次Bezier曲線P0n可被定義爲分別由前、後n個控制點定義的兩條(n-1)次Bezier曲線P0n-1與P1n-1的線性組合:優化
由此獲得Bezier曲線的遞推計算公式
Bézier curve(貝塞爾曲線)是應用於二維圖形應用程序的數學曲線。 曲線定義:起始點、終止點(也稱錨點)、控制點。經過調整控制點,貝塞爾曲線的形狀會發生變化。 1962年,法國數學家Pierre Bézier第一個研究了這種矢量繪製曲線的方法,並給出了詳細的計算公式,所以按照這樣的公式繪製出來的曲線就用他的姓氏來命名,稱爲貝塞爾曲線。
用Swift進行普通線條的繪製代碼,以下:
import UIKit
class BezierPathView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func draw(_ rect: CGRect) {
super.draw(rect)
self.drawLine()
self.drawCommonCurve()
self.drawSmoothPath()
}
func drawLine() {
let offset:CGFloat = 50.0
// 繪製矩形
//let rectpath = UIBezierPath(rect: CGRect.init(x: 15, y: offset, width: 300, height: 60))
let rectpath = UIBezierPath(roundedRect: CGRect.init(x: 15, y: offset, width: 300, height: 60), cornerRadius: 5.0)
rectpath.lineWidth = 5.0
UIColor.green.setStroke()
rectpath.stroke()
UIColor.red.setFill()
rectpath.fill()
// 繪製直線
let path = UIBezierPath()
path.move(to: CGPoint(x: 25.0, y: offset + 130.0))
path.addLine(to: CGPoint(x: 300.0, y: offset + 130.0))
path.lineWidth = 5.0
UIColor.cyan.setStroke()
path.stroke()
}
func drawCommonCurve() {
let offset:CGFloat = 260.0
let curvePath = UIBezierPath()
curvePath.move(to: CGPoint(x: 30.0, y: offset))
curvePath.addQuadCurve(to: CGPoint(x: 350.0, y: offset), controlPoint: CGPoint(x: 350.0, y: offset + 100))
UIColor.blue.setStroke()
curvePath.stroke()
}
func drawSmoothPath() {
let offset:CGFloat = 430
let pointCount:Int = 4
let pointArr:NSMutableArray = NSMutableArray.init()
for i in 0...pointCount {
let px: CGFloat = 15 + CGFloat(i) * CGFloat(80)
let py: CGFloat = i % 2 == 0 ? offset - 60 : offset + 60
let point: CGPoint = CGPoint.init(x: px, y: py)
pointArr.add(point)
}
let bezierPath = UIBezierPath()
bezierPath.lineWidth = 2.0
var prevPoint: CGPoint!
for i in 0 ..< pointArr.count {
let currPoint:CGPoint = pointArr.object(at: i) as! CGPoint
// 繪製綠色圓圈
let arcPath = UIBezierPath()
arcPath.addArc(withCenter: currPoint, radius: 3, startAngle: 0, endAngle: CGFloat(2 * Double.pi), clockwise: true)
UIColor.green.setStroke()
arcPath.stroke()
// 繪製平滑曲線
if i==0 {
bezierPath.move(to: currPoint)
}
else {
let conPoint1: CGPoint = CGPoint.init(x: CGFloat(prevPoint.x + currPoint.x) / 2.0, y: prevPoint.y)
let conPoint2: CGPoint = CGPoint.init(x: CGFloat(prevPoint.x + currPoint.x) / 2.0, y: currPoint.y)
bezierPath.addCurve(to: currPoint, controlPoint1: conPoint1, controlPoint2: conPoint2)
}
prevPoint = currPoint
}
UIColor.red.setStroke()
bezierPath.stroke()
}
}
複製代碼
運行結果:
還能夠進行復雜圖形的繪製。
小編微信:可加並拉入《QiShare技術交流羣》。
關注咱們的途徑有:
QiShare(簡書)
QiShare(掘金)
QiShare(知乎)
QiShare(GitHub)
QiShare(CocoaChina)
QiShare(StackOverflow)
QiShare(微信公衆號)
推薦文章:
Swift 5.1 (10) - 屬性
iOS App後臺保活
Swift 中使用 CGAffineTransform
iOS 性能監控(一)—— CPU功耗監控
iOS 性能監控(二)—— 主線程卡頓監控
iOS 性能監控(三)—— 方法耗時監控
初識Flutter web
用SwiftUI給視圖添加動畫
用SwiftUI寫一個簡單頁面
iOS App啓動優化(三)—— 本身作一個工具監控App的啓動耗時
iOS App啓動優化(二)—— 使用「Time Profiler」工具監控App的啓動耗時
iOS App啓動優化(一)—— 瞭解App的啓動流程
奇舞週刊