How to tame Core Animation

How to tame Core Animation

Core Animation is a wild animal - powerful and beautiful but hard to familiarize and tame. Yet, when you befriend this animal, you can do great things with app visuals. Here's my story on creating a powerful animation for Apple devices in Swift with lots of experiments, limit testing and some math.

6c9d1e82615877b0b2866f82cbf5f557?s=128

Kristaps Grinbergs

November 08, 2019
Tweet

Transcript

  1. 2.

    tame adjective Reduced from a state of native wildness especially

    so as to be tractable and useful to humans
  2. 3.
  3. 5.
  4. 12.
  5. 13.
  6. 17.

    ➡ Layer Kit ➡ August 7, 2006 WWDC ➡ Mac

    OS X 10.5 Leopard ➡ Created by John Harper About Core Animation
  7. 18.
  8. 20.

    Core Animation provides high frame rates and smooth animations without

    burdening the CPU and slowing down your app. – Apple Documentation
  9. 22.
  10. 23.
  11. 27.

    ➡ iOS, macOS and tvOS ➡ Hardware accelerated GPU ➡

    Runs on separate process Core Animation ???
  12. 36.
  13. 38.

    Views Layers vs complex, Auto Layout user interaction CPU powered

    restricted no responder chain drawn on the GPU
  14. 40.

    let bezierPath = UIBezierPath() bezierPath.move(to: point1) bezierPath.addLine(to: point2) bezierPath.addLine(to: point3)

    bezierPath.addLine(to: point1) bezierPath.close() let shapeLayer = CAShapeLayer() shapeLayer.path = bezierPath.cgPath shapeLayer.lineWidth = 0 shapeLayer.fillColor = fillColor.cgColor self.layer.addSublayer(shapeLayer)
  15. 41.

    let bezierPath = UIBezierPath() bezierPath.move(to: point1) bezierPath.addLine(to: point2) bezierPath.addLine(to: point3)

    bezierPath.addLine(to: point1) bezierPath.close() let shapeLayer = CAShapeLayer() shapeLayer.path = bezierPath.cgPath shapeLayer.lineWidth = 0 shapeLayer.fillColor = fillColor.cgColor self.layer.addSublayer(shapeLayer)
  16. 42.

    let bezierPath = UIBezierPath() bezierPath.move(to: point1) bezierPath.addLine(to: point2) bezierPath.addLine(to: point3)

    bezierPath.addLine(to: point1) bezierPath.close() let shapeLayer = CAShapeLayer() shapeLayer.path = bezierPath.cgPath shapeLayer.lineWidth = 1 shapeLayer.fillColor = fillColor.cgColor self.layer.addSublayer(shapeLayer)
  17. 43.

    let bezierPath = UIBezierPath() bezierPath.move(to: point1) bezierPath.addLine(to: point2) bezierPath.addLine(to: point3)

    bezierPath.addLine(to: point1) bezierPath.close() let shapeLayer = CAShapeLayer() shapeLayer.path = bezierPath.cgPath shapeLayer.lineWidth = 1 shapeLayer.fillColor = fillColor.cgColor self.layer.addSublayer(shapeLayer)
  18. 44.
  19. 45.
  20. 46.

    let pathAnimation = CABasicAnimation(keyPath: #keyPath(CAShapeLayer.path)) shapeLayer.add(pathAnimation, forKey: "pathAnimation") pathAnimation.toValue =

    triangle.cgPath pathAnimation.duration = 1.0 pathAnimation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut) pathAnimation.autoreverses = true pathAnimation.repeatCount = .greatestFiniteMagnitude
  21. 47.

    let pathAnimation = CABasicAnimation(keyPath: #keyPath(CAShapeLayer.path)) shapeLayer.add(pathAnimation, forKey: "pathAnimation") pathAnimation.toValue =

    triangle.cgPath pathAnimation.duration = 1.0 pathAnimation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut) pathAnimation.autoreverses = true pathAnimation.repeatCount = .greatestFiniteMagnitude
  22. 48.

    let pathAnimation = CABasicAnimation(keyPath: #keyPath(CAShapeLayer.path)) shapeLayer.add(pathAnimation, forKey: "pathAnimation") pathAnimation.toValue =

    triangle.cgPath pathAnimation.duration = 1.0 pathAnimation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut) pathAnimation.autoreverses = true pathAnimation.repeatCount = .greatestFiniteMagnitude
  23. 49.

    let pathAnimation = CABasicAnimation(keyPath: #keyPath(CAShapeLayer.path)) shapeLayer.add(pathAnimation, forKey: "pathAnimation") pathAnimation.toValue =

    triangle.cgPath pathAnimation.duration = 1.0 pathAnimation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut) pathAnimation.autoreverses = true pathAnimation.repeatCount = .greatestFiniteMagnitude
  24. 50.
  25. 51.

    let animationGroup = CAAnimationGroup() animationGroup.animations = [...] animationGroup.autoreverses = true

    animationGroup.repeatCount = .greatestFiniteMagnitude animationGroup.duration = 2.0
  26. 52.

    let animationGroup = CAAnimationGroup() animationGroup.animations = [...] animationGroup.autoreverses = true

    animationGroup.repeatCount = .greatestFiniteMagnitude animationGroup.duration = 2.0
  27. 53.

    let animationGroup = CAAnimationGroup() animationGroup.animations = [...] animationGroup.autoreverses = true

    animationGroup.repeatCount = .greatestFiniteMagnitude animationGroup.duration = 2.0
  28. 54.
  29. 55.
  30. 56.
  31. 57.
  32. 58.
  33. 59.
  34. 62.
  35. 63.
  36. 66.
  37. 67.

    Know when it’s too much CA is powerful & well

    documented API Hard to do something out of bounds Conclusions
  38. 68.