在不使用CAKeyframeAnimation的情况下沿着路径动画化一个视图

3
我想沿着一条路径使用UIViewPropertyAnimator来实现视图的动画效果(而非使用CAKeyframeAnimation)。
为此,我需要一条带有起点和终点以及控制点的路径,以创建一个二次贝塞尔曲线。
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

但在遍历同样的for循环并将蓝色点添加到计算的x / y位置之后,显示这些位置是正确的。

enter image description here

所以我想知道为什么我的动画不遵循这条路径。

我发现了这个问题,并将我的问题作为答案发布了出去,但我想没有人注意到。


当然!我已经将我的游乐场 https://github.com/kuemme01/PathAnimationTest 推送了。 - kuemme01
1个回答

2

在动画期间,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)

                }
            }
        })
    }

有道理,我不会想到那个!再次感谢你! - kuemme01

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接