How to Draw a Just the Corners of a Rectangle (Without Lines Connecting Them)

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

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.

custom view - rounding rectangle's corners drawn by lines

When drawing an arc, you need to specify the full bounding box for that arc, and the start and sweep angle. I try to see them visually, like so:

arcTo angles

E.g. when going clock wise, the start angle is positioned 180degrees from the origin. And from the startAngle, if you sweep 90 degrees clock wise, you'll end up at the desired end position.

Take note where the origin, startAngle and sweepAngle are in this graphic.
In kotlin, it can look something like this:

// Given some radius, viewWidth and viewHeight
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
path.apply {
moveTo(radius, 0F)
lineTo(viewWidth - radius, 0F)
arcTo(viewWidth - 2 * radius, 0F, viewWidth, 2 * radius, -90F, 90F, false)
lineTo(viewWidth, radius)
arcTo(viewWidth - 2 * radius, viewHeight - 2 * radius, viewWidth, viewHeight, 0F, 90F, false)
lineTo(radius, viewHeight)
arcTo(0F, viewHeight - 2 * radius, 2 * radius, viewHeight, 90F, 90F, false)
lineTo(0F, radius)
arcTo(0F, 0F, 2 * radius, 2 * radius, 180F, 90F, false)
}

canvas?.drawPath(path, linePaint)
}

And the result will be something like this:

Sample Image

Draw only corner of a rectangle

You can draw it by yourself by DrawLine function in Paint event handler, something like this:

Pen pen = new Pen(Color.Red);

private void Form1_Load(object sender, System.EventArgs e)
{
pictureBox1.Paint += new System.Windows.Forms.PaintEventHandler(this.pictureBox1_Paint);

pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
}

private void pictureBox1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
Graphics g = e.Graphics;

g.DrawLine(pen, 0, 0, pictureBox1.Right, 0);

g.DrawLine(pen, 0, 0, 0, pictureBox1.Bottom);
}

It's a use case, maybe you need other coordinates, but you can fix it easily.

How to use android canvas to draw a Rectangle with only topleft and topright corners round?

You can draw that piece by piece using drawLine() and drawArc() functions from the Canvas.

How do I draw a rounded rectangle without filling it (in MFC)?

Just select a NULL brush before drawing the rounded rectangle, like

CPen pen;
CBrush* pOldBrush;
CPen* pOldPen;
if (!pen.CreatePenIndirect(&m_logpen))
return;
pOldBrush = (CBrush*)pDC->SelectStockObject(NULL_BRUSH);
pOldPen = pDC->SelectObject(&pen);
pDC->RoundRect(m_rect, m_roundness);
pDC->SelectObject(pOldBrush);
pDC->SelectObject(pOldPen);

Drawing Rounded Corners Using UIBezierPath

Don't use a shape layer. Use a layer (or a view). Draw the UIBezierPath's path into it and stroke it, and then erase the bottom line by drawing it and stroking it with a .clear blend mode.

Result:

Sample Image

Code (modify as desired; I use here a clear UIView that draws the shape as its draw code):

let p = UIBezierPath(roundedRect: self.bounds,
byRoundingCorners: [.topLeft, .topRight],
cornerRadii: CGSize(width: 4.0, height: 4.0))
UIColor.white.setStroke()
p.stroke()
let p2 = UIBezierPath()
p2.move(to: CGPoint(x:0, y:self.bounds.height))
p2.addLine(to: CGPoint(x:self.bounds.width, y:self.bounds.height))
p2.lineWidth = 2
p2.stroke(with: .clear, alpha: 1)

EDIT Another way would have been to clip out the bottom line area before drawing the rounded rect:

let p1 = UIBezierPath(rect: CGRect(origin:.zero,
size:CGSize(width:self.bounds.width, height:self.bounds.height-2)))
p1.addClip()
let p = UIBezierPath(roundedRect: self.bounds,
byRoundingCorners: [.topLeft, .topRight],
cornerRadii: CGSize(width: 4.0, height: 4.0))
UIColor.white.setStroke()
p.stroke()


Related Topics



Leave a reply



Submit