iOS-Swift知识之 UIBezierPath贝塞尔曲线常用方法详解
背景
iOS开发中,经常会遇到要制作一些图形,比方矩形,圆形,椭圆,弧或许不规则的多边形,这时咱们能够经过重写UIView的draw(_ rect: CGRect)办法,然后经过UIBezierPath来制作。
UIBezierPath这个类在UIKit中, 是Core Graphics结构关于path的一个封装。
关于iOS绘图原理,能够查看博主的这篇文章 iOS底层原理之 UIView制作显示原理流程解析以及性能优化
根本属性和办法阐明
1 UIColor.red.set()
设置线条色彩,也便是画笔色彩。
2 lineWidth
线宽
3 lineCapStyle
线帽款式,是CGLineCap类型的枚举,界说如下
public enum CGLineCap : Int32, @unchecked Sendable {
/// 指定不制作端点,即线条结尾处直接完毕。
case butt = 0
/// 制作圆形端点,即线条结尾处制作一个直径为线条宽度的半圆
case round = 1
/// 制作方形端点,即线条结尾处制作半个边长为线条宽度的正方形。
/// 需要阐明的是,这种形状的端点与“butt”形状的端点十分相似,只是采用这种形式的端点的线条略长一点而已
case square = 2
}
作用如下,次序和枚举次序一一对应
4 lineJoinStyle
线衔接款式,即角落款式,是CGLineJoin类型的枚举,界说如下
public enum CGLineJoin : Int32, @unchecked Sendable {
/// 尖角
case miter = 0
/// 圆角
case round = 1
/// 缺角
case bevel = 2
}
作用如下,次序和枚举次序一一对应
5 stroke()
stroke 得到的是不被填充的view,即只会制作曲线路线。
6 fill()
fill 得到的内部被填充的 view,即会将曲线构成的几何图形,填充满画笔色彩。
制作矩形
经过init(rect: CGRect)办法制作,代码如下
override func draw(_ rect: CGRect) {
UIColor.red.set()
let path1 = UIBezierPath(rect: CGRect(x: 100, y: 100, width: 200, height: 100))
path1.lineWidth = 5.0
path1.lineCapStyle = .round
path1.lineJoinStyle = .round
path1.stroke()
let path2 = UIBezierPath(rect: CGRect(x: 100, y: 230, width: 200, height: 200))
path2.lineWidth = 5.0
path2.lineCapStyle = .round
path2.lineJoinStyle = .round
path2.fill()
}
制作带圆角的矩形
有两种方式,假如四个角都需要圆角,能够经过init(roundedRect rect: CGRect, cornerRadius: CGFloat)办法制作。
假如只需要某些圆角,则能够经过init(roundedRect rect: CGRect, byRoundingCorners corners: UIRectCorner, cornerRadii: CGSize)办法制作。
代码如下
override func draw(_ rect: CGRect) {
UIColor.red.set()
let path1 = UIBezierPath(roundedRect: CGRect(x: 100, y: 100, width: 200, height: 100), cornerRadius: 10)
path1.lineWidth = 5.0
path1.lineCapStyle = .round
path1.lineJoinStyle = .round
path1.stroke()
let path2 = UIBezierPath(roundedRect: CGRect(x: 100, y: 230, width: 200, height: 200), byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize(width: 10, height: 10))
path2.lineWidth = 5.0
path2.lineCapStyle = .round
path2.lineJoinStyle = .round
path2.fill()
}
制作多边形
经过move(to point: CGPoint)和addLine(to point: CGPoint)办法制作,moveToPoint:这个办法是设置开端点,意味着从这个点开端。addLineToPoint:设置想要创立的多边形经过的点,也便是两线相交的那个点,能够接连创立line,每一个line的起点都是先前的结尾,结尾便是指定的点,将线段衔接起来便是咱们想要创立的多边形了。最终第五条线是用path.close()得到的,closePath办法不仅完毕一个shape的subpath表述,它也在最终一个点和第一个点之间画一条线段,这是一个便当的办法,咱们不需要去画最终一条线了。代码如下
override func draw(_ rect: CGRect) {
UIColor.red.set()
let path = UIBezierPath()
path.lineWidth = 5.0
path.lineCapStyle = .round
path.lineJoinStyle = .round
path.move(to: CGPoint(x: 100, y: 300))
path.addLine(to: CGPoint(x: 200, y: 200))
path.addLine(to: CGPoint(x: 300, y: 300))
path.addLine(to: CGPoint(x: 260, y: 400))
path.addLine(to: CGPoint(x: 140, y: 400))
path.close()
path.fill()
}
制作椭圆
经过init(ovalIn rect: CGRect)办法制作,假如传入的rect是一个矩形,则得到矩形的内切椭圆,假如传入的rect是一个正方形,则得到正方形的内切圆。代码如下
override func draw(_ rect: CGRect) {
UIColor.red.set()
let path1 = UIBezierPath(ovalIn: CGRect(x: 100, y: 100, width: 200, height: 100))
path1.lineWidth = 5.0
path1.lineCapStyle = .round
path1.lineJoinStyle = .round
path1.stroke()
let path2 = UIBezierPath(ovalIn: CGRect(x: 100, y: 230, width: 200, height: 200))
path2.lineWidth = 5.0
path2.lineCapStyle = .round
path2.lineJoinStyle = .round
path2.fill()
}
制作一段弧线
经过init(arcCenter center: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat, clockwise: Bool)办法制作,其间arcCenter指圆心坐标,radius指圆的半径,startAngle指圆弧的开端视点,endAngle指圆弧的完毕视点,clockwise指是否顺时针方向制作。其间圆弧的视点参考系如下
代码如下
override func draw(_ rect: CGRect) {
UIColor.red.set()
let path1 = UIBezierPath(arcCenter: CGPoint(x: 200, y: 250), radius: 100, startAngle: 180 / 180 * .pi, endAngle: 45 / 180 * .pi, clockwise: true)
path1.lineWidth = 5.0
path1.lineCapStyle = .round
path1.lineJoinStyle = .round
path1.stroke()
let path2 = UIBezierPath(arcCenter: CGPoint(x: 200, y: 450), radius: 100, startAngle: 0, endAngle: 2 * .pi, clockwise: true)
path2.lineWidth = 5.0
path2.lineCapStyle = .round
path2.lineJoinStyle = .round
path2.fill()
}
制作二次贝塞尔曲线
经过addQuadCurve(to endPoint: CGPoint, controlPoint: CGPoint)办法制作,曲线段在当时点开端,在指定的点完毕,一个控制点的切线界说,图示如下
代码如下
override func draw(_ rect: CGRect) {
UIColor.red.set()
let path1 = UIBezierPath()
path1.lineWidth = 5.0
path1.lineCapStyle = .round
path1.lineJoinStyle = .round
path1.move(to: CGPoint(x: 100, y: 200))
path1.addQuadCurve(to: CGPoint(x: 300, y: 200), controlPoint: CGPoint(x: 100, y: 100))
path1.stroke()
let path2 = UIBezierPath()
path2.lineWidth = 5.0
path2.lineCapStyle = .round
path2.lineJoinStyle = .round
path2.move(to: CGPoint(x: 100, y: 250))
path2.addQuadCurve(to: CGPoint(x: 300, y: 250), controlPoint: CGPoint(x: 250, y: 400))
path2.fill()
}
制作三次贝塞尔曲线
经过addCurve(to endPoint: CGPoint, controlPoint1: CGPoint, controlPoint2: CGPoint)办法制作,曲线段在当时点开端,在指定的点完毕,两个控制点的切线界说,图示如下
代码如下
override func draw(_ rect: CGRect) {
UIColor.red.set()
let path1 = UIBezierPath()
path1.lineWidth = 5.0
path1.lineCapStyle = .round
path1.lineJoinStyle = .round
path1.move(to: CGPoint(x: 100, y: 200))
path1.addCurve(to: CGPoint(x: 300, y: 200), controlPoint1: CGPoint(x: 150, y: 50), controlPoint2: CGPoint(x: 250, y: 350))
path1.stroke()
let path2 = UIBezierPath()
path2.lineWidth = 5.0
path2.lineCapStyle = .round
path2.lineJoinStyle = .round
path2.move(to: CGPoint(x: 100, y: 350))
path2.addCurve(to: CGPoint(x: 300, y: 350), controlPoint1: CGPoint(x: 150, y: 200), controlPoint2: CGPoint(x: 250, y: 500))
path2.fill()
}
制作虚线
经过setLineDash(_ pattern: UnsafePointer?, count: Int, phase: CGFloat)办法制作。
其间pattern是C款式的浮点值数组,包含线段和形式中的空隙的长度(以点为单位)。 数组中的值交替,从第一个线段长度开端,后跟第一个空隙长度,后跟第二个线段长度,依此类推。
count是形式中的值的数量,即虚线数组元素个数。
phase是虚线开端的方位,即开端制作图画的偏移量,沿着虚线图画的点测量。 例如,图画5-2-3-2的相位值phase为6将导致绘图在第一个空隙的中心开端。
代码如下
override func draw(_ rect: CGRect) {
UIColor.red.set()
let path1 = UIBezierPath()
path1.lineWidth = 5.0
path1.lineCapStyle = .round
path1.lineJoinStyle = .round
path1.move(to: CGPoint(x: 50, y: 200))
path1.addLine(to: CGPoint(x: 400, y: 200))
var dashConfig1:[CGFloat] = [10.0, 15.0]
path1.setLineDash(&dashConfig1, count: dashConfig1.count, phase: 0)
path1.stroke()
let path2 = UIBezierPath()
path2.lineWidth = 5.0
path2.lineCapStyle = .round
path2.lineJoinStyle = .round
path2.move(to: CGPoint(x: 50, y: 250))
path2.addLine(to: CGPoint(x: 400, y: 250))
var dashConfig2:[CGFloat] = [10.0, 15.0, 15.0, 25.0]
path2.setLineDash(&dashConfig2, count: dashConfig2.count, phase: 0)
path2.stroke()
}