A small DSL to chain animations on top of UIKit
Swift Ruby Objective-C
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
Demo
Resources
Sources
SwiftAnimations.xcodeproj
Tests
.gitignore
.swift-version
.swiftlint.yml
.travis.yml
CHANGELOG.md
Gemfile
LICENSE
Package.swift
README.md
SwiftAnimations.podspec

README.md

Build Status Carthage compatible

Pod Platform Pod License

codebeat badge cocoapods-doc Readme Score

SwiftAnimations

SwiftAnimations is a small DSL to chain of animations on top of UIKit, unify animation parameters across all application and simplify even more your animation code.

Features

  • Chain simple animations with less and more concise code
  • Sensible default values, so you don't repeat information across all animation blocks
  • Opt in to configure whatever values you see fit on every animation, as opposed to declaring (and repeating) whole list of parameters for every one
  • Default values can be configured for all animations across all application. Change only the values that are different for the specific animation
  • Support for spring and standard animations

Chaining animations

Turn complex sequences of animations into simple cascade and easy to read code:

// Start with a call to 'animate'
animate {
  self.red.transform = CGAffineTransformMakeRotation(CGFloat(M_PI_2))
}.thenAnimate {   // Chain animations, to be executed in order
  self.green.transform = CGAffineTransformMakeRotation(-CGFloat(M_PI_2))
}.afterDelay(1)
 .thenAnimate {
  self.blue.transform = CGAffineTransformMakeScale(1.5, 1)
}.withOptions(.CurveEaseOut).thenAnimate {
  self.yellow.transform = CGAffineTransformMakeScale(1, 1.5)
}.withOptions(.CurveEaseOut).thenAnimate {
  let scale = CGAffineTransformMakeScale(0.5, 0.5)
  self.red.transform = scale
  self.green.transform = scale
  self.blue.transform = scale
  self.yellow.transform = scale
}.completion { completed in
 // Completion of all animations
  println("Completed!")
}

Unified animation values and default values

SwiftAnimations configures all animations with default values for duration, curve, and spring damping and velocity. You can change this globally or per-animation.

// All animations in my app have a baseline of 0.35. I rarely change this
setDefaultAnimationDuration(0.35)
// All animations in my app by default EaseIn EaseOut.
setDefaultAnimationCurve(.EaseInOut)

Also by default animations are 'standard', not spring animations. You can make all animations change the system call they use by switching a simple configuration value:

// I want unified look across application, and I will be using spring animations everywhere unless otherwise specified
setDefaultAnimationType(.Spring)
// Moreover, tedious repetition removed by specifying a default value for damping and velocity
setDefaultSpringDamping(0.1)
setDefaultInitialVelocity(0.3)

If you don't specify default values, the library will use the default ones.

Per-animation parameters

You can also change specific values per-animation:

animate {
  // Animation 1
}.withOptions(.CurveEaseOut).withDuration(0.5).thenAnimate {   // Modify how 'previous' animation is performed
  // Animation 2
}.withDuration(0.1).withType(.Spring).thenAnimate {
  // Animation 3
}.withType(.Regular)
 .afterDelay(0.2)

Roadmap

Later I will be adding redefined animations. And maybe a way to configure those as well across all application code.

animate(flip(self.avatarView))
.thenAnimate(bounce(self.button)).start()

Suggestions and pull requests welcome :)

Why?

UIKit animations API is designed to be simple. It does it job very well for fire-and-forget animations. But there are some times where the application demands not so simple animations.

There are often times when two or three animations need to be chained to achieved desired visual effects. Generally this can be easily done by nesting UIKit.animateWithDuration(...) calls, like so:

UIView.animateWithDuration(0.3, animations: {
  //AnimationA
}, completion: {
  UIView.animateWithDuration(0.3, animations: {
    //AnimationB
  }, completion: {
    UIView.animateWithDuration(0.3, animations: {
      //AnimationC
    }, completion: {
      UIView.animateWithDuration(0.3, animations: {
        //AnimationD
      }, completion: {
        //Usual cleanup
      })
    })
  })
})

Imagine how this thing looks in Objective-C.

There is a big problem with this approach, and it is readability. Swift can make it a bit less painful if you abstract the animations into inner functions of the current function, but I would say that it is very ugly code. And I believe that animation and UI code should be crystal clear, so you don't have to run everything to see what will move around, and where.

See more in the article I wrote

Installation

##CocoaPods Add the pod to your Podfile. Being a Swift-only library, it is required to be linked as a framework (dynamic library).

use_frameworks!
pod 'SwiftAnimations'

Carthage

Add the repository to your Cartfile.

github "DarthMike/SwiftAnimations"

Then drag and drop the produced SwiftAnimations.framework from Carthage/build

Manual

Just drop into your project the files under Source directory.

Author

Miguel Angel Quiñones / @miguelquinon

Inspiration

This idea took off from working in my current project using Swift, and after seeing Spring