用 Swift 進行貝塞爾曲線繪製

級別: ★★☆☆☆
標籤:「iOS」「Swift」「塞爾曲線」
做者: 大成小棧
審校: QiShare團隊php


1. 貝塞爾曲線介紹

以三階爲例:設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、二式代入第三式得:微信

當t從0變到1時,它表示了由三頂點P0、P一、P2三點定義的一條二次Bezier曲線。

而且代表: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第一個研究了這種矢量繪製曲線的方法,並給出了詳細的計算公式,所以按照這樣的公式繪製出來的曲線就用他的姓氏來命名,稱爲貝塞爾曲線。

2. 用Swift進行貝塞爾曲線的繪製

2.1 普通線條繪製

用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()
    }
}
複製代碼

運行結果:

還能夠進行復雜圖形的繪製。

源碼Github地址


小編微信:可加並拉入《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的啓動流程
奇舞週刊

相關文章
相關標籤/搜索