jDirector is a simple and extensible framework for animation and timing written in JavaScript, providing a jQuery-like interface.
An experimental library on functional programming and simulating coroutine.
Download jDirector.js and include it in the html.
<script src="jDirector.js"></script>
Hello World:
var d = new jD.Director();
d.wait(1000).log("Hello World!");
Then "Hello World" will appear after 1s.
Yet another Hello World, which behaves the same:
var d = new jD.Director();
d.wait(1000).instant(function () { console.log("Hello World!"); });
Only chrome is tested now.
Director commands can be called in chains. Later commands will be executed after earlier ones.
NOTE: d
is an instance of a jD.Director
in following code.
d.wait(1000).log("something");
log
will be delayed 1s.
We can call any command multiple times.
d.wait(1000).wait(1000).log('Hello').wait(3000).log('Bye');
"Hello" will appear after 2s and "Bye" will appear 3s after "Hello" appears.
The following code execute two chains parallelly.
d.wait(1000).log('Hi').wait(2000).log('Bye');
d.wait(2000).log('Hello, ').wait(1000).log('World.');
If you want to execute them serially, you should:
var r = d.wait(1000).log('Hi').wait(2000).log('Bye');
r.wait(2000).log('Hello, ').wait(1000).log('World.');
If you want to run a command after all parallel commands are over, you should use after
:
var r = d.wait(1000);
r.after(
r.log('branch 1 start').wait(1000).log('branch 1 end'),
r.log('branch 2 start').wait(2000).log('branch 2 end')
).log('all branches over');
Command after(b1, b2, b..., [sel])
can join branches together. The optional parameter sel
is an integer, specifying when subsequent commands will be executed. If it is not specified, subsequent commands will start after all branches over.
If sel
is a nonnegative integer, subsequent commands are executed after the sel + 1
shorter branch is over.
If sel
is a negative integer, subsequent commands are executed after the -sel
longer branch is over.
You can use invoke
command to chain them together:
var d = new jD.Director();
d.wait(1000).invoke(function () {
return this.after(
this.log('branch 1 start').wait(1000).log('branch 1 end'),
this.log('branch 2 start').wait(2000).log('branch 2 end')
);
}).log('all branches over');
instant(callback)
will call the callback in the timing flow.
d.wait(1000)
.instant(function () {
console.log("Hello");
})
.wait(1000)
.instant(function (str) {
console.log(str);
}, ["Bye"]);
constant(callback, [length], [interval])
will call the callback every interval
milliseconds for length
milliseconds.
If length is not specified or is null, the animation will not stop until the callback returns false or null (strict!).
The default value of interval
is 20.
The callback will be called with a parameter, which represents the time elapsed from the start in milliseconds.
Subsequent commands will be execute after the animation.
d.constant(function(t) {
var c = t / 10;
document.body.style.background = 'rgb(' + c + ',' + c + ',' + c + ')';
return c <= 255; // while c <= 255
}, null, 20)
.log("Animation end.");
jDirector provides extend(commandTable)
to add commands to it.
Example:
var d = new jD.Director();
d.extend({
logStart : function () {
console.log("start");
return this;
},
fadeToBlack : function (speed) {
var t = 255;
return this.constant(function () {
document.body.style.background = 'rgb(' + t + ',' + t + ',' + t + ')';
t -= speed;
return t >= 0;
});
}
});
d.wait(1000).logStart().fadeToBlack(5).log("over");
extend
may throw an error due to a name conflict.
The body of the command should return a Future
object, which can be created by makeFuture
or the helper function justNow
.
- Return
this.justNow()
: Indicating an instant command, whose behavior should finish immediately after invocation, such as hiding, changing texts. Invocations next to it will be called immediatly. - Return
this.makeFuture()
: Indicating a constant command, whose behavior will last a period of time, such as fading, moving around. Invocations next to it will be called after it has finished (after the future object is calledrealize
.
With extend
, we can write plugins for jDirector.
Example:
function MyDirector() {}
var proto = new jD.Director();
proto.extend({
logOK : function () {
return this.log("OK");
}
});
MyDirector.prototype = proto;
new MyDirector().wait(1000).logOK();
Future
is the return value of many commands of jD.Director
, such as wait
and constant
. It has commands of the same names. However, the execution of them will be delayed. So it is the "future".
Create a future for director
.
Make all delayed commands of the Future
object to be executed immediately.
Make it realize after future
realizes.
The callback will be called when the future realizes. The calling code: callback.call(future, director)
.
Use Future
:
d.extend({
delay1s : function () {
var future = this.makeFuture();
setTimeout(future.realize, 1000);
return future;
}
});
- Docs
- How to make your command cancelable
- Advance and dangerous features may be put into jDirectorEx
- All commands cancelable
- Flow Figure Generation
- Plugins:
- jTween