Coder Social home page Coder Social logo

mmick66 / kinieta Goto Github PK

View Code? Open in Web Editor NEW
46.0 2.0 5.0 1.13 MB

A Fast Animation Engine with an Intuitive API

License: Apache License 2.0

Swift 97.97% Ruby 2.03%
animation-engine animation-library animations swift4 ios-swift ios graphics-library graphics-engine tweening tween

kinieta's Introduction

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") }

kinieta's People

Contributors

mmick66 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

kinieta's Issues

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

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.