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