首页 > 解决方案 > 使 UIPanGesture 跟随线条

问题描述

我正在尝试按照此板线移动一个红点:

在此处输入图像描述

红点是 Dot 类的一个实例,它是 UIImage 视图的子类:

class Dot: UIImageView {

enum directions {
    case up, down, left, right, nordWest, nordEst, southWest, southEst
}

var position: Int = 4

var possibleDirections: [directions] {
    switch position {
    case 0:
        return [.right, .down, .southEst]
    case 1:
        return [.left, .right, .down]
    case 2:
        return [.left, .down, .southWest]
    case 3:
        return [.up, .down, .right]
    case 4:
        return [.up, .down, .left, .right, .nordWest, .nordEst, .southWest, .southEst]
    case 5:
        return [.up, .down, .left]
    case 6:
        return [.up, .right, .nordEst]
    case 7:
        return [.up, .left, .right]
    case 8:
        return [.up, .left, .nordWest]
    default:
        return []
    }
}

}

这是我的视图控制器:

    @IBOutlet weak var redDot: Dot!

override func viewDidLoad() {
    super.viewDidLoad()

    redDot.isUserInteractionEnabled = true

    let panGesture = UIPanGestureRecognizer(target: self, action: #selector( moveDot(_:) ))
    redDot.addGestureRecognizer(panGesture)
}


@objc func moveDot(_ sender: UIPanGestureRecognizer) {
    switch sender.state {
    case .began, .changed:
        moveDotWith(gesture: sender)
    case .ended, .cancelled:
        proceedToMove()
    default:
        break
    }
}

private func moveDotWith(gesture: UIPanGestureRecognizer) {

    let translation = gesture.translation(in: redDot)
    let transform = CGAffineTransform(translationX: translation.x, y: translation.y)
    redDot.transform = transform

}

private func proceedToMove() {

}

我想确定 moveDotWith(gesture) 函数只允许移动点后面的行,然后proceedToMove函数将保存更改redDot.position = (Int)

我想我可以保存更改,但我不知道如何使红点跟随线条,因此只能在允许的方向上。

位置从 0 到 8,如下所示:

在此处输入图像描述

我希望用户不能沿着线条拖动空白区域中的点,然后如果用户释放点,它会移动到最近的点。

示例:红点在 1,如果用户试图将其拖到 3,则没有任何反应。如果用户将它拖到 2,则点跟随灰线,然后当用户释放它时,如果点超过线的一半,则转到 2,否则返回 1。

标签: iosswiftuigesturerecognizeruipangesturerecognizer

解决方案


这将需要一些数学工作,但一种方法......

将“possibleDirections”更改为“possibleEndPoints”:

var possibleEndPoints: [Int] {
    switch position {
    case 0:
        return [1, 3, 4]
    case 1:
        return [0, 2, 4]
    case 2:
        return [1, 4, 5]
    case 3:
        return [0, 4, 6]
    case 4:
        return [0, 1, 2, 3, 5, 6, 7, 8]
    case 5:
        return [2, 4, 8]
    case 6:
        return [3, 4, 7]
    case 7:
        return [4, 6, 8]
    case 8:
        return [4, 5, 7]
    default:
        return []
    }
}

现在,当用户拖动时,您需要计算到垂直于拖动点的直线上的点的距离:

在此处输入图像描述

所以,

  • position== 0
  • possibleEndPoints==[1, 3, 4]
  • DP是拖动点
  • A是线上的点0 -> 1
  • B是线上的点0 -> 4
  • C是线上的点0 -> 3

最短的线将是有效线段的“最近点”,因此您将移动redDot到该点 - 在这种情况下,A. 当用户抬起手指时,计算“A超过 50% 的距离1”。

随着用户继续拖动,您可能会到达:

在此处输入图像描述

现在B是离拖动点最近的点,所以移动redDotB。当用户抬起手指时,计算“B超过 50% 的距离4”。

您必须考虑用户拖有效点的情况,例如:

在此处输入图像描述

您必须提出自己的逻辑来决定redDot应该去哪里。


推荐阅读