如何为UIBezierPath绘制的圆弧设置5pt的自定义圆角?
解决圆弧两端固定5pt圆角的问题
要实现圆弧两端固定5pt的圆角,不能依赖shapeLayer.lineCap = .round(它的圆角大小与线宽绑定,等于线宽的一半),需要手动构建包含两端小半圆的完整路径,步骤如下:
核心思路
- 计算主圆弧的调整后起止角度:因为要在两端添加半径5pt的小圆角,主圆弧需要向内收缩一段角度,这个角度差可以通过三角函数推导得出(小圆角半径r=5,主圆弧半径R=原半径,角度差θ=arcsin(r/R))。
- 拼接完整路径:先绘制调整后的主圆弧,再在两端分别绘制半径5pt的小半圆,让整个路径平滑衔接。
完整实现代码
let shapeLayer = CAShapeLayer() let cornerRadius: CGFloat = 5 // 目标两端圆角大小 let lineWidth: CGFloat = 40 let mainArcRadius = rect.midX - 16 - 20 // 原主圆弧半径 // 计算主圆弧需要调整的角度差:因为两端小圆的半径是5,所以主圆弧要向内收一个角度θ let angleOffset = asin(cornerRadius / mainArcRadius) // 构造完整路径 let path = UIBezierPath() // 1. 绘制调整后的主圆弧:起始角度增加angleOffset,结束角度减少angleOffset path.addArc( withCenter: CGPoint(x: rect.midX, y: rect.maxY), radius: mainArcRadius, startAngle: .pi + angleOffset, endAngle: 2 * .pi - angleOffset, clockwise: true ) // 2. 绘制起点的小半圆(左侧圆角) let startPoint = path.currentPoint path.addArc( withCenter: CGPoint(x: startPoint.x + cornerRadius, y: startPoint.y), radius: cornerRadius, startAngle: .pi, endAngle: 0, clockwise: false ) // 3. 绘制终点的小半圆(右侧圆角) let endPoint = path.currentPoint path.addArc( withCenter: CGPoint(x: endPoint.x - cornerRadius, y: endPoint.y), radius: cornerRadius, startAngle: 0, endAngle: .pi, clockwise: false ) // 设置shapeLayer属性 shapeLayer.path = path.cgPath shapeLayer.strokeColor = UIColor.yellow.cgColor shapeLayer.lineWidth = lineWidth shapeLayer.fillColor = UIColor.clear.cgColor // 这里不需要设置lineCap,因为两端的圆角已经手动绘制完成 shapeLayer.lineJoin = .round // 确保主圆弧和小半圆衔接处平滑 layer.addSublayer(shapeLayer)
代码说明
- 角度差计算:
angleOffset = asin(cornerRadius / mainArcRadius),利用直角三角形的正弦函数,算出主圆弧需要向内收缩的角度,保证两端小半圆能完美衔接。 - 路径拼接:先画主圆弧,再分别在起点和终点绘制小半圆,小半圆的圆心位置通过当前路径点偏移得出,方向设置为逆时针,确保和主圆弧的走向匹配。
- 移除lineCap设置:因为两端的圆角已经手动绘制,不需要依赖系统的lineCap,同时设置
lineJoin = .round保证衔接处无棱角。
内容的提问来源于stack exchange,提问作者jmindeveloper
相关产品推荐
相关产品推荐

