Shifty - A teeny tiny tweening engine in JavaScript
Shifty is a tweening engine for JavaScript. It is a lightweight library meant to be encapsulated by higher level tools. At its core, Shifty provides:
- Interpolation of
Number
s over time (tweening) - Playback control of an individual tween
- Extensibility hooks for key points in the tweening process
This is useful because it is the least amount of functionality needed to build customizable animations. Shifty is optimized to run many times a second with minimal processing and memory overhead, which is necessary to achieve smooth animations. The core Shifty library doesn't do:
- Rendering (such as CSS or Canvas)
- Sequencing
- Much else
But don't worry! If you need functionality like this, you can easily extend
the core with whatever you need. In fact, there are some extensions included
in the standard distribution (the dist/
directory) that make Shifty more
useful for common animation needs. Extensions included in the default build
are:
shifty.token.js
: String support. Allows you to interpolate numbers within arbitrarily-formatted strings such as "25px" or "rgb(255, 0, 255)". In other words, this extension allows Shifty to tween CSS properties.shifty.interpolate.js
: Compute the midpoint between a set of values outside of a tween. In other words, compute a single frame of an animation.shifty.bezier.js
: Define custom easing curves based on a cubic Bezier curve. Take a look at cubic-bezier.com for a visual aid.shifty.formulas.js
: A bunch of Robert Penner easing formulas adapted from Scripty2.
Using Shifty
Shifty has no dependencies, so you can just load
shifty.min.js and start using it. This file has all of
the extensions described above baked in. If you only want the core Number
tweening functionality (shifty.core.js), you can easily
build that without any extensions (please see Building
Shifty).
Getting started
This section explains how to get started with Shifty. For full documentation on each method, please see the API documentation.
tweenable()
instance
Making a The first thing you need to do is create a new
instance of Tweenable
:
var tweenable = new Tweenable();
Optionally, you can also define the initial state of the Tweenable
instance
to the constructor via a configuration Object:
var tweenable = new Tweenable({
x: 50,
y: 100,
opacity: 0.5
});
Supplying the initial state to the constructor would obviate the need to supply
a from
value to the tween
method.
tween
Make a basic tween by specifying some options:
- from (Object): Starting position. Required.
- to (Object): Ending position (signature must match
from
). Required. - duration (number): How long to animate for.
- easing (string): Easing formula name to use for tween.
- start (function): Function to execute when the tween begins (after the first tick).
- step (function): Function to execute every tick.
- callback (function): Function to execute upon completion.
var tweenable = new Tweenable();
tweenable.tween({
from: { x: 0, y: 50 },
to: { x: 10, y: -30 },
duration: 1500,
easing: 'easeOutQuad',
start: function () { console.log('Off I go!'); },
finish: function () { console.log('And I\'m done!'); }
});
Important! A reference to the from
object is retained throughout the
life of the tween and is modified by Shifty.
Advanced usage
You can control the state of a tween with the following methods:
Tweenable.prototype.stop();
Tweenable.prototype.pause();
Tweenable.prototype.resume();
You can also examine and modify the state of a Tweenable
:
Tweenable.prototype.get();
Tweenable.prototype.set();
These, as well as all other methods, are detailed more in the API documentation.
Using multiple easing formulas
Shifty supports tweens that have different easing formulas for each property.
Having multiple easing formulas on a single tween can make for some really
interesting animations, because you aren't constrained to moving things in a
straight line. You can make curves! To do this, simply supply easing
as an
Object, rather than a string to tween()
:
var tweenable = new Tweenable(tweenableConfig);
tweenable.tween({
from: {
x: 0,
y: 0
},
to: {
x: 250,
y: 150
},
easing: {
x: 'swingFromTo',
y: 'bounce'
}
});
The Interpolate extension also supports both string and object parameter types
for easing
.
Filters
Filters are used for transforming the properties of a tween at various points
in a Tweenable
instance's life cycle. Filters are meant to convert
non-Number
data types to Number
s so they can be tweened, and then back
again. Just define a filter once, attach it to Tweenable.prototype
, and all
new
instances of Tweenable
will have access to it.
Here's an annotated example of a filter:
Tweenable.prototype.filter.doubler = {
// Gets called when a tween is created.
//
// `currentState` is the current state of the tweened object, `fromState` is
// the state that the tween started at, and `toState` contains the target
// values.
'tweenCreated': function tweenCreated (currentState, fromState, toState) {
Tweenable.each(obj, function (prop) {
// Nothing to do here, just showing that that is a valid filter to hook
// into.
});
},
// Gets called on every update before a tween state is calculated.
'beforeTween': function beforeTween (currentState, fromState, toState) {
Tweenable.each(toState, function (prop) {
// Double each target property right before the tween formula is applied.
obj[prop] *= 2;
});
},
// Gets called on every update after a tween state is calculated.
'afterTween': function afterTween (currentState, fromState, toState) {
Tweenable.each(toState, function (prop) {
// Return the target properties back to their pre-doubled values.
obj[prop] /= 2;
});
}
}
Yes, having doubler
filter is useless. A more practical use of filters is to
add support for more data types. Remember, Shifty only supports Numbers
by default, but you can add support for strings, functions, or whatever else
you might need. For example, the Token extension works by filtering string
values into numbers before each tween step, and then back again after the tween
step.
Building Shifty
Shifty uses nodejs and Grunt for the build system. It also requires a handful of Node modules for the build process. Install the dependencies via npm like so:
$: npm install
Once those are installed, do this at the command line to build the project:
$: grunt build
The the default build
task creates a binary that includes all extensions.
You can also create minimal binaries that only include the bare essentials for
Shifty to run:
$: grunt build-minimal
Note that a minimal build includes no tweening formulas. You can customize and
add build targets in the grunt.js
file. You can also lint the code and run
the unit tests with the default Grunt task:
$: grunt
To generate the documentation:
$: grunt dox
AMD and NodeJS
If an AMD loader (eg. RequireJS,
Curl.js) is present on the page, Shifty
won't generate any globals, so to use it you must list "shifty"
as
a dependency.
define(['shifty'], function(Tweenable){
var tweenable = new Tweenable();
});
Shifty can also be used in NodeJS:
var Tweenable = require('shifty');
Contributors
Take a peek at the Network page to see all of the Shifty contributors, but @millermedeiros in particular deserves recognition for his patches to make Shifty compatible with Node.
Also, special thanks goes to Thomas Fuchs: Shifty's easing formulas and Bezier curve code was adapted from his awesome Scripty2 project.
License
Shifty is distributed under the MIT license. You are encouraged to use and modify the code to suit your needs, as well as redistribute it.