2

I am trying to understand how to create a triangle shape with Swift. I found this code that creates a triangle.

class TriangleLayer: CAShapeLayer {

  let innerPadding: CGFloat = 30.0  

  override init() {
    super.init()
    fillColor = Colors.red.CGColor
    strokeColor = Colors.red.CGColor
    lineWidth = 7.0
    lineCap = kCALineCapRound
    lineJoin = kCALineJoinRound
    path = trianglePathSmall.CGPath
  }

  required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }

  var trianglePathSmall: UIBezierPath {
     let trianglePath = UIBezierPath()
     trianglePath.moveToPoint(CGPoint(x: 5.0 + innerPadding, y: 95.0))     // #1
     trianglePath.addLineToPoint(CGPoint(x: 50.0, y: 12.5 + innerPadding)) // #2
     trianglePath.addLineToPoint(CGPoint(x: 95.0 - innerPadding, y: 95.0)) // #3
     trianglePath.closePath()
     return trianglePath
 }

And this code creates a shape like this enter image description here in the middle of the screen.

I tried to tweak and play around with it to understand how it works; however, at this point I realised that I got lost with the logic quite a bit. I placed the CGPoints of above triangle on an x-y axis in my head and it seems something like:

 #1 x:35, y:95          #3 x:65, y:95
           #2 x:50, y: 42.5 

But the triangle is created upside-down if I place the dots on the x-y axis.

enter image description here

What I want to achieve is what the axis tells, and I want to achieve..

         .   .                                .
                 <like this.   not this> 
           .                                .   .

senty
  • 12,385
  • 28
  • 130
  • 260
  • https://developer.apple.com/library/mac/documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_paths/dq_paths.html#//apple_ref/doc/uid/TP30001066-CH211-SW1 This is Apple's documentation for drawing in 2 dimensions. – Peter Hornsby Dec 22 '15 at 12:38
  • 1
    0,0 is in the upper left corner so the Y-axis increment downwards. – Arbitur Dec 22 '15 at 12:40
  • https://developer.apple.com/library/archive/documentation/2DDrawing/Conceptual/DrawingPrintingiOS/GraphicsDrawingOverview/GraphicsDrawingOverview.html – holex Jul 24 '18 at 13:50

3 Answers3

10

You just have the axes in your head upside down. The coordinate system starts at 0,0 and extends right in X and down in Y.

So your points are really:

           #2 x:50, y: 42.5 
 #1 x:35, y:95          #3 x:65, y:95

to get your desired triangle you'd have something like:

 #1 x:35, y:95          #3 x:65, y:95
           #2 x:50, y: 147.5 
Wain
  • 118,658
  • 15
  • 128
  • 151
1

Result triangles

Code in swift5

//TriangleView

extension UIView {

    func setRightTriangle(targetView:UIView?){
        let heightWidth = targetView!.frame.size.width //you can use triangleView.frame.size.height
        let path = CGMutablePath()

        path.move(to: CGPoint(x: heightWidth/2, y: 0))
        path.addLine(to: CGPoint(x:heightWidth, y: heightWidth/2))
        path.addLine(to: CGPoint(x:heightWidth/2, y:heightWidth))
        path.addLine(to: CGPoint(x:heightWidth/2, y:0))

        let shape = CAShapeLayer()
        shape.path = path
        shape.fillColor = UIColor.blue.cgColor

        targetView!.layer.insertSublayer(shape, at: 0)
    }

    func setLeftTriangle(targetView:UIView?){
        let heightWidth = targetView!.frame.size.width
        let path = CGMutablePath()

        path.move(to: CGPoint(x: heightWidth/2, y: 0))
        path.addLine(to: CGPoint(x:0, y: heightWidth/2))
        path.addLine(to: CGPoint(x:heightWidth/2, y:heightWidth))
        path.addLine(to: CGPoint(x:heightWidth/2, y:0))

        let shape = CAShapeLayer()
        shape.path = path
        shape.fillColor = UIColor.blue.cgColor

        targetView!.layer.insertSublayer(shape, at: 0)
    }

    func setUpTriangle(targetView:UIView?){
     let heightWidth = targetView!.frame.size.width
        let path = CGMutablePath()

        path.move(to: CGPoint(x: 0, y: heightWidth))
        path.addLine(to: CGPoint(x:heightWidth/2, y: heightWidth/2))
        path.addLine(to: CGPoint(x:heightWidth, y:heightWidth))
        path.addLine(to: CGPoint(x:0, y:heightWidth))

        let shape = CAShapeLayer()
        shape.path = path
        shape.fillColor = UIColor.blue.cgColor

        targetView!.layer.insertSublayer(shape, at: 0)
    }

    func setDownTriangle(targetView:UIView?){
        let heightWidth = targetView!.frame.size.width
        let path = CGMutablePath()

        path.move(to: CGPoint(x: 0, y: 0))
        path.addLine(to: CGPoint(x:heightWidth/2, y: heightWidth/2))
        path.addLine(to: CGPoint(x:heightWidth, y:0))
        path.addLine(to: CGPoint(x:0, y:0))

        let shape = CAShapeLayer()
        shape.path = path
        shape.fillColor = UIColor.blue.cgColor

        targetView!.layer.insertSublayer(shape, at: 0)
    }
}
0

Swift 4.*

The easiest way of doing it by using AutoLayout:

  1. Open your Storyboard and drag a UIView in UIViewController, position it and set the size as you wish (that's the place where the triangle will be). Set the view background to be transparent.
  2. Create a new class, you can name it however you want (I named mine TriangleView). This will be the content of that class:

class TriangleView: UIView {

//    predefined variables that can be changed
    var startPoint: CGPoint = CGPoint(x: 0.0, y: 0.5)
    var endPoint: CGPoint = CGPoint(x: 1.0, y: 0.5)
    var firstGradientColor: UIColor = UIColor.white
    var secondGradientColor: UIColor = UIColor.blue

    let gradient: CAGradientLayer = CAGradientLayer()

    override func draw(_ rect: CGRect) {
        let height = self.layer.frame.size.height
        let width = self.layer.frame.size.width

//        draw the triangle 
        let path = UIBezierPath()
        path.move(to: CGPoint(x: width / 2, y: 0))
        path.addLine(to: CGPoint(x: width, y: height))
        path.addLine(to: CGPoint(x: 0, y: height))
        path.close()

//        draw the triangle 'upside down'
//        let path = UIBezierPath()
//        path.move(to: CGPoint(x: 0, y: 0))
//        path.addLine(to: CGPoint(x: width, y: 0))
//        path.addLine(to: CGPoint(x: width / 2, y: height))
//        path.close()

//        add path to layer
        let shapeLayer = CAShapeLayer()
        shapeLayer.path = path.cgPath
        shapeLayer.lineWidth = 1.0

//        Add the gradient for the view background if needed
        gradient.colors = [firstGradientColor.cgColor, secondGradiendColor.cgColor]
        gradient.startPoint = startPoint
        gradient.endPoint = endPoint
        gradient.frame = self.bounds
        gradient.mask = shapeLayer

        self.layer.addSublayer(gradient)
    }
}
  1. Go to your Storyboard, select the UIView and in Identity Inspector write the class name TriangleView

  2. Enjoy your triangle! :)

Đorđe Nilović
  • 3,600
  • 1
  • 25
  • 20