Анимируйте представление вдоль пути без CAKeyframeAnimation - PullRequest
1 голос
/ 22 марта 2019

Я хочу анимировать вид вдоль пути (без CAKeyframeAnimation) вместо этого с помощью UIViewPropertyAnimator.

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

let path = UIBezierPath()
path.move(to: view.center)
path.addQuadCurve(to: target.center, controlPoint: CGPoint(x: view.center.x-10, y: target.center.y+160))

Мой аниматор использует анимацию UIView.animateKeyframes для анимации положения вдоль пути.

let animator = UIViewPropertyAnimator(duration: duration, curve: .easeIn)

    animator.addAnimations {
        UIView.animateKeyframes(withDuration: duration, delay: 0, options: [.calculationModeLinear], animations: {
            let points = 100
            for i in 1...points {
                let pos = Double(i)/Double(points)
                let x = self.quadBezier(pos: pos,
                                        start: Double(view.center.x),
                                        con: Double(view.center.x-10),
                                        end: Double(target.center.x))
                let y = self.quadBezier(pos: pos,
                                        start: Double(view.center.y),
                                        con: Double(target.center.y+160),
                                        end: Double(target.center.y))

                let duration = 1.0/Double(points)
                let startTime = duration * Double(i)
                UIView.addKeyframe(withRelativeStartTime: startTime, relativeDuration: duration) {
                    view.center = CGPoint(x: x, y: y)
                }
            }
        })
    }

Для вычисления точек я использую ту же функцию, что и @rmaddy, думаю, у нас естьтот же источник здесь.

func quadBezier(pos: Double, start: Double, con: Double, end: Double) -> Double {
    let t_ = (1.0 - pos)
    let tt_ = t_ * t_
    let tt = pos * pos

    return Double(start * tt_) + Double(2.0 * con * t_ * pos) + Double(end * tt)
}

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

enter image description here

Но после итерации по тому же циклу и добавления синих точек к вычисленным позициям х / у показывает, что позиции правильные.

enter image description here

Поэтому я удивляюсь, почему моя анимация не следует этому пути.

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

1 Ответ

2 голосов
/ 23 марта 2019

View.center изменяется во время анимации, исправьте его, тогда нет проблем:

try the following:

        let cent = view.center
        UIView.animateKeyframes(withDuration: duration, delay: 0, options: [.beginFromCurrentState], animations: {
            let points = 100

            for i in 1...points {

                let pos = Double(i)/Double(points)
                let x = self.quadBezier(pos: pos,
                                        start: Double(cent.x), //here
                                        con: Double(cent.x-10), //here
                                        end: Double(square.center.x))
                let y = self.quadBezier(pos: pos,
                                        start: Double(cent.y), //here
                                        con: Double(square.center.y+160),
                                        end: Double(square.center.y))

                let duration = 1.0 / Double(points)
                let startTime = duration * Double(i)
                print("Animate: \(Int(x)) : \(Int(y))")
                UIView.addKeyframe(withRelativeStartTime: startTime, relativeDuration: duration) {
                   view.center = CGPoint(x: x, y: y)

                }
            }
        })
    }
...