Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to draw a just the corners of a rectangle (without lines connecting them)

I have a CGRect value and need to draw a border around it. I just want the corners to be drawn without any lines connecting them.

Something like this...

enter image description here

How would I draw this figure using swift?

like image 791
coder Avatar asked Dec 02 '22 11:12

coder


2 Answers

Here's a custom UIView class that draws itself with the four corners. You can set various properties to get the look you need.

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()
    }
}

Sample usage:

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

Copy and paste that into a playground. Try different values for the properties.

like image 192
rmaddy Avatar answered Dec 22 '22 05:12

rmaddy


You draw those shapes the same way Superman gets into his tights: one leg at a time. Divide the shape into three parts: the vertical leg, the 90-degree arc that forms the rounded corner, and the horizontal leg. Now just draw each of those in turn.

I'll illustrate by showing how to draw one corner; the other three corners are similar and symmetrical and are left as an exercise for the reader.

Assume r is our rect and that we are in a drawing context (e.g. a UIView's draw(_:) or an image view graphics context). Let's make some initial assumptions (feel free to change them):

UIColor.yellow.setStroke()
let segLength : CGFloat = 40
let cornerSize : CGFloat = 10
let lineWidth : CGFloat = 6

Now we just form a bezier path describing one leg of the corner, the rounded corner arc, and the other leg of the corner, and stroke it:

 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()

The result looks like this (I've shaded the background in blue to make it easier to see, and I've zoomed in a bit):

enter image description here

The other three corners work exactly the same way, just changing the obvious things that would need to be changed.

like image 36
matt Avatar answered Dec 22 '22 05:12

matt