引言
這里僅對(duì)UIBezierPath這一獨(dú)立的類進(jìn)行使用,不結(jié)合Core Animation中的類。
虛線繪制
在繪制完整實(shí)例前,先熟悉下setLineDash方法的使用。
直接上代碼和呈現(xiàn)效果:
let path = UIBezierPath.init()
path.move(to: CGPoint.init(x: 30, y: 100))
path.addLine(to: CGPoint.init(x: 600, y: 100))
path.lineWidth = 5
let LineDashArr: [CGFloat] = [20.0,40.0,40.0,80.0,60.0]
path.setLineDash(LineDashArr, count: 5, phase: 0)
UIColor.red.setStroke()
path.stroke()

向setLineDash方法傳入的三個(gè)參數(shù):
第一個(gè)參數(shù):存放虛線各段長(zhǎng)度的浮點(diǎn)數(shù)組。按照 劃線--間隔--劃線--間隔--... 設(shè)置,并且在最后一個(gè)浮點(diǎn)數(shù)表示的虛線部分繪制完畢后,回到第一個(gè)數(shù)進(jìn)行循環(huán),直到虛線繪制完成。
第二個(gè)參數(shù):截取數(shù)組的個(gè)數(shù)。當(dāng)此數(shù)小于數(shù)組實(shí)際個(gè)數(shù)時(shí),相當(dāng)于截取數(shù)組的前n個(gè)來(lái)使用,數(shù)組剩余元素完全無(wú)用。
第三個(gè)參數(shù):偏移量,在此例中,如果設(shè)置偏移量為20,則第一段劃線長(zhǎng)度為40,第一個(gè)間隔為40,以此類推。
靜態(tài)指南針
先看下最后完成的效果:

拆分來(lái)看,包含圓、三角形的繪制,是UIBezierPath的基本應(yīng)用,唯一有一丟丟技巧的是刻度繪制,這就要用到前面虛線繪制的方法了。
羅盤輪廓
很簡(jiǎn)單,用init(ovalIn:)方法創(chuàng)建一個(gè)圓形,填充、描邊。
let radius = CGFloat(160)
let originX = self.center.x
let originY = self.center.y
let path = UIBezierPath.init(ovalIn: CGRect.init(x: originX - radius, y: originY - radius, width: radius*2, height: radius*2))
path.lineWidth = 5
UIColor.black.setStroke()
UIColor.white.setFill()
path.stroke()
path.fill()

加一下羅盤上的文字,這部分代碼就不展示了:

指針
這里分為兩部分繪制,藍(lán)色部分和紅色部分,每部分path添加兩條線即可,且無(wú)需用close()閉合路徑。只填充,不需描邊。
let blueHand = UIBezierPath.init()
blueHand.lineWidth = 4
blueHand.move(to: CGPoint.init(x: originX - 8, y: originY))
blueHand.addLine(to: CGPoint.init(x: originX, y: originY - 120))
blueHand.addLine(to: CGPoint.init(x: originX + 8, y: originY))
UIColor.blue.setFill()
blueHand.fill()
let redHand = UIBezierPath.init()
redHand.lineWidth = 4
redHand.move(to: CGPoint.init(x: originX - 8, y: originY))
redHand.addLine(to: CGPoint.init(x: originX, y: originY + 120))
redHand.addLine(to: CGPoint.init(x: originX + 8, y: originY))
UIColor.red.setFill()
redHand.fill()

羅盤刻度
通過(guò)觀察發(fā)現(xiàn),羅盤刻度分為兩類,一類是四個(gè)字母對(duì)應(yīng)的大刻度,一類是密集的小刻度,對(duì)于每類刻度,刻度間間隔相同,刻度粗細(xì)也相同,可以通過(guò)將圓形路徑繪制為虛線的方法分別繪制,這里要注意把虛線間間隔算準(zhǔn)了。
圓的0點(diǎn)參照官方文檔中的圖:

大刻度繪制:
let scaleRadius = CGFloat(150)
let scale = UIBezierPath.init(ovalIn: CGRect.init(x: originX - scaleRadius, y: originY - scaleRadius, width: scaleRadius*2, height: scaleRadius*2))
scale.lineWidth = 20
let LineDashArr: [CGFloat] = [4.0,scaleRadius*CGFloat(Double.pi*0.5) - 4]
scale.setLineDash(LineDashArr, count: 2, phase: 2)
UIColor.black.setStroke()
scale.stroke()
我設(shè)置的刻度寬度為4,為保證每條刻度線位于正中位置,故偏移量為2,間隔為 1/4圓周-刻度寬度的一半*2 , 即 R * π * 0.5 - 刻度寬度。

小刻度同理:
let milliScaleR = CGFloat(155)
let milliScale = UIBezierPath.init(ovalIn: CGRect.init(x: originX - milliScaleR, y: originY - milliScaleR, width: milliScaleR*2, height: milliScaleR*2))
milliScale.lineWidth = 10
let mLineDashArr: [CGFloat] = [2.0,scaleRadius*CGFloat(Double.pi/80)-0.1 - 2]
milliScale.setLineDash(mLineDashArr, count: 2, phase: 1)
UIColor.black.setStroke()
milliScale.stroke()

完整Demo:https://github.com/XG-nil/UIBezierPathDemo