在向上和向下平移时使用多次旋转为 UIView 设置动画
Animate UIView with multiple rotations while translating up and down
我有一个名为 swirlButton 的按钮,我想让它制作上下跳跃的动画,并让它向上翻转 3 次,向下翻转 3 次。我正在使用 translatedBy 来移动它,并使用 rotated 来旋转它,尽管在这个例子中我只让它动画化了一个转弯的部分,当动画完成时它会以另一种方式返回。
首先,我一开始不知道如何让它旋转不止一次。例如,我无法将 rotated(by:) 值设置为 .pi*3,因为它似乎只等于 0 度并且从不设置动画。如果我将它设置为 .pi.
也一样
var transforms: CGAffineTransform = .identity
let jumpDuration:Double = 2.0 //0.8
let halfJumpDuration:Double = jumpDuration/2.0
UIView.animateKeyframes(withDuration: jumpDuration, delay: 0, options: [UIView.KeyframeAnimationOptions.calculationModeCubicPaced], animations: {
UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: halfJumpDuration/jumpDuration, animations: {
transforms = transforms.translatedBy(x: 0, y: -60)
transforms = transforms.rotated(by: .pi/2)
swirlButton.transform = transforms
})
UIView.addKeyframe(withRelativeStartTime: halfJumpDuration/jumpDuration, relativeDuration: halfJumpDuration/jumpDuration, animations: {
transforms = .identity
transforms = transforms.translatedBy(x: 0, y: 0)
swirlButton.transform = transforms
})
},
completion: { _ in
print("animation finished")
})
除了上升和下降之外,旋转与我想要发生的情况相去甚远。让它向上逆时针旋转3圈,向下继续逆时针旋转3圈,很难吗?
我认为为此使用 CABasicAnimation 更容易。
这是我想出的:
func animateButton() {
swirlButton.layer.add(rotateAnimation(), forKey: nil)
CATransaction.begin()
let upAnimation = bounceAnimation()
CATransaction.setCompletionBlock{ () in
self.swirlButton.layer.add(self.bounceAnimation(animatingDown: true), forKey: nil)
}
swirlButton.layer.add(upAnimation, forKey: nil)
CATransaction.commit()
}
func rotateAnimation() -> CABasicAnimation {
let rotate = CABasicAnimation(keyPath: "transform.rotation")
rotate.fromValue = 0
rotate.toValue = -6*CGFloat.pi
rotate.duration = 2
return rotate
}
func bounceAnimation(animatingDown: Bool = false) -> CABasicAnimation {
let buttonY = swirlButton.layer.position.y
let buttonX = swirlButton.layer.position.x
let translate = CABasicAnimation(keyPath: "position")
translate.fromValue = animatingDown ? [buttonX, buttonY - 200] : [buttonX, buttonY]
translate.toValue = animatingDown ? [buttonX, buttonY] : [buttonX, buttonY - 200]
translate.duration = 1
translate.fillMode = .forwards
translate.isRemovedOnCompletion = false
return translate
}
translate.fillMode = .forwards & translate.isRemovedOnCompletion = false 是防止闪烁的必要条件 in-between 动画和 CATransaction 允许我们为第一个动画(向上)设置完成块完成。
我有一个名为 swirlButton 的按钮,我想让它制作上下跳跃的动画,并让它向上翻转 3 次,向下翻转 3 次。我正在使用 translatedBy 来移动它,并使用 rotated 来旋转它,尽管在这个例子中我只让它动画化了一个转弯的部分,当动画完成时它会以另一种方式返回。
首先,我一开始不知道如何让它旋转不止一次。例如,我无法将 rotated(by:) 值设置为 .pi*3,因为它似乎只等于 0 度并且从不设置动画。如果我将它设置为 .pi.
也一样var transforms: CGAffineTransform = .identity
let jumpDuration:Double = 2.0 //0.8
let halfJumpDuration:Double = jumpDuration/2.0
UIView.animateKeyframes(withDuration: jumpDuration, delay: 0, options: [UIView.KeyframeAnimationOptions.calculationModeCubicPaced], animations: {
UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: halfJumpDuration/jumpDuration, animations: {
transforms = transforms.translatedBy(x: 0, y: -60)
transforms = transforms.rotated(by: .pi/2)
swirlButton.transform = transforms
})
UIView.addKeyframe(withRelativeStartTime: halfJumpDuration/jumpDuration, relativeDuration: halfJumpDuration/jumpDuration, animations: {
transforms = .identity
transforms = transforms.translatedBy(x: 0, y: 0)
swirlButton.transform = transforms
})
},
completion: { _ in
print("animation finished")
})
除了上升和下降之外,旋转与我想要发生的情况相去甚远。让它向上逆时针旋转3圈,向下继续逆时针旋转3圈,很难吗?
我认为为此使用 CABasicAnimation 更容易。
这是我想出的:
func animateButton() {
swirlButton.layer.add(rotateAnimation(), forKey: nil)
CATransaction.begin()
let upAnimation = bounceAnimation()
CATransaction.setCompletionBlock{ () in
self.swirlButton.layer.add(self.bounceAnimation(animatingDown: true), forKey: nil)
}
swirlButton.layer.add(upAnimation, forKey: nil)
CATransaction.commit()
}
func rotateAnimation() -> CABasicAnimation {
let rotate = CABasicAnimation(keyPath: "transform.rotation")
rotate.fromValue = 0
rotate.toValue = -6*CGFloat.pi
rotate.duration = 2
return rotate
}
func bounceAnimation(animatingDown: Bool = false) -> CABasicAnimation {
let buttonY = swirlButton.layer.position.y
let buttonX = swirlButton.layer.position.x
let translate = CABasicAnimation(keyPath: "position")
translate.fromValue = animatingDown ? [buttonX, buttonY - 200] : [buttonX, buttonY]
translate.toValue = animatingDown ? [buttonX, buttonY] : [buttonX, buttonY - 200]
translate.duration = 1
translate.fillMode = .forwards
translate.isRemovedOnCompletion = false
return translate
}
translate.fillMode = .forwards & translate.isRemovedOnCompletion = false 是防止闪烁的必要条件 in-between 动画和 CATransaction 允许我们为第一个动画(向上)设置完成块完成。