是否可以通过在iOS swift上绘制线条来分组图像?

时间:2018-04-16 03:33:38

标签: ios swift xcode uiview uiimageview

例如,如果我在随机位置的视图上有多个图像。通过在其上绘制线条来选择图像,并使用手势对图像进行分组。现在,我可以随机显示图像,但不能通过绘制线条来分组图像。 这里截图1是我现在得到的结果:enter image description here

截图2这正是我想要的。 enter image description here

1 个答案:

答案 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个相邻点之间的线与您的相交图像视图。