UIBezierPath Triangle with rounded edges

Viewed 19458

I have designed the following code to generate a UIBezierPath. This path is used within a CAShapeLayer to mask a UIView. Note, the view's height and width are variable.

This code generates a triangle with sharp edges, but I would like to make the corners rounded. I have experimented with addArcWithCenter..., lineCapStyle and lineJoinStyle etc but nothing seems to work for me.

UIBezierPath *bezierPath = [UIBezierPath bezierPath];

CGPoint center = CGPointMake(rect.size.width / 2, 0);
CGPoint bottomLeft = CGPointMake(10, rect.size.height - 0);
CGPoint bottomRight = CGPointMake(rect.size.width - 0, rect.size.height - 0);
 
[bezierPath moveToPoint:center];
[bezierPath addLineToPoint:bottomLeft];
[bezierPath addLineToPoint:bottomRight];
[bezierPath closePath];

How do I round all the edges of a triangle in a UIBezierPath? Do I need sublayers, multiple paths etc?

I am not drawing this BezierPath so all the CGContext... functions in drawRect are not useful in this context

7 Answers

Rounded Triangle in Swift 4

A playground based on @an0's answer above.

rounded triangle in swift

import UIKit
import PlaygroundSupport
import CoreGraphics

var view = UIView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
view.backgroundColor = .black
PlaygroundPage.current.liveView = view

let triangle = CAShapeLayer()
triangle.fillColor = UIColor.systemGreen.cgColor
triangle.path = createRoundedTriangle(width: 220, height: 200, radius: 15)
triangle.position = CGPoint(x: 140, y: 130)
view.layer.addSublayer(triangle)


func createRoundedTriangle(width: CGFloat, height: CGFloat, radius: CGFloat) -> CGPath {
    // Draw the triangle path with its origin at the center.
    let point1 = CGPoint(x: -width / 2, y: height / 2)
    let point2 = CGPoint(x: 0, y: -height / 2)
    let point3 = CGPoint(x: width / 2, y: height / 2)

    let path = CGMutablePath()
    path.move(to: CGPoint(x: 0, y: height / 2))
    path.addArc(tangent1End: point1, tangent2End: point2, radius: radius)
    path.addArc(tangent1End: point2, tangent2End: point3, radius: radius)
    path.addArc(tangent1End: point3, tangent2End: point1, radius: radius)
    path.closeSubpath()

    return path
}

Rounded Triangle in swift

Base on @invisible squirrel's answer I wrote a UIView extension.

   class TriangleView: UIView { 
      override func draw(_ rect: CGRect) {
         let widthHeight = self.layer.frame.size.height

         let triangle = CAShapeLayer()
         triangle.fillColor = UIColor.black.cgColor
         triangle.path = roundedTriangle(widthHeight: widthHeight)
         triangle.position = CGPoint(x: 0, y: 0)
         self.layer.addSublayer(triangle)
      }

      func roundedTriangle(widthHeight: CGFloat) -> CGPath {
         let point1 = CGPoint(x: widthHeight/2, y:0)
         let point2 = CGPoint(x: widthHeight , y: widthHeight)
         let point3 =  CGPoint(x: 0, y: widthHeight)
    
         let path = CGMutablePath()
  
         path.move(to: CGPoint(x: 0, y: widthHeight))
         path.addArc(tangent1End: point1, tangent2End: point2, radius: 5)
         path.addArc(tangent1End: point2, tangent2End: point3, radius: 5)
         path.addArc(tangent1End: point3, tangent2End: point1, radius: 5)
         path.closeSubpath()
         return path
      }  
   }
Related