A Fast Animation Engine with an Intuitive API

Overview

Kinieta

An Animation Engine for iOS with an Intuitive API and Readable Code! (Written in Swift 4.0.)

Why another?

I decided to build an Animation Engine from scratch for the usual reason: No other did what I wanted how I wanted it! While there are some great libraries out there, my requiremenets where pretty restrictive as what I wanted was:

  • A library written in Swift 4.0
  • With a timeline approach where animations can run in parallel at different start and end points
  • The ability to group various animations from different views with a single complete block
  • A simple API where I could just throw in some variables and the rest would be dealt by the library
  • A convention over configuration approach where many variables would be assumed when not passed
  • Efficient interpolation with infinite easing functions based on custom Bezier curves
  • Provides real color interpolation using the advanced HCL color space rather than plain RGB
  • Code that was extremely easy to read and new developers from the community could join in in no time!

Installation

Cocoa Pods

pod 'Kinieta', '~> 0.5'

Manual

For the moment, just copy the files in the Kinieta (virtual) folder

How to Use

square.move(to: ["x": 374], during: 1.0).easeInOut(.Back).wait(for: 1.0).complete {
    square.move(to: ["x": 74])
}

Basic Move with Ease

Basic Usage

An extension on UIView that is included in the code will provide the entry point for the animations. The interface object is the Kinieta and there is one for every view.

// This will snap the view to the given coordinates
aView.move(to: ["x": 250, "y": 500])

// This will animate the same view to the coordinates in 0.5 seconds
aView.move(to: ["x": 250, "y": 500], during: 0.5)

// This will delay the start of the animation by 0.5 seconds
aView.move(to: ["x": 250, "y": 500], during: 0.5).delay(for: 0.5)

// And this will ease the whole thing
aView.move(to: ["x": 250, "y": 500], during: 0.5).delay(for: 0.5).easeInOut()

// While this will ease it with a bounce-back
aView.move(to: ["x": 250, "y": 500], during: 0.5).delay(for: 0.5).easeInOut(.Back)

// And call the complete block when the animation is finished
aView.move(to: ["x": 250, "y": 500], during: 0.5).delay(for: 0.5).easeInOut(.Back).complete { print("") }

The UIView properties that can be animated, together with their keys are:

Key Value Type Metric Property Animated
"x" Any Numeric screen points frame.origin.x
"y" Any Numeric screen points frame.origin.y
"w" or "width" Any Numeric screen points frame.size.width
"h" or "height" Any Numeric screen points frame.size.height
"a" or "alpha" Any Numeric 0 to 1 transparency alpha
"r" or "rotation" Any Numeric degrees transform
"frame" CGRect composite frame
"bg" or "background" UIColor color backgroundColor
"brc" or "borderColor" UIColor color layer.borderColor
"brw" or "borderWidth" UIColor screen points layer.borderWidth
"crd" or "cornerRadius" UIColor bevel radius layer.cornerRadius

Note: When two synonymous keys (like "bg" and "background") are passed in the same list the most verbose (ie. "background") will win over and the other will be silently ignored.

Easing

Every move can be smoothed by calling one of the 3 easing functions and pass:

// When no curve is passed `.Quad` is used
aView.move(to: ["x": 250, "y": 500], during: 0.5).easeIn()

// Ease at start, end and both ends respectively
aView.move(to: ["x": 250, "y": 500], during: 0.5).easeIn(.Cubic)
aView.move(to: ["x": 250, "y": 500], during: 0.5).easeOut(.Cubic)
aView.move(to: ["x": 250, "y": 500], during: 0.5).easeInOut(.Cubic)

An default argument can be passed to provide an easing functions to be used, Quad being the default. All easing is based on Bezier curves and many are provided by default as seen in the Easing.Types enum.

enum Types {
    case Sine
    case Quad
    case Cubic
    case Quart
    case Quint
    case Expo
    case Back 
    case Custom(Bezier)
}

The last type .Custom will capture a custom Bezier curve and use that as an easing function. A 3rd degree (or cubic) Bezier curve is composed of 4 points called control points. The first and last is by convetion (0.0, 0.0) and (1.0, 1.0) while the other 2 define the curvature. You will not have to figure out these numbers by hand of course as they are useful tools throughout the web to help with that, cubic-bezier being one of them.

For example, for a very fast start and sudden slow down animation I used this curve as taken from the site, and plugged the numbers in a Bezier instance:

let myBezier = Bezier(0.16, 0.73, 0.89, 0.24)
aView.move(to: ["x": 250, "y": 500], during: 1.0).easeInOut(.Custom(myBezier))

Move with Custom Ease

All the curves passed are prebaked into tables for fast resolution!

Sequencing

You can string a few animations together very easily:

let start = ["x": aView.x, "y": aView.y]
aView.move(to: ["x": 250, "y": 500], during: 0.5).easeInOut(.Cubic)
     .move(to: ["x": 300, "y": 200], during: 0.5).easeInOut(.Cubic)
     .move(to: start, during: 0.5).easeInOut(.Cubic)

The dictionary with the animations can be saved and passed later as the example above shows. You can also add a pause between animations by calling the wait(for time: TimeInterval) function:

aView.move(to: ["x": 250, "y": 500], during: 0.5).easeInOut(.Cubic)
     .wait(for: 0.5)
     .move(to: ["x": 300, "y": 200], during: 0.5).easeInOut(.Cubic)

Finally, you can repeat the animation sequence with the again(times: Int = 1) function.

aView.move(to: ["x": 250, "y": 500], during: 0.5).easeInOut(.Cubic)
     .move(to: ["x": 300, "y": 200], during: 0.5).easeInOut(.Cubic)
     .again()

Parallelizing

You can run various animations together to achieve more complicated effects. For example, we can add a short fade at the end of a move and have a single callback when everything finishes:

aView.move(to: ["x": 200, "y": 500], during: 1.0).easeInOut(.Cubic)
     .move(to: ["a": 0], during: 0.2).delay(for: 0.8).easeOut()
     .parallel()
     .complete { print("Finished All") }

Move with Custom Ease

Potential Pitfalls in Combining Groups

What .parallel() does is to create an internal group with all the actions that preceded the call added inside. This might cause a problem when two or more parallel groups need to be run sequencially. For example:

aView.move(to: ["x": 300], during: 1.0).easeInOut() // this needs to run first,
    .move(to: ["x": 200], during: 1.0).easeInOut() // then this...
    .move(to: ["a": 0], during: 0.2).easeOut()     // ...parallel with this!
    .parallel()

The code above will take all three moves and run then in parallel, esentially ignoring the first. What we wanted however is for the first move to run on its own followed by the other 2 in parallel. To achive this we call the then property as follows:

aView.move(to: ["x": 300], during: 1.0).easeInOut() 
    .then        
    .move(to: ["x": 200], during: 1.0).easeInOut() 
    .move(to: ["a": 0], during: 0.2).easeOut()     
    .parallel()

For more information on how the engine works to combine actions please consult the wiki.

Grouping

You can group multiple animation of different views and get a common complete handler when they all finish.

Engine.shared.group([
    aView.move(to: ["x": 374], during: 1.0).easeInOut(.Cubic)
         .move(to: ["a": 0], during: 0.2).delay(for: 0.8).easeOut().parallel(),
    otherView.move(to: ["x": 100, "r": 30], during: 1.0).easeInOut(.Cubic)
]) { print("Both Finished") }

Remember that calls to the Kinieta API return an object so one could also do:

let move1 = aView.move(to: ["x": 374], during: 1.0).easeInOut(.Cubic)
let move2 = otherView.move(to: ["x": 100, "r": 30], during: 1.0).easeInOut(.Cubic)
Engine.shared.group([move1, move2]) { print("Both Finished") }
You might also like...
Ease is an event driven animation system that combines the observer pattern with custom spring animations as observers
Ease is an event driven animation system that combines the observer pattern with custom spring animations as observers

Ease is an event driven animation system that combines the observer pattern with custom spring animations as observers. It's magic. Features Animate a

Elegant SVG animation kit for swift
Elegant SVG animation kit for swift

Elephant This is SVG animation presentation kit for iOS. Example You can run example app. Please open Example-iOS/Elephant-iOS.xcworkspace! Usage You

Gemini is rich scroll based animation framework for iOS, written in Swift.
Gemini is rich scroll based animation framework for iOS, written in Swift.

Overview What is the Gemini? Gemini is rich scroll based animation framework for iOS, written in Swift. You can easily use GeminiCollectionView, which

Design and prototype customized UI, interaction, navigation, transition and animation for App Store ready Apps in Interface Builder with IBAnimatable.
Design and prototype customized UI, interaction, navigation, transition and animation for App Store ready Apps in Interface Builder with IBAnimatable.

Design and prototype customized UI, interaction, navigation, transition and animation for App Store ready Apps in Interface Builder with IBAnimatable.

🎨 Gradient animation effect like Instagram
🎨 Gradient animation effect like Instagram

Pastel 🎨 Gradient animation effect like Instagram Example override func viewDidLoad() { super.viewDidLoad() let pastelView = PastelView(fram

Pulse animation for iOS written with Swift.
Pulse animation for iOS written with Swift.

Pulsator Pulse animation for iOS written with Swift. Great For: Pulses of Bluetooth, BLE, beacons (iBeacon), etc. Map Annotations Installation CocoaPo

A fantastic Physical animation library for swift
A fantastic Physical animation library for swift

A fantastic Physical animation library for swift(Not Just Spring !!!), it is base on UIDynamic and extension to it, friendly APIs make you use it or c

ZoomTransitioning provides a custom transition with image zooming animation and swiping the screen edge.

ZoomTransitioning Overview ZoomTransitioning provides a custom transition with image zooming animation. When you use this library with UINavigationCon

Easy animation library on iOS with Swift2
Easy animation library on iOS with Swift2

Cheetah Cheetah is an animation utility on iOS with Swift. Cheetah can animate any properties since Cheetah uses simple CADisplayLink run loop to chan

Comments
  • Nice wrapper, this usage block of code doesn't compile!

    Nice wrapper, this usage block of code doesn't compile!

    Hi,

    Nice wrapper, this usage block of code doesn't compile!, I am not sure what's wrong

    Engine.shared.group([ aView.move(to: ["x": 374], during: 1.0).easeInOut(.Cubic) .move(to: ["a": 0], during: 0.2).delay(for: 0.8).easeOut().parallel(), otherView.move(to: ["x": 100, "r": 30], during: 1.0).easeInOut(.Cubic) ]) { print("Both Finished") }

    It produces the following error Value of type 'Kinieta' does not conform to expected element type 'Action'

    I hope its a simple fix since this block code is the usage on the github site.

    Thanks

    opened by waelsaad 0
Owner
Michael Michailidis
iOS + Node.js = ❤
Michael Michailidis
YapAnimator is your fast and friendly physics-based animation system

YapAnimator is your fast and friendly physics-based animation system. YapAnimator was built with ease-of-use in mind, keeping you sane and your design

Yap Studios 1.9k Dec 6, 2022
Simple Interface Core Animation. Run type-safe animation sequencially or parallelly

Simple Interface Core Animation Sica can execute various animations sequentially or parallelly. Features Animation with duration and delay parallel /

CATS Open Source Softwares 1k Nov 10, 2022
An experiment for using SwiftUI's custom timing Animation to create an orbital-like animation.

Orbital-SwiftUI-Animation An experiment for using SwiftUI's custom timing curve to create an orbital-like animation. How it looks: How it works: Apply

Mostafa Abdellateef 7 Jan 2, 2023
SwiftUI-Text-Animation-Library - Text animation library for SwiftUI

⚠️ This repository is under construction. SwiftUI Text Animation Library Make yo

null 28 Jan 8, 2023
Swiftui-animation-observer - Track SwiftUI animation progress and completion via callbacks

SwiftUI Animation Observer Track SwiftUI animation progress and completion via c

Gordan Glavaš 9 Nov 5, 2022
Ubergang is a tweening engine for iOS written in Swift.

Ubergang is a tweening engine for iOS written in Swift. Features Tween numeric values, UIColors and CGAffineTransforms Tween along UIBezierPaths Tween

Robin Falko 54 Apr 15, 2022
Designed for gesture-driven animations. Fast, simple, & extensible!

Yet Another Animation Library Designed for gesture-driven animations. Fast, simple, & extensible! It is written in pure swift 3.1 with protocol orient

Luke Zhao 509 Dec 21, 2022
ChainPageCollectionView A custom View with two level chained collection views and fancy transition animation

ChainPageCollectionView A custom View with two level chained collection views and fancy transition animation. Demo Requirements iOS 9.0+ Xcode 8 Insta

Yansong Li 775 Dec 7, 2022
A DSL to make animation easy on iOS with Swift.

This project is highly inspired by JHChainableAnimations, If you project is developed with Objective-C, use JHChainableAnimations instead. With DKChai

Draven 1.9k Dec 9, 2022