答案 0 :(得分:2)
对于您要做的事情,我将首先创建一个能够处理手势和绘制路径的自定义视图(子类)。
对于手势识别器,我会使用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
使图形无效时,将调用此方法。在你的情况下,最好在路径点的setter上完成:
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
}
现在,在这个基本实现之后,您可以通过绘制更好的线(弯曲)开始播放,并且在不检查点是否在图像视图内部的情况下,而不是任何2个相邻点之间的线与您的相交图像视图。