ios 三角形 UIView - Swift
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30650343/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Triangle UIView - Swift
提问by Zog
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:
我不知道如何制作一个三角形的 UIView。但是我已经能够使它像这样的矩形工作:
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.
这已经奏效了。但我不知道如何制作三角形。我想要它作为 UIView 的原因是因为我在它上面使用了碰撞并让用户移动它。我试过一个 PNG 三角形,但它检测到碰撞是图像的边界而不是三角形的开始。
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
亚历克斯
回答by Taylor M
Updated for Swift 3:
为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:斯威夫特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.
这将从MinX,MaxY开始;
从起点到MaxX、MaxY画一条线;
从 MaxX,MaxY 到 MaxX/2, MinY 画一条线;
然后关闭到起始位置的路径。
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.
下一部分设置您要使用的颜色。在这个例子中 255,127,0, Alpha 0.6 然后将用设置的颜色填充你刚刚在上面绘制的路径。
Then in your View Controller
然后在您的视图控制器中
Swift 3:
斯威夫特 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:斯威夫特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.
然而,这将导致同样的问题,因为这个视图的框架仍然是一个矩形。UIKit 适用于矩形,您必须使用另一个框架,例如 Sprite Kit。
回答by Abdoelrhman
I've modified the previous code a bit to add margin and fill color as inspectable and it works well with Swift4:
我稍微修改了之前的代码,将边距和填充颜色添加为可检查的,并且它适用于 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()
}
}
回答by Shanmugasundharam
CAShapeLayer it can change the shape of layers.
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)
回答by Saifan Nadaf
Swift 5:
斯威夫特 5:
This code worked for me for different sides. for UIView
using CGMutablePath()
and CAShapeLayer()
这段代码适用于我的不同方面。用于UIView
使用CGMutablePath()
和CAShapeLayer()
*Assuming your view's height and width are same.
*假设您的视图的高度和宽度相同。
*Set your views's background color as clearColor.
*将视图的背景颜色设置为 clearColor。
A) Right Side
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) Left Side
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) Up Side
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) Down Side
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)
}
*Change X any Y values according to your requirement.
*根据您的要求更改 X 任何 Y 值。
回答by matt
I have tried a PNG triangle but it detects the collision as the border of the image not the start of the triangle.
我试过一个 PNG 三角形,但它检测到碰撞是图像的边界而不是三角形的开始。
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 onlyrectangular view collisions). If you want advanced shape collisions, either you must implement them yourself or you must use Sprites.
没有什么可以做,如果你要使用头脑简单的碰撞(例如内置的UIKit动力学-它只是矩形视图碰撞)。如果你想要高级形状碰撞,要么你必须自己实现它们,要么你必须使用 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.
这更容易处理:只需覆盖hitTest
此视图,nil
如果用户触摸的位置在三角形图像的边界之外,则返回。