In this episode we take a look at CoreAnimation's easiest form of animation with CABasicAnimation. Using this class we can animate properties of a layer, such as frame, background color, paths for CAShapeLayer, and more. We also cover timing functions and how to make a transition between shapes a bit easier for the system to interpolate between.
Episode Links Episode Source Code Core Animation Programming Guide - The documentation around Core Animation is incredibly rich and full of important information. Definitely worth reading to better understand the layer system and how drawing works. objc.io - Animations Explained - a great article on Core Animation. Includes animated gifs of the animations, which helps solidify the concepts being discussed. Creating the Layer lazy var layer: CAShapeLayer = { let layer = CAShapeLayer() layer.path = UIBezierPath(rect: CGRectMake(0, 0, 100, 100)).CGPath layer.frame = CGRectMake(0, 0, 100, 100) layer.position = self.view.center layer.fillColor = UIColor.redColor().CGColor return layer }() Animating the position of the layer let posAnim = CABasicAnimation(keyPath: "position.x") posAnim.fromValue = layer.bounds.size.width / 2 posAnim.toValue = view.frame.size.width - layer.bounds.size.width / 2 posAnim.duration = anim.duration posAnim.repeatCount = 3 posAnim.autoreverses = true posAnim.delegate = self posAnim.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) layer.addAnimation(posAnim, forKey: "position") Animating the fillColor of the layer let anim = CABasicAnimation(keyPath: "fillColor") anim.fromValue = UIColor.darkGrayColor().CGColor anim.toValue = UIColor.purpleColor().CGColor anim.repeatCount = 10 anim.duration = 1.5 anim.autoreverses = true layer.addAnimation(anim, forKey: "colorAnimation") layer.fillColor = anim.fromValue as CGColorRef Animating the Path of the layer let pathAnim = CABasicAnimation(keyPath: "path") pathAnim.fromValue = layer.path pathAnim.toValue = trianglePath() pathAnim.duration = 4 pathAnim.autoreverses = true pathAnim.repeatCount = HUGE layer.addAnimation(pathAnim, forKey: "pathAnimation") The trianglePath method is defined as: func trianglePath() -> CGPathRef { let path = UIBezierPath() let w = layer.bounds.size.width let h = layer.bounds.size.height path.moveToPoint(CGPointMake(w/2, 0)) path.addLineToPoint(CGPointMake(w/2, 0)) path.addLineToPoint(CGPointMake(w, h)) path.addLineToPoint(CGPointMake(0, h)) path.closePath() return path.CGPath } Note the extra vertex here. This is useful to help guide the animation interpolator into animating properly between the triangle and square. Without it, the shape morphs in unnatural ways. For best results, always animate with the same number of vertices. Getting the actual values of the layer If you query for the fillColor, position or path during an animation, you’ll only see the value that the property contains. To get the actual values that you see on screen you need to query for the presentationLayer: func tick() { println("x: \(layer.presentationLayer()?.position.x)") } This might be nil if no animations are running, and if an animation is improperly configured then this may cause an EXC_BAD_ACCESS error.