【问题标题】:Triangle UIView - Swift三角形 UIView - 斯威夫特
【发布时间】:2015-08-19 10:45:57
【问题描述】:

所以我正在制作一个游戏,在该游戏中,我要丢下的物体必须被用户在屏幕底部的尖刺(三角形)摧毁。

我不知道如何制作一个三角形的 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)

我们将不胜感激,

谢谢,

亚历克斯

【问题讨论】:

  • 将 CAShapeLayer 添加到您的视图中,并给它一个三角形路径(您使用 UIBezierPath 创建)。
  • 听起来你使用 UIKit 的目的更适合 SpriteKit

标签: ios xcode swift uiview ios8


【解决方案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。

【讨论】:

  • 我相信triange 是错字? :)
  • @Arefly 谢谢!固定。
  • @UdayNaidu 要动态更改颜色,请向TriangleView 添加一个属性来保存颜色并使用它来设置填充颜色。另请查看文档中的“视图绘图周期”。
  • 我没有尝试绘制三角形。但这有助于我画梯形:d
  • 会画黑色背景,我们应该在init中添加self.isOpaque = false来修复它
【解决方案2】:

斯威夫特 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 值。

【讨论】:

  • 如果有人需要从视图中间的 upsaide-triagleview,请使用此路径。 path.move(to: CGPoint(x: 0, y: heightWidth/2)) path.addLine(to: CGPoint(x:heightWidth/2, y: 0)) path.addLine(to: CGPoint(x:heightWidth, y:heightWidth/2)) path.addLine(to: CGPoint(x:0, y:heightWidth/2))
【解决方案3】:

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)

【讨论】:

    【解决方案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()
        }
    }
    

    【讨论】:

      【解决方案5】:

      我尝试了一个 PNG 三角形,但它检测到碰撞是图像的边界而不是三角形的开始。

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

      并让用户移动它

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

      【讨论】:

      【解决方案6】:

      这将在 4 个方向中的任一个方向上为您提供 较短 点或 较长 点。易于使用:

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

      import UIKit
      
      class PointingTriangleView: UIView {
          
          override init(frame: CGRect) {
              super.init(frame: frame)
          }
          
          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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-07-22
        • 2017-03-24
        • 1970-01-01
        • 2016-02-08
        • 2017-11-13
        • 2015-08-19
        • 2014-09-11
        相关资源
        最近更新 更多