ADDC 2017 - John Sundell: Creating great animations on iOS

ADDC 2017 - John Sundell: Creating great animations on iOS

Animations are a huge part of modern application design - and on iOS we have quite a number of tools at our disposal to create great ones to delight & inform our users. Durning this talk, John will go through several animation techniques and talk about how they can be used to create a smooth workflow for both developers & designers - and resulting in a great user experience.

More about the talk, authors & slides: https://addconf.com/talks/7/
Read about the conference: https://addconf.com

Transcript

  1. 7.
  2. 8.
  3. 9.
  4. 11.
  5. 13.
  6. 14.
  7. 15.
  8. 16.
  9. 19.
  10. 21.
  11. 22.

    Jump let jumpAction = SKAction.sequence([ .moveBy(x: 0, y: 3, duration:

    0.1), .moveBy(x: 0, y: -3, duration: 0.1) ]) let carAction = SKAction.sequence([ jumpAction .wait(forDuration: 2) ])
  12. 23.

    Jump let jumpAction = SKAction.sequence([ .moveBy(x: 0, y: 3, duration:

    0.1), .moveBy(x: 0, y: -3, duration: 0.1) ]) let carAction = SKAction.sequence([ jumpAction .wait(forDuration: 2) ]) carNode.run(.repeatForever(carAction))
  13. 24.

    Jump let jumpAction = SKAction.sequence([ .moveBy(x: 0, y: 3, duration:

    0.1), .moveBy(x: 0, y: -3, duration: 0.1) ]) let wheelAction = SKAction.sequence([ .rotate(byAngle: .pi * 2, duration: 1.5) jumpAction ]) wheelNode.run(.repeatForever(wheelAction)) Rotate & jump let carAction = SKAction.sequence([ jumpAction .wait(forDuration: 2) ]) carNode.run(.repeatForever(carAction))
  14. 25.

    Jump let jumpAction = SKAction.sequence([ .moveBy(x: 0, y: 3, duration:

    0.1), .moveBy(x: 0, y: -3, duration: 0.1) ]) let wheelAction = SKAction.sequence([ .rotate(byAngle: .pi * 2, duration: 1.5) jumpAction ]) wheelNode.run(.repeatForever(wheelAction)) Rotate & jump let carAction = SKAction.sequence([ jumpAction .wait(forDuration: 2) ]) carNode.run(.repeatForever(carAction))
  15. 26.

    ) Great for complex stand-alone scenes - Easy to compose

    actions to build animations . Create hierarchies matching the asset structure ♻ Actions can be reused and their parameters can be easily tweaked SpriteKit
  16. 30.

    button.alpha = 0 UIView.animate(withDuration: 0.3, animations: { button.alpha = 1

    }, completion: { _ in UIView.animate(withDuration: 0.3) { button.frame.size = CGSize(width: 200, height: 200) } })
  17. 35.

    struct Animation { var duration: TimeInterval var closure: (UIView) ->

    Void } extension Animation { } static func fadeIn(duration: TimeInterval) -> Animation { return Animation(duration: duration, closure: { $0.alpha = 1 }) } static func scale(to size: CGSize, duration: TimeInterval) -> Animation { return Animation(duration: duration, closure: { $0.frame.size = size }) }
  18. 36.

    extension UIView { func animate(_ animations: [Animation]) { guard !animations.isEmpty

    else { return } var animations = animations let animation = animations.removeFirst() UIView.animate(withDuration: animation.duration, animations: { animation.closure(self) }, completion: { _ in self.animate(animations) }) } }
  19. 37.

    extension UIView { func animate(_ animations: [Animation]) { guard !animations.isEmpty

    else { return } var animations = animations let animation = animations.removeFirst() UIView.animate(withDuration: animation.duration, animations: { animation.closure(self) }, completion: { _ in self.animate(animations) }) } } Exit condition
  20. 38.

    extension UIView { func animate(_ animations: [Animation]) { guard !animations.isEmpty

    else { return } var animations = animations let animation = animations.removeFirst() UIView.animate(withDuration: animation.duration, animations: { animation.closure(self) }, completion: { _ in self.animate(animations) }) } } Exit condition Take out the next animation
  21. 39.

    extension UIView { func animate(_ animations: [Animation]) { guard !animations.isEmpty

    else { return } var animations = animations let animation = animations.removeFirst() UIView.animate(withDuration: animation.duration, animations: { animation.closure(self) }, completion: { _ in self.animate(animations) }) } } Exit condition Take out the next animation Perform the animation
  22. 40.

    extension UIView { func animate(_ animations: [Animation]) { guard !animations.isEmpty

    else { return } var animations = animations let animation = animations.removeFirst() UIView.animate(withDuration: animation.duration, animations: { animation.closure(self) }, completion: { _ in self.animate(animations) }) } } Exit condition Take out the next animation Perform the animation Recursively call the method
  23. 41.
  24. 42.
  25. 44.

    burrito.animate([ .scale(to: burrito.frame.size * 1.5, duration: 0.3), .move(to: basket.center, duration:

    0.3) ]) burrito.animate(inParallel: [ .scale(to: burrito.frame.size * 0.5, duration: 0.3), .fadeOut(duration: 0.3) ]) iHungry 0 1 2 3 4 5 6 7 8 9 : ; < = >
  26. 45.

    burrito.animate([ .scale(to: burrito.frame.size * 1.5, duration: 0.3), .move(to: basket.center, duration:

    0.3) ]) burrito.animate(inParallel: [ .scale(to: burrito.frame.size * 0.5, duration: 0.3), .fadeOut(duration: 0.3) ]) basket.animate([ .scale(to: basket.frame.size * 1.5, duration: 0.3), .scale(to: basket.frame.size, duration: 0.3) ]) iHungry 0 1 2 3 4 5 6 7 8 9 : ; < = >
  27. 46.

    burrito.animate([ .scale(to: burrito.frame.size * 1.5, duration: 0.3), .move(to: basket.center, duration:

    0.3) ]) burrito.animate(inParallel: [ .scale(to: burrito.frame.size * 0.5, duration: 0.3), .fadeOut(duration: 0.3) ]) basket.animate([ .scale(to: basket.frame.size * 1.5, duration: 0.3), .scale(to: basket.frame.size, duration: 0.3) ]) badge.animate(.fadeIn(duration: 0.3)) iHungry 0 1 2 3 4 5 6 7 8 9 : ; < = > 1
  28. 47.
  29. 49.
  30. 56.
  31. 65.

    + Swordsman/Moving/Right 0@2x.png 1@2x.png 2@2x.png 3@2x.png 4@2x.png 5@2x.png 6@2x.png 7@2x.png

    Duration.txt B Animation( name: "Swordsman/Right/Moving", frameCount: , duration: 1.12 ) 8
  32. 66.

    + Swordsman/Moving/Right 0@2x.png 1@2x.png 2@2x.png 3@2x.png 4@2x.png 5@2x.png 6@2x.png 7@2x.png

    Duration.txt B Animation( name: "Swordsman/Right/Moving", frameCount: , duration: 1.12 ) 8@2x.png 9
  33. 67.

    %