我设法创造圆角,但我遇到第一个圆角(右下角)的问题
问题:
这是我自定义矩形的代码和截图:
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()
答案 0 :(得分:17)
我认为你所做的事情过于复杂。 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)
答案 1 :(得分:8)
一些观察结果:
确保使用bounds
视图并将其插入线宽的一半。这样可以确保整个描边边框都位于视图的bounds
之内。如果您的线宽为1,可能不会那么明显,但是如果线宽较大,则问题会变得更加明显。
如果使用draw(_:)
方法,请不要使用传递给该方法的rect
,而应参考bounds
(如上所述,插图)。传递给CGRect
的{{1}}是要绘制的矩形,不一定是完整的draw(_:)
。 (通常但并非总是如此,因此总是引用视图的bounds
,而不是传递给此方法的bounds
。)
the documentation说(强调):
视图边界中需要更新的部分。第一次绘制视图时,此矩形通常是视图的整个可见范围。 但是,在随后的绘图操作中,矩形可能仅指定视图的一部分。
我将给视图的所有各种属性提供一个rect
观察者,该观察者将触发重新绘制视图。这样,任何IB覆盖或以编程方式设置的值都将自动反映在结果视图中。
如果需要,您可以制作整个didSet
,并制作属性@IBDesignable
,以便可以在Interface Builder中看到它。这不是必需的,但是如果您希望在情节提要或NIB中看到此效果,则很有用。
恕我直言,虽然您可以使用圆弧圆角,但是使用四边形曲线更容易。您只需指定弧的结束点和矩形的角,然后二次贝塞尔曲线将产生一个很好的圆角。使用此技术,无需计算角度或圆弧的中心。
因此:
@IBInspectable
结果是:
答案 2 :(得分:7)
没关系,我实际上找到了解决方案。
而不是用直线启动代码:
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.closePath()
以下是代码和屏幕截图:
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()
答案 3 :(得分:2)
Swift 5 ,其中包含配置变量:
override func draw(_ rect: CGRect) {
let arrowXOffset: CGFloat = 13
let cornerRadius: CGFloat = 6
let arrowHeight: CGFloat = 6
let mainRect = CGRect(origin: rect.origin, size: CGSize(width: rect.width, height: rect.height - arrowHeight))
let leftTopPoint = mainRect.origin
let rightTopPoint = CGPoint(x: mainRect.maxX, y: mainRect.minY)
let rightBottomPoint = CGPoint(x: mainRect.maxX, y: mainRect.maxY)
let leftBottomPoint = CGPoint(x: mainRect.minX, y: mainRect.maxY)
let leftArrowPoint = CGPoint(x: leftBottomPoint.x + arrowXOffset, y: leftBottomPoint.y)
let centerArrowPoint = CGPoint(x: leftArrowPoint.x + arrowHeight, y: leftArrowPoint.y + arrowHeight)
let rightArrowPoint = CGPoint(x: leftArrowPoint.x + 2 * arrowHeight, y: leftArrowPoint.y)
let path = UIBezierPath()
path.addArc(withCenter: CGPoint(x: rightTopPoint.x - cornerRadius, y: rightTopPoint.y + cornerRadius), radius: cornerRadius,
startAngle: CGFloat(3 * Double.pi / 2), endAngle: CGFloat(2 * Double.pi), clockwise: true)
path.addArc(withCenter: CGPoint(x: rightBottomPoint.x - cornerRadius, y: rightBottomPoint.y - cornerRadius), radius: cornerRadius,
startAngle: 0, endAngle: CGFloat(Double.pi / 2), clockwise: true)
path.addLine(to: rightArrowPoint)
path.addLine(to: centerArrowPoint)
path.addLine(to: leftArrowPoint)
path.addArc(withCenter: CGPoint(x: leftBottomPoint.x + cornerRadius, y: leftBottomPoint.y - cornerRadius), radius: cornerRadius,
startAngle: CGFloat(Double.pi / 2), endAngle: CGFloat(Double.pi), clockwise: true)
path.addArc(withCenter: CGPoint(x: leftTopPoint.x + cornerRadius, y: leftTopPoint.y + cornerRadius), radius: cornerRadius,
startAngle: CGFloat(Double.pi), endAngle: CGFloat(3 * Double.pi / 2), clockwise: true)
path.addLine(to: rightTopPoint)
path.close()
}
答案 4 :(得分:1)
您无法自动执行此操作。您必须缩短线条,然后使用您想要角半径的半径弧。
因此。您可以将线添加到x-radius,y,而不是向x,y添加线。 然后添加弧。然后下一行从x,y +半径开始。