在没有 CAKeyframeAnimation 的情况下为沿着路径的视图设置动画
Animate a view alongside a path without CAKeyframeAnimation
我想为路径旁边的视图设置动画(没有 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 相同的函数,认为我们这里有相同的source。
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)
}
首先我认为计算是错误的,因为感觉计算点是通过控制点什么的:
但是在遍历相同的 forloop 并将蓝色点添加到计算出的 x/y 位置后,表明位置是正确的。
所以我想知道为什么我的动画不遵循该路径。
我找到了这个 question 并发布了我的问题作为答案,但我想没有人认出它。
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)
}
}
})
}
我想为路径旁边的视图设置动画(没有 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 相同的函数,认为我们这里有相同的source。
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)
}
首先我认为计算是错误的,因为感觉计算点是通过控制点什么的:
但是在遍历相同的 forloop 并将蓝色点添加到计算出的 x/y 位置后,表明位置是正确的。
所以我想知道为什么我的动画不遵循该路径。
我找到了这个 question 并发布了我的问题作为答案,但我想没有人认出它。
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)
}
}
})
}