三角形 UIView - Swift

Triangle UIView - Swift

所以我正在制作一个游戏,其中我正在丢弃必须由用户在屏幕底部用尖刺(三角形)销毁的对象。

我不知道如何制作一个三角形的 UIView。但是我已经能够让它像这样像一个矩形一样工作:

 let barrier = UIView(frame: CGRect(x:125, y: 650, width: 130, height:20))
 barrier.backgroundColor = UIColor.orangeColor()
 view.addSubview(barrier)

这很奏效。但是我不知道如何制作三角形。我想要它作为 UIView 的原因是因为我在它上面使用了碰撞并让用户移动它。我已经尝试了一个 PNG 三角形,但它检测到碰撞是作为图像的边界而不是三角形的开始。

我已经试过了,但是没用...

 let square = UIView(frame: CGPathMoveToPoint(path, nil, 50, 0), CGPathAddLineToPoint(path, nil, 100, 50), CGPathAddLineToPoint(path, nil, 0, 100))
 square.backgroundColor = UIColor.purpleColor()
 view.addSubview(square)

我们将不胜感激,

谢谢,

亚历克斯

I have tried a PNG triangle but it detects the collision as the border of the image not the start of the triangle.

如果您打算使用头脑简单的碰撞(例如内置的 UIKit Dynamics - 它 矩形视图碰撞,您对此无能为力。 .如果你想要高级形状碰撞,要么你必须自己实现它们,要么你必须使用 Sprites。

and for the user to move it

这更容易处理:只需覆盖此视图的 hitTest 和 return nil 如果用户触摸的位置在三角形图像的边界之外。

更新 Swift 3:

class TriangleView : UIView {

    override init(frame: CGRect) {
        super.init(frame: frame)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override func draw(_ rect: CGRect) {

        guard let context = UIGraphicsGetCurrentContext() else { return }

        context.beginPath()
        context.move(to: CGPoint(x: rect.minX, y: rect.maxY))
        context.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
        context.addLine(to: CGPoint(x: (rect.maxX / 2.0), y: rect.minY))
        context.closePath()

        context.setFillColor(red: 1.0, green: 0.5, blue: 0.0, alpha: 0.60)
        context.fillPath()
    }
}


Swift 2:

import UIKit

class TriangleView : UIView {

    override init(frame: CGRect) {
        super.init(frame: frame)
    }

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override func drawRect(rect: CGRect) {

        var ctx : CGContextRef = UIGraphicsGetCurrentContext()

        CGContextBeginPath(ctx)
        CGContextMoveToPoint(ctx, CGRectGetMinX(rect), CGRectGetMaxY(rect))
        CGContextAddLineToPoint(ctx, CGRectGetMaxX(rect), CGRectGetMaxY(rect))
        CGContextAddLineToPoint(ctx, (CGRectGetMaxX(rect)/2.0), CGRectGetMinY(rect))
        CGContextClosePath(ctx)

        CGContextSetRGBFillColor(ctx, 1.0, 0.5, 0.0, 0.60);
        CGContextFillPath(ctx);
       }
 } 

这将从MinX、MaxY开始;
从起点画一条线到MaxX,MaxY;
从 MaxX,MaxY 到 MaxX/2, MinY;
画一条线 然后关闭到起始位置的路径。

下一部分设置您要使用的颜色。在这个例子中 255,127,0, Alpha 0.6 然后将用设置的颜色填充上面刚刚绘制的路径。

然后在你的视图控制器中

Swift 3:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let triangle = TriangleView(frame: CGRect(x: 10, y: 20, width: 25 , height: 30))
        triangle.backgroundColor = .white
        view.addSubview(triangle)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}


Swift 2:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        let triangle = TriangleView(frame: CGRectMake(10, 20, 25, 30))
        triangle.backgroundColor = .whiteColor()
        view.addSubview(triangle)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

但是,这将导致同样的问题,因为此视图的框架仍将是矩形。 UIKit 与矩形一起工作,您将不得不使用其他框架,例如 Sprite Kit。

CAShapeLayer 可以改变图层的形状。

    var mask = CAShapeLayer()
    mask.frame = self.layer.bounds

    let width = self.layer.frame.size.width
    let height = self.layer.frame.size.height

    var path = CGPathCreateMutable()

    CGPathMoveToPoint(path, nil, 30, 0)
    CGPathAddLineToPoint(path, nil, width, 0)
    CGPathAddLineToPoint(path, nil, width, height)
    CGPathAddLineToPoint(path, nil, 0, height)
    CGPathAddLineToPoint(path, nil, 30, 0)

    mask.path = path

    // CGPathRelease(path); - not needed

    self.layer.mask = mask

    var shape = CAShapeLayer()
    shape.frame = self.bounds
    shape.path = path
    shape.lineWidth = 3.0
    shape.strokeColor = UIColor.whiteColor().CGColor
    shape.fillColor = UIColor.clearColor().CGColor

    self.layer.insertSublayer(shape, atIndex: 0)

我稍微修改了之前的代码,添加了可检查的边距和填充颜色,它与 Swift4 配合得很好:

import UIKit

@IBDesignable
class TriangleView : UIView {
    var _color: UIColor! = UIColor.blue
    var _margin: CGFloat! = 0

    @IBInspectable var margin: Double {
        get { return Double(_margin)}
        set { _margin = CGFloat(newValue)}
    }


    @IBInspectable var fillColor: UIColor? {
        get { return _color }
        set{ _color = newValue }
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override func draw(_ rect: CGRect) {

        guard let context = UIGraphicsGetCurrentContext() else { return }

        context.beginPath()
        context.move(to: CGPoint(x: rect.minX + _margin, y: rect.maxY - _margin))
        context.addLine(to: CGPoint(x: rect.maxX - _margin, y: rect.maxY - _margin))
        context.addLine(to: CGPoint(x: (rect.maxX / 2.0), y: rect.minY + _margin))
        context.closePath()

        context.setFillColor(_color.cgColor)
        context.fillPath()
    }
}

Swift 5:

这段代码对我来说适用于不同的方面。对于 UIView 使用 CGMutablePath()CAShapeLayer()

*假设您的视图的高度和宽度相同。

*将视图的背景颜色设置为 clearColor。

A) 右侧

 @IBOutlet weak var triangleView: UIView!

 override func viewDidLoad() {
        super.viewDidLoad()
        self.setRightTriangle()   
    }

 func setRightTriangle(){
        let heightWidth = triangleView.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

        triangleView.layer.insertSublayer(shape, at: 0)
    }


B) 左侧

 func setLeftTriangle(){
        let heightWidth = triangleView.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

        triangleView.layer.insertSublayer(shape, at: 0)
    }


C) 上侧

  func setUpTriangle(){
        let heightWidth = triangleView.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

           triangleView.layer.insertSublayer(shape, at: 0)
       }


D) 下行

  func setDownTriangle(){
        let heightWidth = triangleView.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

        triangleView.layer.insertSublayer(shape, at: 0)
    }

*根据您的要求更改 X 的任何 Y 值。

这会给你一个更短点或更长点在4个方向中的任何一个。易于使用:

1 - 创建一个 class (c+p):

import UIKit

class PointingTriangleView: UIView {
    
    override init(frame: CGRect) {
        super.init(frame: frame)

        self.backgroundColor = UIColor.clear
    }
    
    var fillColorCGColor = UIColor.brown.cgColor
    
    var pointingLongDown = false
    var pointingShortDown = false

    var pointingLongUp = false        
    var pointingShortUp = false
    
    var pointingLongLeft = false
    var pointingShortLeft = false
    
    var pointingLongRight = false
    var pointingShortRight = false
    
    override func draw(_ rect: CGRect) {
        
        guard let context = UIGraphicsGetCurrentContext() else { return }
        
        context.beginPath()
        
        if pointingLongDown {
            context.move(to: CGPoint(x: rect.minX, y: rect.minY))
            context.addLine(to: CGPoint(x: rect.maxX, y: rect.minY))
            context.addLine(to: CGPoint(x: rect.midX, y: rect.maxY))
        }
        
        if pointingShortDown {
            context.move(to: CGPoint(x: rect.minX, y: rect.midY))
            context.addLine(to: CGPoint(x: rect.maxX, y: rect.midY))
            context.addLine(to: CGPoint(x: rect.midX, y: rect.maxY))
        }
        
        if pointingLongUp {
            context.move(to: CGPoint(x: rect.minX, y: rect.maxY))
            context.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
            context.addLine(to: CGPoint(x: rect.midX, y: rect.minY))
        }
        
        if pointingShortUp {
            context.move(to: CGPoint(x: rect.minX, y: rect.maxY))
            context.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
            context.addLine(to: CGPoint(x: rect.midX, y: rect.midY))
        }
        
        if pointingLongLeft {
            context.move(to: CGPoint(x: rect.minX, y: rect.midY))
            context.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
            context.addLine(to: CGPoint(x: rect.maxX, y: rect.minY))
        }
        
        if pointingShortLeft {
            context.move(to: CGPoint(x: rect.midX, y: rect.midY))
            context.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
            context.addLine(to: CGPoint(x: rect.maxX, y: rect.minY))
        }
        
        if pointingLongRight {
            context.move(to: CGPoint(x: rect.maxX, y: rect.midY))
            context.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
            context.addLine(to: CGPoint(x: rect.minX, y: rect.minY))
        }
        
        if pointingShortRight {
            context.move(to: CGPoint(x: rect.midX, y: rect.midY))
            context.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
            context.addLine(to: CGPoint(x: rect.minX, y: rect.minY))
        }
        
        context.closePath()
        
        context.setFillColor(fillColorCGColor)
        context.fillPath()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
}

2 - 创建一个对象,确保设置您喜欢的方向和颜色:

lazy var pointingArrow: PointingTriangleView = {
    let v = PointingTriangleView()
    v.translatesAutoresizingMaskIntoConstraints = false

    v.pointingShortUp = true // *** set the direction that you prefer here ***

    v.fillColorCGColor = UIColor.blue.cgColor // select your preferred color and make sure it ends in .cgColor 
    return v
}()

3 - 设置 Anchors:

view.addSubview(pointingArrow)

pointingArrow.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true 
pointingArrow.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
pointingArrow.widthAnchor.constraint(equalToConstant: 20).isActive = true
pointingArrow.heightAnchor.constraint(equalToConstant: 20).isActive = true