TweenKit is a powerful animation library that allows you to animate (or ‘tween’) anything. TweenKit’s animations are also scrubbable, perfect for building awesome onboarding experiences!

Download the example project to see how these animations were created

###TweenKit’s animations are:

  • Reveseable
  • Repeatable
  • Groupable
  • Sequenceable
  • Scrubbable
  • Quick and easy to use!

Example

The example project contains a collection of examples of how to use TweenKit. Run Example.xcodeproj

Importing TweenKit

Add import TweenKit to the top of the files you want to use TweenKit from

Actions

TweenKit’s animations are composed of ‘Actions’. These are small animation units that can be chained or grouped to build complex animations. Once you have created an action, you can tell the scheduler to run it.

scheduler.run(action: myAction)
Copy the code

Grouping actions

Using an ActionGroup, several animations can be run at once. For instance, we can change a view’s frame and it’s background color:

// Create a move action let fromRect = CGRect(x: 50, y: 50, width: 40, height: 40) let toRect = CGRect(x: 100, y: 100, width: 200, height: 100) Let move = InterpolationAction(from: fromRect, to: toRect, duration: 2.0, easing: .elasticOut) { [unowned self] in self.squareView.frame = $0 } // Create a color change action let changeColor = InterpolationAction(from: uicolor. red, to: uicolor. orange, duration: 2.0, easing: .exponentialOut) { [unowned self] in self.squareView.backgroundColor = $0 } // Make a group to run them at the same time  let moveAndChangeColor = ActionGroup(actions: move, changeColor) scheduler.run(action: moveAndChangeColor)Copy the code

Running actions in sequence

Using an ActionSequence, several animations can be run in order. This time, we can use supply a closure as the ‘from’ parameter, to animate the view from it’s current frame:

let moveOne = InterpolationAction(from: { [unowned self] in self.squareView.frame },
                                  to: CGRect(x: 120, y: 80, width: 50, height: 50),
                                  duration: 1,
                                  easing: .exponentialInOut) {
                                   [unowned self] in self.squareView.frame = $0
}
        
let moveTwo = InterpolationAction(from: { [unowned self] in self.squareView.frame },
                                  to: CGRect(x: 70, y: 120, width: 130, height: 130),
                                  duration: 1,
                                  easing: .exponentialInOut) {
                                    [unowned self] in self.squareView.frame = $0
}
        
let moveTwice = ActionSequence(actions: moveOne, moveTwo)
scheduler.run(action: moveTwice)
Copy the code

Repeating actions

Use RepeatAction to repeat your actions, or RepeatForeverAction to repeat an action forever. You can easily contruct these using the repeated(times:) and repeatedForever methods on any action:

let repeatedForever = myAction.repeatedForever()
scheduler.run(action: repeatedForever)
Copy the code

Arc Actions

ArcAction can animate any object that conforms to Tweenable2DCoordinate in a circular motion.

By creating some ArcActions in a staggared Group, we can easily create an activity indicator:

// Create an ArcAction for each circle layer let actions = circleLayers.map{ layer -> ArcAction<CGPoint> in let action =  ArcAction(center: self.view.center, radius: radius, startDegrees: 0, endDegrees: 360, duration: 1.3) {[unowned layer] in layer.center = $0} action.easing =.sineinout return action} // Run the actions in a staggered group let group = ActionGroup(staggered: actions, offset: // Run the action scheduler. Run (action: scheduler) repeatForever)Copy the code

Bezier Actions

Objects can be animated along a bezier path using BezierAction. The callback supplies both position and rotation.

BezierAction can animate any value that conforms to the Tweenable2DCoordinate protocol.

let action = BezierAction(path: bezierPath, duration: 4.0) {[unowned self] (postion, rotation) in self.rocketImageView.center = postion let rocketRotation = CGFloat(rotation.value) self.rocketImageView.transform = CGAffineTransform(rotationAngle: rocketRotation) } action.easing = .exponentialInOut scheduler.run(action: action)Copy the code

Scrubbable actions

Scrubbable Actions are great for building unique onboarding experiences.

Instead of adding the action to a scheduler, create an ActionScrubber instance:

let move = InterpolationAction(from: { [unowned self] in self.squareView.frame },
                               to: CGRect(x: 130, y: 100, width: 100, height: 100),
                               duration: 1,
                               easing: .elasticOut) {
                                [unowned self] in self.squareView.frame = $0
}
        
self.actionScrubber = ActionScrubber(action: move)

// Scrub the action in a UISlider callback
func sliderChanged(slider: UISlider) {
    actionScrubber.update(t: Double(slider.value))
}
Copy the code

Animating your own objects

By adding conformance to the Tweenable protocol, anything can be animated. You decide what it means to ‘tween’ your object, making this a flexible approach.

For instance, by conforming String to Tweenable we can turn a bat into a cat:

InterpolationAction(from: "bat",
                    to: "cat",
                    duration: 4,
                    easing: .exponentialInOut) {
                     [unowned self] in self.label.text = $0
}
Copy the code

Other Stuff

Use DelayAction to add a delay in to a sequence

Use CallBlockAction to trigger a callback at any point in a sequence

[email protected]

@stevebarnegren

License

TweenKit is available under the MIT license. See the LICENSE file for more info.