Giter VIP home page Giter VIP logo

keyframes.js's Introduction

keyframes.js

A functional animation library

Demo/Playground/Tutorial

[TL;DR](https://github.com/alexeisavca/keyframes.js# book-iii-enlighment)

Book I: Motivation

Once upon a time there was a programmer, he discovered the ways of Tao at an early age, and he's been following them ever since, knowing that he'll never achieve perfection, for only the Tao of Programming is perfect, but also knowing that the road itself is the reward. And often that programmer needed an animation library, but alas, every one of them was filled with heresy and filth, bad practice and monkey code leaking from every LoC. And so one time the programmer could not take it anymore, in dispair, he cried:

"Oh, the great Tao of programming! Indeed all things are possible within you, for you are perfection itself, indeed all the patterns exist within you, for patterns are your sacred body, indeed all the good practices flow within you, for good practices are your holy blood, indeed all readability and reusability comes from you, for readability and reusablity are your divine breath! But tell me, oh, Magnificient Tao, why have you forsaken the writers of animation libraries, why do they all suck? It is for our sins! Without doubt it is because our defiance to write tests and comments and document our code that you send us such punishment!"

And thus answered the Tao of programming:

"Do not despair, my child, for I have chosen you to write an animation library that will be the essence of my divine will!"

Humbled, the programmer fell unto his knees, and rasing his hands toward the bright light that was the Tao, he plead:

"Oh, merciful Tao! I am not worthy of such task! Surely I do not deserve to be the tool of your sacred plan!"

And so the Tao spoke:

"My child, you've been up all night, your body is tired from sleep deprivation, you're eyes are red from reading too much bad code, and your mind is taunted from playing too much StarCraft! Go now, light the holy fire, and put a kettle upon it, and from that kettle you shall pour yourself a very strong coffee, the drink of the gods! Let the sacred fluid of coffee flow inside you, and you shall see!"

And thus he saw, drinking the divine ambrosia and staring into city lights, he saw!

Book II: Introduction

In the beginning there was T, and there was S. And T was time, and S was state, and T was a set of real numbers from 0 to 1, 0 being the beginning of all things, and 1 the end of them. And S was the set of the possible CSS styles, all the combinations of CSS, CSS3 and even vendor specific properties existed within S. And from the fusion of T and S, there was a function of T upon S, f: T -> S.

"Behold!" a voice said, "For that function is the animation in its purest form!"

"But how can there be an animation with nothing to animate? And what use is the animation if it lasts an eternity?" doubted the programmer.

"Oh you of little faith! Shall you question me next what use is the Pythagorean theorem without a triangle to measure? Or the associative law without taxes to pay? Truly, those who cannot see beyond particularities walk the path of antipatterns, they shall never comprehend the Tao! But those who see beyond the lines of code, beyond the current project, those who see the universal abstraction, they walk the path of the righteous, and they shall achieve enlightment! For truly, as long as the faithful understands the abstraction, he shall find plenty of opportunities to implement it, but the sinner, he who is blind to the mathematical model, even after implementing MAX_INT isolated cases of it, shall not see the diamond beneath the facets!"

The programmer stood silent in awe, as the voice spoke thus:

"Behold! Let

function rotate(t){
  var grades = 360 * t;
  return `transform: rotateX(${grades})`
}

Let d = 24!
Let h equal the current hour!
And there, by requestAnimationFraming

rotate(h/d);

I have just made the Earth spin!"

And the Earth span, and there was Day and there was Night, and by the end of the Night the programmer was enlightened.

Book III: Enlighment

"Behold! For this is the code of the righteous!"

npm install keyframes.js
import * as K from "keyframes.js"
var fadeOut = K.property('opacity', 1, 0);
var blink = K.toAndFrom(fadeOut);
var blink4times = K.repeat(4, blink);
var blink4timesEased = K.easings.easeInOutExpo(blink4times);
K.stream(1000, blink4timesEased, K.intoDom(document.getElementById('the-thing')));

Here and below animation means a function of T over S, f: T->S, where T is a set of real numbers from 0 to 1, inclusive, and S is a set of flat(1 level) objects. Any function that takes a real number n, 0 <= n <= 1 and returns a flat object is a valid animation that can be used with this library. By convention, any function that returns an animation will be called generator, for example

function fadeTo(opacity){
  return function(t){
    return {
      opacity: opacity * t
    }
  }
}

is a generator.

Book IV: The API of the righteous

"Use these tools, understand and accept them, as it is promised, he who does so will surely achieve enlightment!"

tween(Object from, Object to)

Returns an animation that connects the from and to states

var fadeOut = tween({
  opacity: 1
}, {
  opacity: 0
});

fadeOut(.25);//{opacity: .75}
fadeOut(.5);//{opacity: .5}
fadeOut(.75);//{opacity: .25}

This function is smart enough to extract and interpolate numbers from strings, so this will work as you'd expect it:

var muchPropertiesWow = tween({
  width: '1px',
  transform: 'rotateY(-90deg)'
}, {
  width: '100px',
  transform: 'rotateY(0deg)'
})

However, be sure to use the same units in both to and from state. Even if a value is 0, still use units, i.e 0px, 0deg etc.

transition(String propertyName, initialValue, finalValue)

Connects two states of a single property. The example above could be written as:

var fadeOut = transition('opacity', 1, 0)

ensure(Object state)

Creates and animation that for any 0<t<1 returns the state passed as argument

ensureProperty(String property, value)

Same as ensure({property: value})

reverse(animation)

Returns an animation that is the reverse of the argument. Using the var fadeOut from above:

var fadeIn = reverse(fadeOut)

is the same as:

var fadeIn = property('opacity', 0, 1);

or

var fadeIn = tween({opacity: 0, opacity: 1})

chain({t1: animation1, t2: animation2})

Creates a single animation from several subanimations that will be executed consecutively. Requires an object with float keys that indicate at what time(relative to the parent animation) the animation passed as value should run:

var fadeOut = transition('opacity', 1, 0)
var fadeIn = reverse(fadeOut);
var blink = chain({
  0: fadeOut,
  .5: fadeIn
})

chainEvenly(animation1, animation2, animation3...)

Will chain all the animations passed as arguments, each one receiving a 1/nrArguments in parents' timeline

merge(animation1, animation2, animation3...)

Merges animations, i.e. "executes" them in parallel.

merge(property('width', '1px', '100px'), property('height', '1px', '100'))

would be the same as

tween({
  width: '1px',
  height: '1px'
}, {
  width: '100px',
  height: '100px'
})

linger(t, animation)

Will return a new animation, in which the second argument will run until t, after that, its last state will be persisted till the end of the resulting animation.

linger(.3, transition('transform', 'rotateZ(0deg)', 'rotateZ(90deg)'))

is same as

chain({
  0: transition('transform', 'rotateZ(0deg)', 'rotateZ(90deg)'),
  .3: ensureProperty('transform', 'rotateZ(90deg)')
})

foreshadow(t, animation)

The counterpart of linger. Will staticly persist the animation's first frame until t, then will play the animation until the end

imposePresence(from, to, animation)

A marriage of foreshadow and linger, will persist the animation's first frame until from, will animate the animation from from to to and will persist its last frame from to till the end. Keep in mind it is not the same as

foreshadow(from, linger(to, animation)

toAndFrom(animation)

Will chain the animation with its reverse, the first animation will end and the second will start at .5. The example above could be written as

var blink = toAndFrom(transition('opacity', 1, 0));

repeat(times, animation)

Will chain the animation with itself times times, t will be distributed evenly between all the subanimations, each one will consume 1/times of parent t.

prerender(ms, animation)

Will map the animation as to run during ms milliseconds(60 fps) and cache the result, will return a function that will return the result from that cache. ###stream(ms, animation, cb, onEnd) Will execute the animation in real time(using requestAnimationFrame) during ms milliseconds, will call cb each frame with the current state as argument. Will call onEnd when the animation ends.

stream(1000, transition('opacity', 1, 0.5), state => console.log(state))//{opacity: 0.1}, {opacity: 0.2}, opacity{0.3}...

infiniteStream(ms, animation, cb)

Same as stream, but will run the animation infinitely in loops of ms milliseconds and will return a function that, when called, will stop the animation.

var stopSpinning = infiniteStream(1000, rotate, intoDom(spinner)); //will spin until stopSpinning() is called

intoDom(DOMElement)

Returns a function that takes a state as an argument an applies it to the DOMElement. Use with stream:

stream(1000, animations, intoDom(document.getElementById('the-target')))

toCss(animationName, frames, animation)

Generates CSS @keyframes with the specified name and number of keyframes and returns the string

Easings

import {easings} from "keyframes.js"

or

import * as easings from "keyframes.js/easings"

ease(easingFunction, animation)

Will return an animation eased by easingFunction. Easing function takes the standard easings arguments:

function(currentTime, totalTime, progressRatio, valueSoFar, change)

Use bind to make your function reusable:

var myAwesomeEasing = ease.bind(null, function(currentTime, totalTime, progressRatio, valueSoFar, change){
//...
});
var easedAnimation = myAwesomeEasing(animation)

Preset easing functions

The standard Robert Penner's easing formulas are available, use them like this:

easeInQuad(animation)

List of preset easing functions

  • linear
  • easeInQuad
  • easeOutQuad
  • easeInOutQuad
  • easeInCubic
  • easeOutCubic
  • easeInOutCubic
  • easeInQuart
  • easeOutQuart
  • easeInOutQuart
  • easeInQuint
  • easeOutQuint
  • easeInOutQuint
  • easeInSine
  • easeOutSine
  • easeInOutSine
  • easeInExpo
  • easeOutExpo
  • easeInOutExpo
  • easeInCirc
  • easeOutCirc
  • easeInOutCirc
  • Roll your own! Add your easing function to keyframes.js/easings and then create a pull request.

Implementations:

  • React/Flux
  • Roll your own! Write a function that can be used as a callback for stream and works with your favourite framework/library, and then submit a pull request. Or write a plugin and link it here in README

Please read

Please read
If you think this software is worth a buck or two, I'd be gald to have it.
Please support the caffeine addiction of your humble servant by donating to my PayPal [email protected]

keyframes.js's People

Contributors

alexeisavca avatar

Stargazers

 avatar YG avatar Matthieu van den Bosch avatar Darren avatar Dave Lage avatar  avatar darlan dieterich avatar Leo Chioveanu avatar Joel Benjamin  avatar  avatar txiejun avatar Nhu H Trinh avatar David Granström avatar Hans Höglund avatar Matt avatar Jeremy Kahn avatar phil avatar Rabbit avatar Javier Chávarri avatar  avatar Jeong Seong Dae avatar Theun Kohlbeck avatar  avatar Larion Garaczi avatar Ozan Falan avatar Michael Anthony avatar  avatar timelyportfolio avatar John avatar Fernando Bueno avatar czc avatar Edan Schwartz avatar Samuel Schmidt avatar Piyush Chauhan avatar Kav Singh avatar Jesper Thøgersen avatar Denis Stoyanov avatar Rafau avatar Vincent Simard avatar Horace Ho avatar seunggi avatar

Watchers

Richard Hess avatar timelyportfolio avatar James Cloos avatar Denis Stoyanov avatar Michael Anthony avatar  avatar

keyframes.js's Issues

Installtion issue

Hi
Your library is clearly a brilliant idea and it's exactly what I was looking for but , i tried many times to install the repository but nothing works : the npm command does'nt seem to trigger any installation ... Any idea for what i m doing wrong ?

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.