Reputation: 751
I have been trying to create an animation that simulates a coin flip toss. This is what I am currently using, but there is a slight delay between each animation execution, and I don't think UIView.transition is the optimal way to do it.
var duration: CGFloat = 0.25
var imageIndex = 1
var repeatCount = 0
@objc func handleSpin()
{
let options: UIViewAnimationOptions = .transitionFlipFromLeft
UIView.transition(with: self.coinImageView, duration: TimeInterval(duration), options: options, animations: nil) { (completed) in
if self.repeatCount == 10
{
self.duration = 0.25
self.imageIndex = 1
self.repeatCount = 0
return
//animation done
}
else
{
self.coinImageView.image = UIImage(named: self.imageNames[self.imageIndex])
self.duration += 0.075
self.repeatCount += 1
self.imageIndex = self.imageIndex == self.imageNames.count - 1 ? 0 : self.imageIndex + 1
self.handleSpin()
}
}
This function calls itself 10 times, increasing the animation duration a little every time. But as I said the problem is there is a slight delay between each execution which I want to fix.
I have also tried with CATransition, and adding it to the layer of the imageView like this:
func flipAnimation()
{
let animation = CATransition()
animation.type = "flip"
animation.startProgress = 0
animation.endProgress = 0.5
animation.subtype = "fromLeft"
animation.duration = 0.5
animation.repeatCount = 0
self.layer.add(animation, forKey: "animation")
}
The problem here is that I can't get image to stay flipped, as it reverts back to default when the animation finishes, furthermore I don't know how to keep track of when the animation is done.
Is there a third and better way of doing this?
EDIT: I should mention that I have also tried using the Spring library, but it has the same problem with CATransition; when the animation finishes the image get reverted back to it’s normal state and I can’t find any way of preventing that.
Upvotes: 1
Views: 1041
Reputation: 4659
You could try animate keyframes, maybe this would look better:
extension UIView {
func startAnimatingFlip(with duration: TimeInterval) {
UIView.setAnimationCurve(.linear)
UIView.animateKeyframes(withDuration: duration / 2, delay: 0, options: .beginFromCurrentState, animations: {
UIView.setAnimationCurve(.linear)
UIView.addKeyframe(withRelativeStartTime: duration / 2, relativeDuration: 0.5, animations: {
self.transform = CGAffineTransform(scaleX: -1, y: 1)
})
UIView.addKeyframe(withRelativeStartTime: 0.5, relativeDuration: 0.5, animations: {
self.transform = CGAffineTransform(scaleX: 1, y: 1)
})
}) { _ in
self.startAnimatingFlip(with: duration)
}
}
}
Of course you'll have to adjust it to your needs. But in terms of animation, doesn't seem to have any delay between keyframes.
Upvotes: 1