Elhoej
Elhoej

Reputation: 751

How to make a continuously flip animation?

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

Answers (1)

Au Ris
Au Ris

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

Related Questions