对于您试图做的事情,我将首先创建一个能够处理手势和绘制路径的自定义视图(一个子类)。
对于手势识别器,我将使用
UIPanGestureRecognizer
。您要做的是在处理手势的位置设置一组点,然后使用这些点绘制路径:
private var currentPathPoints: [CGPoint] = []
@objc private func onPan(_ sender: UIGestureRecognizer) {
switch sender.state {
case .began: currentPathPoints = [sender.location(in: self)] // Reset current array by only showing a current point. User just started his path
case .changed: currentPathPoints.append(sender.location(in: self)) // Just append a new point
case .cancelled, .ended: endPath() // Will need to report that user lifted his finger
default: break // These extra states are her just to annoy us
}
}
所以,如果平移手势识别器使用这种方法,它应该跟踪用户拖动的点。现在这些都是最好的
drawRect
需要在视图中覆盖,如:
override func draw(_ rect: CGRect) {
super.draw(rect)
// Generate path
let path: UIBezierPath = {
let path = UIBezierPath()
var pointsToDistribute = currentPathPoints
if let first = pointsToDistribute.first {
path.move(to: first)
pointsToDistribute.remove(at: 0)
}
pointsToDistribute.forEach { point in
path.addLine(to: point)
}
return path
}()
let color = UIColor.red // TODO: user your true color
color.setStroke()
path.lineWidth = 3.0
path.stroke()
}
现在,当您通过调用
setNeedsDisplay
.在您的情况下,最好在路径点设置器上进行:
private var currentPathPoints: [CGPoint] = [] {
didSet {
setNeedsDisplay()
}
}
由于此视图应作为整个场景的覆盖,因此您需要某种方式来报告事件。应创建一个委托过程来实现以下方法:
func endPath() {
delegate?.myLineView(self, finishedPath: currentPathPoints)
}
因此,现在如果视图控制器是委托,它可以检查路径中选择了哪些图像视图。对于第一个版本,只需检查任何点是否在任何图像视图内即可:
func myLineView(sender: MyLineView, finishedPath pathPoints: [CGPoint]) {
let convertedPoints: [CGPoint] = pathPoints.map { sender.convert($0, to: viewThatContainsImages) }
let imageViewsHitByPath = allImageViews.filter { imageView in
return convertedPoints.contains(where: { imageView.frame.contains($0) })
}
// Use imageViewsHitByPath
}
现在,在这个基本实现之后,您可以通过绘制一条更好的线(曲线)开始玩游戏,在这种情况下,您不会检查点是否在图像视图内,而是检查任何两个相邻点之间的线是否与图像视图相交。