引言
这里仅对UIBezierPath这一独立的类进行使用,不结合Core Animation中的类。
虚线绘制
在绘制完整实例前,先熟悉下setLineDash方法的使用。
直接上代码和呈现效果:
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方法传入的三个参数:
第一个参数:存放虚线各段长度的浮点数组。按照 划线--间隔--划线--间隔--... 设置,并且在最后一个浮点数表示的虚线部分绘制完毕后,回到第一个数进行循环,直到虚线绘制完成。
第二个参数:截取数组的个数。当此数小于数组实际个数时,相当于截取数组的前n个来使用,数组剩余元素完全无用。
第三个参数:偏移量,在此例中,如果设置偏移量为20,则第一段划线长度为40,第一个间隔为40,以此类推。
静态指南针
先看下最后完成的效果:
拆分来看,包含圆、三角形的绘制,是UIBezierPath的基本应用,唯一有一丢丢技巧的是刻度绘制,这就要用到前面虚线绘制的方法了。
罗盘轮廓
很简单,用init(ovalIn:)方法创建一个圆形,填充、描边。
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()
加一下罗盘上的文字,这部分代码就不展示了:
指针
这里分为两部分绘制,蓝色部分和红色部分,每部分path添加两条线即可,且无需用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()
罗盘刻度
通过观察发现,罗盘刻度分为两类,一类是四个字母对应的大刻度,一类是密集的小刻度,对于每类刻度,刻度间间隔相同,刻度粗细也相同,可以通过将圆形路径绘制为虚线的方法分别绘制,这里要注意把虚线间间隔算准了。
圆的0点参照官方文档中的图:
大刻度绘制:
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()
我设置的刻度宽度为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