在iOSswift中可以通过在图像上画线来对图像进行分组吗?
Is it possible to group images by drawing lines on it in iOS swift?
举个例子,如果我在随机位置的视图上有多个图像。通过在图像上画线来选择图像,并使用手势对图像进行分组。现在我可以随机显示图像,但不能通过在图像上画线来对图像进行分组。
这里的屏幕截图 1 是我现在得到的结果:
屏幕截图 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([=14=], to: viewThatContainsImages) }
let imageViewsHitByPath = allImageViews.filter { imageView in
return convertedPoints.contains(where: { imageView.frame.contains([=14=]) })
}
// Use imageViewsHitByPath
}
现在,在这个基本实现之后,您可以通过绘制一条更好的线(弯曲的)开始播放,并且在您不检查点是否在图像视图内而是检查任何 2 个相邻点之间的线是否与您的相交的情况下图像视图。
举个例子,如果我在随机位置的视图上有多个图像。通过在图像上画线来选择图像,并使用手势对图像进行分组。现在我可以随机显示图像,但不能通过在图像上画线来对图像进行分组。
这里的屏幕截图 1 是我现在得到的结果:
屏幕截图 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([=14=], to: viewThatContainsImages) }
let imageViewsHitByPath = allImageViews.filter { imageView in
return convertedPoints.contains(where: { imageView.frame.contains([=14=]) })
}
// Use imageViewsHitByPath
}
现在,在这个基本实现之后,您可以通过绘制一条更好的线(弯曲的)开始播放,并且在您不检查点是否在图像视图内而是检查任何 2 个相邻点之间的线是否与您的相交的情况下图像视图。