如何将圆角添加到UIBezierPath自定义矩形?

Azi*_*ode 14 ios uibezierpath swift

我设法创造圆角,但我遇到第一个圆角(右下角)的问题

题 :

  • 我可以在(moveToPoint)方法之前添加(addArcWithCenter)方法吗?
  • 如何摆脱矩形开头的直线(右下角)?

这是我的自定义矩形代码和截图:

let path = UIBezierPath()
path.moveToPoint(CGPoint(x: 300, y: 0))
path.addArcWithCenter(CGPoint(x: 300-10, y: 50), radius: 10 , startAngle: 0 , endAngle: CGFloat(M_PI/2)  , clockwise: true) //1st rounded corner
path.addArcWithCenter(CGPoint(x: 200, y: 50), radius:10, startAngle: CGFloat(2 * M_PI / 3), endAngle:CGFloat(M_PI) , clockwise: true)// 2rd rounded corner
path.addArcWithCenter(CGPoint(x: 200, y: 10), radius:10, startAngle: CGFloat(M_PI), endAngle:CGFloat(3 * M_PI / 2), clockwise: true)// 3rd rounded corner
// little triangle at the bottom
path.addLineToPoint(CGPoint(x:240 , y:0))
path.addLineToPoint(CGPoint(x: 245, y: -10))
path.addLineToPoint(CGPoint(x:250, y: 0))
path.addArcWithCenter(CGPoint(x: 290, y: 10), radius: 10, startAngle: CGFloat(3 * M_PI / 2), endAngle: CGFloat(2 * M_PI ), clockwise: true)
path.closePath()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

mat*_*att 18

我认为你所做的事情过于复杂.UIBezierPath为您提供了UIBezierPath(roundedRect:)为什么不使用它?描边圆角矩形; 擦掉你要放小三角形的地方; 添加三角形; 填补复合路径; 并划过三角形缺失的两边.像这样(这只是我碰巧躺在的一些代码 - 当然你应该改变数字以适应你的形状):

let con = UIGraphicsGetCurrentContext()
CGContextTranslateCTM(con, 10, 10)
UIColor.blueColor().setStroke()
UIColor.blueColor().colorWithAlphaComponent(0.4).setFill()
let p = UIBezierPath(roundedRect: CGRectMake(0,0,250,180), cornerRadius: 10)
p.stroke()
CGContextClearRect(con, CGRectMake(20,170,10,11))
let pts = [
    CGPointMake(20,180), CGPointMake(20,200),
    CGPointMake(20,200), CGPointMake(30,180)
]
p.moveToPoint(pts[0])
p.addLineToPoint(pts[1])
p.addLineToPoint(pts[3])
p.fill()
CGContextStrokeLineSegments(con, pts, 4)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


Rob*_*Rob 14

几个观察:

  1. 确保您获取视图bounds并将其插入线宽的一半。这确保了整个描边边框落在bounds视图的范围内。如果您的线宽为 1,这可能不那么明显,但是如果线宽更大,问题就会变得更加明显。

  2. 如果使用draw(_:)方法,请不要使用rect传递给此方法的 ,而是参考bounds(插图,如上所述)。该CGRect传递给draw(_:)正在绘制的矩形,不一定全面bounds。(通常是,但并非总是如此,所以总是引用bounds视图的 ,而不是rect传递给此方法的。)

    正如文档所说(强调):

    需要更新的视图边界部分。第一次绘制视图时,此矩形通常是视图的整个可见边界。但是,在后续的绘制操作中,矩形可能仅指定视图的一部分。

  3. 我会给视图的所有各种属性一个didSet观察者,它将触发视图重绘。这样,任何 IB 覆盖或以编程方式设置的值都将自动反映在结果视图中。

  4. 如果你愿意,你可以制作整个东西@IBDesignable并制作 properties @IBInspectable,所以你可以在 Interface Builder 中看到它的呈现。这不是必需的,但如果您想在故事板或 NIB 中看到它的呈现,它会很有用。

  5. 虽然您可以使用圆弧圆角,但使用四边形曲线更容易,恕我直言。您只需指定圆弧的结束位置和矩形的角,二次贝塞尔曲线将产生一个很好的圆角。使用这种技术,不需要计算角度或圆弧的中心。

因此:

@IBDesignable
class BubbleView: UIView {
    @IBInspectable var lineWidth:    CGFloat = 1       { didSet { setNeedsDisplay() } }
    @IBInspectable var cornerRadius: CGFloat = 10      { didSet { setNeedsDisplay() } }
    @IBInspectable var calloutSize:  CGFloat = 5       { didSet { setNeedsDisplay() } }
    @IBInspectable var fillColor:    UIColor = .yellow { didSet { setNeedsDisplay() } }
    @IBInspectable var strokeColor:  UIColor = .black  { didSet { setNeedsDisplay() } }

    override func draw(_ rect: CGRect) {
        let rect = bounds.insetBy(dx: lineWidth / 2, dy: lineWidth / 2)
        let path = UIBezierPath()

        // lower left corner
        path.move(to: CGPoint(x: rect.minX + cornerRadius, y: rect.maxY - calloutSize))
        path.addQuadCurve(to: CGPoint(x: rect.minX, y: rect.maxY - calloutSize - cornerRadius),
                          controlPoint: CGPoint(x: rect.minX, y: rect.maxY - calloutSize))

        // left
        path.addLine(to: CGPoint(x: rect.minX, y: rect.minY + cornerRadius))

        // upper left corner
        path.addQuadCurve(to: CGPoint(x: rect.minX + cornerRadius, y: rect.minY),
                          controlPoint: CGPoint(x: rect.minX, y: rect.minY))

        // top
        path.addLine(to: CGPoint(x: rect.maxX - cornerRadius, y: rect.minY))

        // upper right corner
        path.addQuadCurve(to: CGPoint(x: rect.maxX, y: rect.minY + cornerRadius),
                          controlPoint: CGPoint(x: rect.maxX, y: rect.minY))

        // right
        path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY - calloutSize - cornerRadius))

        // lower right corner
        path.addQuadCurve(to: CGPoint(x: rect.maxX - cornerRadius, y: rect.maxY - calloutSize),
                          controlPoint: CGPoint(x: rect.maxX, y: rect.maxY - calloutSize))

        // bottom (including callout)
        path.addLine(to: CGPoint(x: rect.midX + calloutSize, y: rect.maxY - calloutSize))
        path.addLine(to: CGPoint(x: rect.midX, y: rect.maxY))
        path.addLine(to: CGPoint(x: rect.midX - calloutSize, y: rect.maxY - calloutSize))
        path.close()

        fillColor.setFill()
        path.fill()

        strokeColor.setStroke()
        path.lineWidth = lineWidth
        path.stroke()
    }
}
Run Code Online (Sandbox Code Playgroud)

这产生:

在此处输入图片说明


Azi*_*ode 9

没关系,我实际上找到了解决方案.

而不是用直线启动代码:

path.moveToPoint(CGPoint(x: 300, y: 0))
Run Code Online (Sandbox Code Playgroud)

我改为以弧形开始(右上角):

path.addArcWithCenter(CGPoint(x: 300-10, y: 50), radius: 10 , startAngle: 0 , endAngle: CGFloat(M_PI/2)  , clockwise: true) //1st rounded corner
Run Code Online (Sandbox Code Playgroud)

通过这样做,我有四个圆角,我只需要在代码的末尾添加一条直线:

path.closePath()  
Run Code Online (Sandbox Code Playgroud)

这是代码和截图:

let path = UIBezierPath()
path.addArcWithCenter(CGPoint(x: 300-10, y: 50), radius: 10 , startAngle: 0 , endAngle: CGFloat(M_PI/2)  , clockwise: true) //1st rounded corner
path.addArcWithCenter(CGPoint(x: 200, y: 50), radius:10, startAngle: CGFloat(2 * M_PI / 3), endAngle:CGFloat(M_PI) , clockwise: true)// 2rd rounded corner
path.addArcWithCenter(CGPoint(x: 200, y: 10), radius:10, startAngle: CGFloat(M_PI), endAngle:CGFloat(3 * M_PI / 2), clockwise: true)// 3rd rounded corner
// little triangle
path.addLineToPoint(CGPoint(x:240 , y:0))
path.addLineToPoint(CGPoint(x: 245, y: -10))
path.addLineToPoint(CGPoint(x:250, y: 0))
path.addArcWithCenter(CGPoint(x: 290, y: 10), radius: 10, startAngle: CGFloat(3 * M_PI / 2), endAngle: CGFloat(2 * M_PI ), clockwise: true)
path.addLineToPoint(CGPoint(x:300 , y:50))
path.closePath()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述