You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何为自定义UIBezierPath图形添加左上、右上圆角(滑块控制)

解决自定义UIBezierPath图形添加左上/右上圆角的问题

首先,咱们得先搞清楚为什么你之前的方法都不生效:

  • 你用UIBezierPath(roundedRect:byRoundingCorners:cornerRadii:)创建的路径是标准矩形,和你自定义的曲线路径完全不匹配,作为mask的话只会显示矩形的圆角区域,自然得不到你想要的效果。
  • CAShapeLayer设置cornerRadius只对矩形类路径生效,自定义曲线路径的边角系统无法自动识别,所以这个属性不会起作用。
  • 直接给ImageView加圆角,作用的是ImageView本身的矩形layer,而非你绘制的自定义图形,所以也无效。

正确解决方案:手动修改自定义路径,添加圆角圆弧

既然你的图形是用自定义UIBezierPath绘制的,咱们直接在原路径的基础上,把左上、右上的直角替换成圆角圆弧即可。以下是修改后的完整代码:

// 定义圆角半径,可根据滑块值动态调整
var cornerRadius: CGFloat = 20.0 // 这里可以替换成你的滑块传入值

// 1. 创建带圆角的自定义路径
let bezierPath = UIBezierPath()

// 处理右上圆角:从(360 - cornerRadius, 0)出发,绘制右上圆弧
bezierPath.move(to: CGPoint(x: 360 - cornerRadius, y: 0))
bezierPath.addArc(withCenter: CGPoint(x: 360 - cornerRadius, y: cornerRadius), 
                  radius: cornerRadius, 
                  startAngle: .pi * 3/2, 
                  endAngle: 0, 
                  clockwise: true)

// 继续原有的曲线绘制(从右上圆弧终点到(360,75))
bezierPath.addCurve(to: CGPoint(x: 360, y: 75), 
                    controlPoint1: CGPoint(x: 359.53, y: 30.5), 
                    controlPoint2: CGPoint(x: 359.91, y: 55.45))

// 保留原路径的剩余曲线部分
bezierPath.addCurve(to: CGPoint(x: 360, y: 153.78), 
                    controlPoint1: CGPoint(x: 360.35, y: 153.21), 
                    controlPoint2: CGPoint(x: 360, y: 153.78))
bezierPath.addCurve(to: CGPoint(x: 180, y: 153.78), 
                    controlPoint1: CGPoint(x: 360, y: 153.78), 
                    controlPoint2: CGPoint(x: 271.2, y: 212.77))
bezierPath.addCurve(to: CGPoint(x: 0, y: 153.78), 
                    controlPoint1: CGPoint(x: 88.8, y: 94.8), 
                    controlPoint2: CGPoint(x: 0, y: 153.78))

// 处理左上圆角:从(0,153.78)到(0, cornerRadius),绘制左上圆弧
bezierPath.addLine(to: CGPoint(x: 0, y: cornerRadius))
bezierPath.addArc(withCenter: CGPoint(x: cornerRadius, y: cornerRadius), 
                  radius: cornerRadius, 
                  startAngle: .pi, 
                  endAngle: .pi * 3/2, 
                  clockwise: true)

// 连接到右上圆角的起点,闭合路径
bezierPath.addLine(to: CGPoint(x: 360 - cornerRadius, y: 0))
bezierPath.close()

// 2. 填充路径(如果是直接绘制在View上)
UIColor.green.setFill()
bezierPath.fill()

// 3. 如果是作为ImageView的mask使用
let maskLayer = CAShapeLayer()
maskLayer.path = bezierPath.cgPath
self.imgTop.layer.mask = maskLayer

代码说明:

  • 我们把原路径中左上(0,0)、右上(360,0)这两个直角,替换成了用addArc(withCenter:...)绘制的圆弧。
  • 圆弧的圆心、半径、起始/结束角度都是根据圆角半径计算的,确保圆角和原路径完美衔接。
  • 你可以把cornerRadius替换成滑块的实时值,就能实现动态调整圆角大小的效果。

另一种方法:路径交集(适合复杂图形)

如果你不想修改原路径,也可以通过原路径和圆角矩形路径取交集的方式得到最终路径:

// 1. 你的原自定义路径
let originalPath = UIBezierPath()
// ... 这里是你原有的路径绘制代码 ...

// 2. 创建带左上、右上圆角的矩形路径
let roundedRectPath = UIBezierPath(roundedRect: self.imgTop.bounds, 
                                   byRoundingCorners: [.topLeft, .topRight], 
                                   cornerRadii: CGSize(width: cornerRadius, height: cornerRadius))

// 3. 取两个路径的交集
if let combinedCGPath = originalPath.cgPath.copy(using: CGPathTransform(intersect: roundedRectPath.cgPath)) {
    let finalPath = UIBezierPath(cgPath: combinedCGPath)
    // 设置mask
    let maskLayer = CAShapeLayer()
    maskLayer.path = finalPath.cgPath
    self.imgTop.layer.mask = maskLayer
}

这种方法不需要修改原路径,适合图形比较复杂的场景,但要注意路径的坐标系要保持一致。

内容的提问来源于stack exchange,提问作者Khushbu Desai

火山引擎 最新活动