Треугольник 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)

Любая помощь будет оценена,

Спасибо,

Алекс

Ответы

Ответ 1

Обновлено для 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.

Ответ 2

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)

Ответ 3

Я пробовал треугольник PNG, но он обнаруживает столкновение как границу изображения, а не начало треугольника.

Вы ничего не можете с этим поделать, если собираетесь использовать простодушные столкновения (например, встроенная динамика UIKit Dynamics - это только конфликты с прямоугольным представлением). Если вам нужны расширенные коллизии формы, либо вы должны их реализовать самостоятельно, либо вы должны использовать Sprites.

и для пользователя, чтобы переместить его

С этим гораздо проще справиться: просто переопределите hitTest для этого представления и верните nil, если место, к которому пользователь прикасается, находится за пределами изображения треугольника.

Ответ 4

Я немного изменил предыдущий код, чтобы добавить маркер и заполнить цвет как проверяемый, и он хорошо работает с 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()
    }
}