Create a Rotation Animation for Album Artwork in Swift
We love minor animation, which is something we feel extraterrestrial. Today we want to show you the way we create a nicely animation for album artwork view inside our next project:
As you can see, the artwork is a circle image view, we also have to smaller circle at the center to create effect of a real CD. Then, we add a shadow to the image and finally, we make it rotate!
View Layer
Go to interface builder, and add an square UIImageView, then place two square view at center of this image:
Don’t forget to create outlets for those three views.
View Properties
Assume that we have outlets as follow:
@IBOutlet weak var diskContainer: UIView!
@IBOutlet weak var artworkDisk: UIImageView!
@IBOutlet weak var diskOuter: UIView!
@IBOutlet weak var diskInner: UIView!
Note that diskContainer
is the view containing all three views above. We will need this because when we make our image view rounded, the shadow effect will be lost, so we have to apply shadow effect onto containing view.
Next, make image view and two inner views rounded, and add the shadow to outer container like following:
self.diskInner.layer.cornerRadius = 2
self.diskOuter.layer.cornerRadius = 8
self.diskOuter.layer.borderColor = UIColor(netHex: 0x8F8F8F, alpha: 1).CGColor
self.artworkDisk.layer.cornerRadius = 80
self.diskContainer.layer.cornerRadius = 80
self.diskContainer.layer.shadowColor = UIColor.blackColor().CGColor
self.diskContainer.layer.shadowOffset = CGSizeMake(0, 0)
self.diskContainer.layer.shadowRadius = 6
self.diskContainer.layer.shadowOpacity = 0.6
self.artworkContainer.layer.shadowColor = UIColor.blackColor().CGColor
self.artworkContainer.layer.shadowOffset = CGSizeMake(0, 4)
self.artworkContainer.layer.shadowRadius = 4
self.artworkContainer.layer.shadowOpacity = 0.6
Note the cornerRadius
value is half of its size (width or height), so we can create a perfect circle.
Add Animation
We should set a beautiful image to our artwork UIImageView
first:
self.artworkDisk.image = <your-image>
Our animation will be placed inside a function:
func runSpinAnimationOn(view: UIView, duration: Double, rotation: Double, repeat: Float) {
let animation = CABasicAnimation(keyPath: "transform.rotation.z")
animation.toValue = NSNumber(double: M_PI * 2.0 * rotation * duration)
animation.duration = duration
animation.cumulative = true
animation.repeatCount = repeat
animation.removedOnCompletion = false
animation.fillMode = kCAFillModeForwards
view.layer.addAnimation(animation, forKey: "rotationAnimation") }
Here we use a CABasicAnimation
so we can control almost every aspects of the animation. We also add the animation to layer of a view, and allow caller to customize duration as well as rotation angle and repeat count.
To apply this animation to our artwork image, simply call:
self.runSpinAnimationOn(self.artworkDisk, duration: 1, rotation: M_PI / 2 / 60, repeat: MAXFLOAT)
We use MAXFLOAT
for repeat
to make our artwork spin forever, we also defining duration step by 1 second and rotation angle with value of M_PI
divide by 120. Feel free to adjust those values to achieve rotation speed of the animation. Now you can run project and see your artwork spinning.
Resume and Pause Animation
Sometimes we want to pause the rotation and resume it later. Maybe in case of buffering. To do that, we save the offset time of animation, change animation speed to zero when we want it to be paused, and change it back to 1.0 when we want to resume it. Our pause and resume functions should be like this:
func pauseAnimation(layer: CALayer) {
let pausedTime = layer.convertTime(CACurrentMediaTime(), fromLayer: nil)
layer.speed = 0
layer.timeOffset = pausedTime
}
func resumeAnimation(layer: CALayer) {
let pausedTime = layer.timeOffset
if (pausedTime > 0) {
layer.speed = 1
layer.timeOffset = 0
layer.beginTime = layer.convertTime(CACurrentMediaTime(), fromLayer: nil) - pausedTime
} else {
self.runSpinAnimationOn(self.artworkDisk, duration: 1, rotation: M_PI / 2 / 60, repeat: MAXFLOAT)
}
}
You can see that inside resumeAnimation
, we add check for pausedTime
, if it is zero then we known the animation have not been started yet, so we call run spin animation of our view.
That is it! Feel free to tell us if you have any comments or questions!