如何只绘制矩形的角落(不连接线条)

4

我有一个CGRect值并需要在它周围绘制边框。我只想画出角而没有连接它们的线。

类似这样...

enter image description here

我该如何使用Swift绘制这个图形?


你尝试过使用UIBezierPath来绘制一个角落吗? - Abizern
不,我之前只使用过UIBezierPath几次。我只用UIBezierPath画了一个完整的矩形。@Abizern - coder
1
你不能在CGRect周围绘制边框,因为它只包含有关矩形的信息而不可见。因此,你想要接收什么?CALayer、UIView? - O.Daniel
我会绘制圆角矩形并擦除线条的中间部分。 - matt
我想用CAShapleLayer或类似的东西来绘制形状。我不想要一张图片。 - coder
如果你只想要简单的角落绘制,也可以使用以下网址:https://pastebin.com/mSehYjr8 - Brandon
3个回答

14

这里是一个自定义的UIView类,它会以四个角落自己绘制。你可以设置各种属性来获得你所需的外观。

class CornerRect: UIView {
    var color = UIColor.black {
        didSet {
            setNeedsDisplay()
        }
    }
    var radius: CGFloat = 5 {
        didSet {
            setNeedsDisplay()
        }
    }
    var thickness: CGFloat = 2 {
        didSet {
            setNeedsDisplay()
        }
    }
    var length: CGFloat = 30 {
        didSet {
            setNeedsDisplay()
        }
    }

    override func draw(_ rect: CGRect) {
        color.set()

        let t2 = thickness / 2
        let path = UIBezierPath()
        // Top left
        path.move(to: CGPoint(x: t2, y: length + radius + t2))
        path.addLine(to: CGPoint(x: t2, y: radius + t2))
        path.addArc(withCenter: CGPoint(x: radius + t2, y: radius + t2), radius: radius, startAngle: CGFloat.pi, endAngle: CGFloat.pi * 3 / 2, clockwise: true)
        path.addLine(to: CGPoint(x: length + radius + t2, y: t2))

        // Top right
        path.move(to: CGPoint(x: frame.width - t2, y: length + radius + t2))
        path.addLine(to: CGPoint(x: frame.width - t2, y: radius + t2))
        path.addArc(withCenter: CGPoint(x: frame.width - radius - t2, y: radius + t2), radius: radius, startAngle: 0, endAngle: CGFloat.pi * 3 / 2, clockwise: false)
        path.addLine(to: CGPoint(x: frame.width - length - radius - t2, y: t2))

        // Bottom left
        path.move(to: CGPoint(x: t2, y: frame.height - length - radius - t2))
        path.addLine(to: CGPoint(x: t2, y: frame.height - radius - t2))
        path.addArc(withCenter: CGPoint(x: radius + t2, y: frame.height - radius - t2), radius: radius, startAngle: CGFloat.pi, endAngle: CGFloat.pi / 2, clockwise: false)
        path.addLine(to: CGPoint(x: length + radius + t2, y: frame.height - t2))

        // Bottom right
        path.move(to: CGPoint(x: frame.width - t2, y: frame.height - length - radius - t2))
        path.addLine(to: CGPoint(x: frame.width - t2, y: frame.height - radius - t2))
        path.addArc(withCenter: CGPoint(x: frame.width - radius - t2, y: frame.height - radius - t2), radius: radius, startAngle: 0, endAngle: CGFloat.pi / 2, clockwise: true)
        path.addLine(to: CGPoint(x: frame.width - length - radius - t2, y: frame.height - t2))

        path.lineWidth = thickness
        path.stroke()
    }
}

示例用法:

let cr = CornerRect(frame: CGRect(x: 0, y: 0, width: 300, height: 500))
cr.color = .yellow
cr.thickness = 5
cr.backgroundColor = .white

将其复制并粘贴到游乐场中。尝试为属性使用不同的值。


4
你可以把这些形状画出来,就像超人穿上他的紧身衣一样:一步一步地完成。将形状分为三个部分:垂直腿、90度弧线和水平腿形成的圆角。现在依次画出每个部分即可。
我将通过展示如何绘制一个圆角来说明;其他三个圆角类似且对称,留给读者作为练习。
假设r是我们的矩形,我们处于绘图环境中(例如UIView的draw(_:)或图像视图图形上下文)。让我们做出一些初始假设(随意更改):
UIColor.yellow.setStroke()
let segLength : CGFloat = 40
let cornerSize : CGFloat = 10
let lineWidth : CGFloat = 6

现在我们只需形成一个贝塞尔路径,描述圆角的一条腿、圆弧和另一条腿,并对其进行描边。
 let p = UIBezierPath()
 p.lineWidth = lineWidth
 // draw top left corner
 p.move(to: CGPoint(x:r.minX, y:r.minY + segLength + cornerSize))
 p.addLine(to: CGPoint(x:r.minX, y:r.minY + cornerSize))
 p.addArc(withCenter: CGPoint(x:r.minX + cornerSize, y:r.minY + cornerSize),
    radius: cornerSize,
    startAngle: CGFloat.pi,
    endAngle: CGFloat.pi * 3.0 / 2.0,
    clockwise: true)
p.addLine(to:CGPoint(x:r.minX + segLength + cornerSize, y:r.minY))
p.stroke()

结果看起来像这样(我已经用蓝色阴影来突出背景,并稍微放大了一点):

enter image description here

其他三个角落的操作方式完全相同,只需要更改需要更改的明显内容即可。

1

由于我花了一些时间才弄明白,所以我将分享“需要更改的显而易见的事情”,以完成其余矩形,使用@matt的答案 :)

let p = UIBezierPath()
p.lineWidth = lineWidth
// draw top left corner
p.move(to: CGPoint(x:r.minX, y:r.minY + segLength + cornerSize))
p.addLine(to: CGPoint(x:r.minX, y:r.minY + cornerSize))
p.addArc(withCenter: CGPoint(x:r.minX + cornerSize, y:r.minY + cornerSize),
            radius: cornerSize, startAngle: CGFloat.pi, endAngle: CGFloat.pi * 1.5, clockwise: true)
p.addLine(to:CGPoint(x:r.minX + segLength + cornerSize, y:r.minY))
// draw top right corner
p.move(to: CGPoint(x:r.maxX - segLength - cornerSize, y:r.minY ))
p.addLine(to: CGPoint(x:r.maxX - cornerSize, y:r.minY ))
p.addArc(withCenter: CGPoint(x:r.maxX - cornerSize, y:r.minY + cornerSize),
            radius: cornerSize, startAngle: CGFloat.pi * 1.5, endAngle: 0, clockwise: true)
p.addLine(to:CGPoint(x:r.maxX, y:r.minY + segLength + cornerSize))
// draw bottom right corner
p.move(to: CGPoint(x:r.maxX, y:r.maxY - segLength - cornerSize))
p.addLine(to: CGPoint(x:r.maxX, y:r.maxY - cornerSize ))
p.addArc(withCenter: CGPoint(x:r.maxX - cornerSize, y:r.maxY - cornerSize),
radius: cornerSize, startAngle: 0, endAngle: CGFloat.pi * 0.5, clockwise: true)
p.addLine(to:CGPoint(x:r.maxX - segLength - cornerSize, y:r.maxY))
// draw bottom left corner
p.move(to: CGPoint(x:r.minX + segLength + cornerSize, y:r.maxY))
p.addLine(to: CGPoint(x:r.minX + cornerSize, y:r.maxY ))
p.addArc(withCenter: CGPoint(x:r.minX + cornerSize, y:r.maxY - cornerSize),
radius: cornerSize, startAngle: CGFloat.pi * 0.5, endAngle: CGFloat.pi, clockwise: true)
p.addLine(to:CGPoint(x:r.minX, y:r.maxY - segLength - cornerSize))
p.stroke()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接