我有一个UIImageView
,我想要让它旋转180度,用时1秒钟,然后停留1秒钟,再用时1秒钟将其旋转180度回到原始位置。
我该如何实现这个目标?我已经尝试了100种方法,但它一直会弹回来,而不是旋转回去。
编辑:我忘记添加需要无限重复此操作。
我有一个UIImageView
,我想要让它旋转180度,用时1秒钟,然后停留1秒钟,再用时1秒钟将其旋转180度回到原始位置。
我该如何实现这个目标?我已经尝试了100种方法,但它一直会弹回来,而不是旋转回去。
编辑:我忘记添加需要无限重复此操作。
你只需要创建一个关键帧动画。 它被设计用于将多个动画链接在一起,在第一个关键帧中通过PI
旋转你的UIImageView
子类,在第二个关键帧中将其转换回identity
。
let rotateForwardAnimationDuration: TimeInterval = 1
let rotateBackAnimationDuration: TimeInterval = 1
let animationDuration: TimeInterval = rotateForwardAnimationDuration + rotateBackAnimationDuration
UIView.animateKeyframes(withDuration: animationDuration, delay: 0, options: [], animations: {
UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: rotateForwardAnimationDuration) {
self.imageView.transform = CGAffineTransform(rotationAngle: .pi)
}
UIView.addKeyframe(withRelativeStartTime: 0.5, relativeDuration: rotateBackAnimationDuration) {
self.imageView.transform = .identity
}
})
结果:
编辑: 这是一个无限循环播放的示例。我假设您的图像在视图控制器中,并且保持对imageView的某些引用。
例如,当 viewDidAppear
被调用时,调用一个函数来触发动画,然后在动画完成的完成块中,再次调用相同的函数。
class ViewController: UIViewController {
@IBOutlet weak var imageView: UIImageView!
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.runRotateAnimation()
}
func runRotateAnimation() {
let rotateForwardAnimationDuration: TimeInterval = 1
let rotateBackAnimationDuration: TimeInterval = 1
let animationDuration: TimeInterval = rotateForwardAnimationDuration + rotateBackAnimationDuration
UIView.animateKeyframes(withDuration: animationDuration, delay: 0, options: [], animations: {
UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: rotateForwardAnimationDuration) {
self.imageView.transform = CGAffineTransform(rotationAngle: .pi)
}
UIView.addKeyframe(withRelativeStartTime: 0.5, relativeDuration: rotateBackAnimationDuration) {
self.imageView.transform = .identity
}
}) { (isFinished) in
// To loop it continuosly, just call the same function from the completion block of the keyframe animation
self.runRotateAnimation()
}
}
}
您可以在UIView.animate的completionHandler中执行第二个动画。
let duration = self.transitionDuration(using: transitionContext)
let firstAnimDuration = 0.5
UIView.animate(withDuration: firstAnimDuration, animations: {
/* Do here the first animation */
}) { (completed) in
let secondAnimDuration = 0.5
UIView.animate(withDuration: secondAnimDuration, animations: {
/* Do here the second animation */
})
}
现在你可能会遇到另一个问题。
如果您使用CGAffineTransform旋转视图,并为每个动画分配此类型的新对象以应用于您的view.transform,则将丢失先前的变换操作。
因此,根据这篇文章:如何在Swift中应用多个变换,您需要连接变换操作。
这是一个示例,将旋转180度并在1秒后返回原点:
let view = UIView.init(frame: CGRect.init(origin: self.view.center, size: CGSize.init(width: 100, height: 100)))
view.backgroundColor = UIColor.red
self.view.addSubview(view)
var transform = view.transform
transform = transform.rotated(by: 180)
UIView.animate(withDuration: 2, animations: {
view.transform = transform
}) { (completed) in
transform = CGAffineTransform.identity
UIView.animate(withDuration: 2, delay: 1, options: [], animations: {
view.transform = transform
}, completion: nil)
}
.animate方法为您提供了设置一些动画选项的能力。特别是UIViewAnimationOptions结构包含:
有了这个想法,您可以这样做:
var transform = view.transform.rotated(by: 180)
UIView.animate(withDuration: 2, delay: 0, options: [.repeat, .autoreverse], animations: {
self.myView.transform = transform
})
但是,您需要在两个动画之间有一个延迟,因此您需要使用以下技巧:
只需在您的ViewController中创建一个方法来为您的视图进行动画处理。在最后一个completionHandler中,只需调用该方法来创建无限循环。
最后,您需要在viewDidAppear上调用该方法以启动动画。
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.animation()
}
func animation() {
var transform = view.transform
transform = transform.rotated(by: 180)
UIView.animate(withDuration: 2, delay: 0, options: [], animations: {
self.myView.transform = transform
}) { bool in
transform = CGAffineTransform.identity
UIView.animate(withDuration: 2, delay: 1, options: [], animations: {
self.myView.transform = transform
}, completion: { bool in
self.animation()
})
}
}
CABasicAnimation
,它是一个更轻量级的动画,支持repeatCount
属性。 - dirtydanee