iOS UIKit中如何用Bezier Path实现左侧内凹曲线?
解决UIKit中左侧内凹曲线的实现问题
你的问题在于用了两个独立的CAShapeLayer分别绘制左侧圆形和右侧弧形,导致形状重叠、描边重复,且左侧内凹用贝塞尔曲线(addCurve)难以精确控制弧度。正确的做法是将整个形状合并为一个闭合的UIBezierPath,用反向圆弧实现左侧内凹,只用一个图层渲染即可。
修改后的完整代码
class ArcView : UIView { override init(frame: CGRect) { super.init(frame: frame) } required init?(coder: NSCoder) { super.init(coder: coder) } func setupViewWith(textToDisplay: String, imageNamed: String, backgroundColor: UIColor){ setupView(backgroundColor: backgroundColor) } func setupView(backgroundColor: UIColor){ // 用单一图层绘制完整路径 let fullPath = getFullPath() let shapeLayer = CAShapeLayer() shapeLayer.path = fullPath.cgPath shapeLayer.lineWidth = 1.5 shapeLayer.strokeColor = UIColor.white.cgColor shapeLayer.fillColor = backgroundColor.cgColor self.layer.addSublayer(shapeLayer) } // 生成完整的闭合路径:左侧内凹圆弧 + 右侧外凸圆弧 + 直线连接 func getFullPath() -> UIBezierPath { let height = bounds.height let width = bounds.width let halfHeight = height / 2.0 // 左侧内凹圆弧参数:圆心在view垂直中线、左侧边缘外(半径等于半高) let leftArcCenter = CGPoint(x: halfHeight, y: halfHeight) let leftArcRadius = halfHeight // 右侧外凸圆弧参数:和你原来的逻辑一致 let rightArcCenter = CGPoint(x: width - halfHeight, y: halfHeight) let rightArcRadius = halfHeight let path = UIBezierPath() // 起点:左侧内凹圆弧的顶部端点 let leftTopPoint = CGPoint(x: leftArcCenter.x + leftArcRadius, y: 0) path.move(to: leftTopPoint) // 画直线到右侧外凸圆弧的顶部端点 let rightTopPoint = CGPoint(x: rightArcCenter.x - rightArcRadius, y: 0) path.addLine(to: rightTopPoint) // 绘制右侧外凸圆弧(顺时针从顶部到底部) path.addArc(withCenter: rightArcCenter, radius: rightArcRadius, startAngle: .pi * 1.5, endAngle: .pi * 0.5, clockwise: true) // 画直线到左侧内凹圆弧的底部端点 let leftBottomPoint = CGPoint(x: leftArcCenter.x + leftArcRadius, y: height) path.addLine(to: leftBottomPoint) // 绘制左侧内凹圆弧(逆时针从底部到顶部,形成内凹效果) path.addArc(withCenter: leftArcCenter, radius: leftArcRadius, startAngle: .pi * 0.5, endAngle: .pi * 1.5, clockwise: false) path.close() return path } } extension CGFloat { func toRadians() -> CGFloat { return self * CGFloat(Double.pi) / 180.0 } }
关键修改说明
- 合并路径:把原来的两个独立路径合并为一个闭合路径,避免图层重叠导致的视觉错误
- 内凹圆弧实现:用
addArc并设置clockwise: false,从底部逆时针绘制到顶部,形成精准的内凹弧度,替代原来难以控制的贝塞尔曲线 - 使用bounds:改用
self.bounds获取尺寸,适配布局变化时的视图大小调整 - 单一图层:只用一个
CAShapeLayer渲染,保证描边连续、填充统一
内容的提问来源于stack exchange,提问作者Karthi Rasu
相关产品推荐
相关产品推荐

