заставить UIPanGesture следовать линиям - PullRequest
0 голосов
/ 05 ноября 2018

Я пытаюсь переместить красную точку, следуя этой линии доски:

enter image description here

Красная точка - это экземпляр класса 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 []
    }
}

}

Вот мой viewController:

    @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 (жест) позволяла перемещать только точки, следующие за линиями, тогда функция continueToMove сохранит изменение с помощью redDot.position = (Int)

Я думаю, что я могу сохранить изменения, но я не знаю, как заставить красную точку следовать за линиями и так только в разрешенных направлениях.

Позиции изменяются от 0 до 8, например:

enter image description here

Я хочу, чтобы пользователи не могли перетаскивать точку в пустых областях, только вдоль линий, а затем, если пользователь отпускает эту точку, она переходит к ближайшей точке.

пример: красная точка на 1, если пользователь пытается перетащить ее на 3, ничего не происходит. если пользователь перетаскивает его до 2, точка следует за серой линией, затем, когда пользователь отпускает ее, если точка больше половины линии, она переходит к 2, в противном случае она возвращается к 1.

1 Ответ

0 голосов
/ 05 ноября 2018

Это займет немного математической работы, но один подход ...

Измените ваши «возможные направления» на «возможные точки конца»:

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 []
    }
}

Теперь, когда пользователь перетаскивает, вам нужно вычислить расстояние до точки на линии, перпендикулярной точке перетаскивания:

enter image description here

Итак,

  • position == 0
  • possibleEndPoints == [1, 3, 4]
  • DP - это точка сопротивления
  • A - точка на линии 0 -> 1
  • B - точка на линии 0 -> 4
  • C - точка на линии 0 -> 3

Самая короткая линия будет «ближайшей точкой» к действительному отрезку, поэтому вы должны переместиться на redDot к этой точке - в данном случае A. Когда пользователь поднимает палец, рассчитайте, что «A более 50% пути к 1».

Поскольку пользователь продолжает перетаскивание, вы можете достичь:

enter image description here

Теперь B является ближайшей точкой к точке перетаскивания, поэтому переместите redDot на B. Когда пользователь поднимает палец, рассчитайте, что «B более 50% пути к 4».

Вам придется учитывать случаи, когда пользователи перетаскивают за действительную точку, как в:

enter image description here

Вам придется придумать свою собственную логику, чтобы решить, куда redDot идти.

...