Detailed explanation of common methods of UIBezierPath Bezier curve for iOS knowledge literacy

background

In iOS development, it is often encountered to draw some graphics, such as rectangles, circles, ellipses, arcs or irregular polygons. At this time, we can rewrite the draw(_ rect: CGRect) method of UIView, and then use UIBezierPath to draw.

UIBezierPath is a class in UIKit, which is an encapsulation of paths in the Core Graphics framework.

Regarding the principle of iOS drawing, you can check this blogger's article : UIView drawing and display principle of the underlying principle of iOS, process analysis and performance optimization

Basic properties and method descriptions

1 UIColor.red.set()

Set the line color, which is the brush color.

2 lineWidth

Line width

3 lineCapStyle

Line cap style, an enumeration of type CGLineCap, defined as follows

public enum CGLineCap : Int32, @unchecked Sendable {
    
    /// 指定不绘制端点,即线条结尾处直接结束。
    case butt    = 0

    /// 绘制圆形端点,即线条结尾处绘制一个直径为线条宽度的半圆
    case round   = 1

    /// 绘制方形端点,即线条结尾处绘制半个边长为线条宽度的正方形。
    /// 需要说明的是,这种形状的端点与“butt”形状的端点十分相似,只是采用这种形式的端点的线条略长一点而已
    case square  = 2
}
复制代码

The effect is as follows, the order corresponds to the enumeration order one by one

4 lineJoinStyle

The line join style, that is, the corner style, is an enumeration of type CGLineJoin and is defined as follows

public enum CGLineJoin : Int32, @unchecked Sendable {
    
    /// 尖角
    case miter = 0

    /// 圆角
    case round = 1

    /// 缺角
    case bevel = 2
}
复制代码

The effect is as follows, the order corresponds to the enumeration order one by one

5 stroke()

What stroke gets is a view that is not filled, that is, only a curved route is drawn.

6 fill()

The inner filled view obtained by fill will fill the geometric figure formed by the curve with the brush color.

draw rectangle

Draw by init(rect: CGRect) method, the code is as follows

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()
}
复制代码

Draw a rectangle with rounded corners

There are two ways. If all four corners need to be rounded, they can be drawn by the init(roundedRect rect: CGRect, cornerRadius: CGFloat) method.

If you only need some rounded corners, you can draw by init(roundedRect rect: CGRect, byRoundingCorners corners: UIRectCorner, cornerRadii: CGSize) method.

code show as below

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()
}
复制代码

draw polygon

通过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()
}
复制代码

绘制虚线

Draw by setLineDash(_ pattern: UnsafePointer?, count: Int, phase: CGFloat) method.

where pattern is a C-style array of floating point values ​​containing the lengths (in points) of line segments and gaps in the pattern. The values ​​in the array alternate, starting with the first segment length, followed by the first gap length, followed by the second segment length, and so on.

count is the number of values ​​in the pattern, i.e. the number of dotted array elements.

phase is where the dashed line starts, i.e. the offset at which to start drawing the pattern, measured along the points of the dashed pattern. For example, a phase value of 6 for the pattern 5-2-3-2 will cause the drawing to start in the middle of the first gap.

code show as below

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()
}
复制代码

Guess you like

Origin juejin.im/post/7086332791540940813