добавить скорость UIPanGestureRecognizer в UIViewPropertyAnimator

Я следовал руководству по созданию интерактивной анимации центра управления iOS с помощью UIViewPropertyAnimator:

http://www.swiftkickmobile.com/building-better-app-animations-swift-uiviewpropertyanimator/

при смахивании вверх или вниз по нижнему меню после отпускания пальца я хочу добавить скорость панорамирования к UIViewPropertyAnimator и продолжить анимацию:

popupViewPanned(recognizer:) {

    switch recognizer.state {
        .
        .
        .
    // after finger released
        case .end:
        // continue all animations using pan velocity with spring timing

        let normalizedPanVelocity: // how to normalize pan velocity
     runningAnimators.forEach { $0.continueAnimation(withTimingParameters: spring(for: velocity()), durationFactor: 0) }
    }
}

func velocity() -> CGVector {
    let pan = panRecognizer
    let progress = runningAnimators[0].fractionComplete
    let fraction = popupOffset*(1 - progress)
    return CGVector(with: pan.velocity(in: view), fraction: fraction)
}
func spring(for velocity: CGVector = .zero) -> UITimingCurveProvider {
    return UISpringTimingParameters(dampingRatio: 0.9, initialVelocity: velocity)//UISpringTimingParameters(mass: 2.5, stiffness: 80, damping: 25, initialVelocity: velocity)
}

проблема в том, что когда я быстро смахиваю вверх или вниз по меню и отпускаю тоньше, кажется, что анимация ударяется о стену (медленно быстро), затем продолжаю отдыхать

так как я могу решить проблему? Я пытался целый день, но я не мог это исправить


person Hashem Aboonajmi    schedule 31.05.2018    source источник


Ответы (1)


В документации для UISpringTimingParameters указано: https://developer.apple.com/documentation/uikit/uispringtimingparameters/1649832-init

Вектор со значением 1,0 соответствует начальной скорости, которая покрывает все расстояние анимации за одну секунду. Например, если общее расстояние анимации составляет 200 точек, а начальная скорость представления составляет 100 точек в секунду, укажите вектор с величиной 0,5.

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

И глядя на официальную документацию для CGVector, инициализатор, который вы используете, не задокументирован. https://developer.apple.com/documentation/coregraphics/cgvector

В итоге я вычислил нормализованный вектор самостоятельно. Вам нужно будет рассчитать общее количество точек, которые вид перемещает от начала анимации до конца, а затем использовать этот distanceToMove, чтобы сделать из него "единичный вектор"/нормировать его:

let distanceToMove = newY - oldY
let velocity = recognizer.velocity(in: view)
let relativeVelocityY = velocity.x / distanceToMove
let relativeVelocity = CGVector(dx: 0, dy: relativeVelocityY)
let timing = UISpringTimingParameters(dampingRatio: 0.9, initialVelocity: relativeVelocity)

Дайте мне знать, если это сработало для вас.

person Ichor de Dionysos    schedule 29.09.2018