Triangle UIView - Swift

匿名 (未验证) 提交于 2019-12-03 01:23:02

问题:

So I'm making a game in which I am dropping objects which have to be destroyed by a spike(triangle) at the bottom of the screen by a user.

I cannot work out how to make a UIView that is a triangle. However I have been able to make it work as a rectangle like this:

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

And this has worked. But I cannot work out how to make a triangle. The reason I want it as a UIView is because im using collisions on it and for the user to move it. I have tried a PNG triangle but it detects the collision as the border of the image not the start of the triangle.

I have tried this but it doesn't work...

 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) 

Any and all help will be appreciated,

Thanks,

Alex

回答1:

Updated for 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);        }  }  

This will start from MinX, MaxY;
Draw a line from the start to MaxX, MaxY;
Draw a line from MaxX,MaxY to MaxX/2, MinY;
Then close the path to the start location.

The next part sets the color you want to use. In this example 255,127,0, Alpha 0.6 Then will fill the path you just drew above with the set color.

Then in your View Controller

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.     } } 

However, this is going to cause the same problem as the frame of this view is still going to be a rectangle. UIKit works with rectangles, you would have to use another framework, like Sprite Kit.



回答2:

CAShapeLayer it can change the shape of layers.

    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:

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

There is nothing you can do about that if you're going to use simple-minded collisions (e.g. the built-in UIKit Dynamics - it does only rectangular view collisions). If you want advanced shape collisions, either you must implement them yourself or you must use Sprites.

and for the user to move it

That is much easier to deal with: simply override hitTest for this view and return nil if the place the user touches is outside the borders of the triangle image.



回答4:

I've modified the previous code a bit to add margin and fill color as inspectable and it works well with 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()     } } 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!