Day 57 - 100 Days of Swift
Project 15 (part 1)
Day 57 is the first part of the fifteenth project. It is a technique project on animation using UIView.animate
. You look at scaling, translating and rotating with CGAffineTransform
and you look at animating other properties on a UIView
. You also look at a couple of basic options you can add to an animation.
First, you use the storyboard to give yourself a button at the bottom center of the screen (it doesn’t really matter where), tie it to an action in ViewController.swift
and then add a couple of variables:
1
2
3
4
5
var imageView: UIImageView!
var currentAnimation = 0
@IBAction func tapped(_ sender: UIButton) {
}
You set up imageView
in viewDidLoad
:
1
2
3
imageView = UIImageView(image: UIImage(named: "penguin"))
imageView.center = CGPoint(x: 512, y: 384)
view.addSubview(imageView)
Then, at the end of tapped()
you add this code to rotate through the current animation:
1
2
currentAnimation += 1
currentAnimation %= 8
This adds 1 to currentAnimation
and then sets it to the results of currentAnimation % 8
. This is a clean way of cycling through the numbers 0-7.
Next, you add a call to UIView.animate
with a switch
statement to perform the different animations:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
sender.isHidden = true
UIView.animate(withDuration: 1,
delay: 0,
options: [],
animations: {
switch self.currentAnimation {
case 0:
break
default:
break
}
}) { _ in
sender.isHidden = false
}
Right now this doesn’t actually do anything, but once we add the animations, it will hide the button, perform the animation, and then unhide the button.
The first animation you add is to scale up the image view and scale it back to it’s original size:
1
2
3
4
case 0:
self.imageView.transform = CGAffineTransform(scaleX: 2, y: 2)
case 1:
self.imageView.transform = .identity

Then you add a translation:
1
2
3
4
5
case 2:
self.imageView.transform = CGAffineTransform(translationX: -256,
y: -256)
case 3:
self.imageView.transform = .identity

Then you add a rotation:
1
2
3
4
case 4:
self.imageView.transform = CGAffineTransform(rotationAngle: CGFloat.pi)
case 5:
self.imageView.transform = .identity

And finally, you animate the opacity and background color at the same time:
1
2
3
4
5
6
case 6:
self.imageView.alpha = 0.1
self.imageView.backgroundColor = .green
case 7:
self.imageView.alpha = 1
self.imageView.backgroundColor = .clear

The only modification I made was to get rid of cases 1, 3, and 5 and make the default
case be to reset the identity:
1
2
default:
self.imageView.transform = .identity
This just gets rid of a little bit of the duplicate code.
Finally, you add a little bit of spring to the animation like this:
1
2
3
4
5
6
UIView.animate(withDuration: 1,
delay: 0,
usingSpringWithDamping: 0.5,
initialSpringVelocity: 5,
options: [],
animations: {
That leads to animations that look like this:




You can find my version of this project at the end of day 57 on Github here.
Reflections
Animations are a lot of fun. They can definitely bring a lot of whimsy to an app, if they are implemented well and don’t keep the user from getting their work done. The main thing that usually keeps me from doing many animations is that it seems like it will be a lot of work. I have some experience with animation outside of the programming environment (mostly with After Effects), and I know how long it can take to dial in those keyframes. But it is amazing how easy some things can be with the system APIs. These animations all look great (with the exception of the opacity/color one, which I think is mostly there for demonstration purposes) and it took very little code to get them up and running. That’s awesome!