Chris Oliver's Weblog
- All
- F3
- JavaFX
- Programming
- Research
Programming Animations in FX
![]() |
![]() |
My goal is to make it possible for the programmer to specify the required behavior and still be able to actually understand what his code is doing.
Animations are fundamentally updates. They assign values to properties (or invoke processes that do such) at certain time instants.
The traditional animation loop
while (animationIsRunning) {
// update stuff
wait(interval);
}
is easy to understand, but it has several drawbacks:
- It requires a dedicated thread - introducing data synchronization issues
- It doesn't handle jitter - "update stuff" can take variable amounts of time at each iteration, making the animation look choppy.
- Since the time consumed by "update stuff" is included in the loop, the animation will exhibit different behavior based on the speed of the processor.
FX provides a time iterated for loop which (I think) is as easy to understand but overcomes these limitations:
println("before the animation");
for (i in [1..10] dur 10000) {
// update stuff
}
println("after the animation");
The above loop describes a discrete animation which executes every second for 10 seconds. In addition, the loop body is always executed in the current thread. However the loop still blocks until all 10 iterations are complete. Currently, this is implemented with the Event Queue Hack, but proper support for continuations could be provided via code generation by the FX compiler. Since the loop blocks, it can be intuitively incorporated into a larger sequential process, e.g;
Rect {
fill: green
height: 50
width: 50
var x = 0
var y = 0
x: bind x
y: bind y
onMouseClicked: operation(e) {
for (i in [0..100] dur 1000) {
x = i;
}
for (i in [0..100] dur 1000 {
y = i;
}
}
}
The above moves the rectangle from (0, 0) to (100, 0) over 1 second, and then moves it from (100, 0) to (100, 100) over 1 second, when you click the mouse on the rectangle.
Now, sometimes we want animations to run in parallel. For this case, a nearly identical construct is provided, namely the update trigger:
trigger on (i = [1..10] dur 10000) {
// update stuff
}
println("after the trigger, but the animation is still running");
In this case the body of the trigger is executed 10 times, once per second. However, unlike the for loop, the code after the trigger executes in parallel with the trigger's body. The body of the trigger is still executed in the same thread, however, when the timer triggers it:
Rect {
fill: green
height: 50
width: 50
var x = 0
var y = 0
x: bind x
y: bind y
onMouseClicked: operation(e) {
trigger on (i = [0..100] dur 1000) {
x = i;
}
trigger on (i = [0..100] dur 1000) {
y = i;
}
}
}
In this example, the animations of x and y occur in parallel and the the rectangle moves diagonally from (0, 0) to (100, 100) over 1 second.
In the case of discrete animations such as these the "frame rate" for the loop body is duration/(sizeof input-1). For cases where an animation is conceptually continuous, a better approach is often to use a predefined (high) frame rate and interpolate between the values for each frame using some interpolation function. The syntax is open to discussion but here's how that works right now:
Rect {
fill: green
height: 50
width: 50
var x = 0
var y = 0
x: bind x
y: bind y
onMouseClicked: operation(e) {
trigger on (i = [0, 100] dur 1000 motion LINEAR) {
x = i;
}
trigger on (i = [0, 100] dur 1000 motion LINEAR) {
y = i;
}
}
}
LINEAR is a predefined function that performs linear interpolation (you can plug in your own instead). The interpolation function is of the form
function<T> (inputValues:T*, elapsedTimeAsUnitInterval: Number): T
As a shorthand for animating individual properties a form of the the assignment statement is also provided:
x = [0, 100] dur 1000 motion LINEAR; y = [0, 100] dur 1000 motion LINEAR;
which is equivalent to the two triggers above in onMouseClicked().
Finally, for the case where the for loop actually doesn't do anything:
for (i in [0, 1] dur 1000) {
// don't do anything
}
we have a shorthand called "wait"
wait(1000);
Below are a few test cases for these constructs:
-
Video Poker
Standalone FXPad -
Motorola Intro
Standalone FXPad -
Simple Path Animation
FXPad
Posted at 04:03PM Aug 09, 2007 by Christopher Oliver in JavaFX | Comments[11]


Check out this fisheye animation component for Flex:
http://demo.quietlyscheming.com/fisheye/TileExplorer.html
From this blog entry:
http://www.quietlyscheming.com/blog/2006/04/25/new-component-2d-fisheye-v02/
Posted by Ryan de Laplante on August 11, 2007 at 11:37 AM PDT #
At the bottom of this page are links to all kinds of interesting animation components for Flex.
http://www.quietlyscheming.com/blog/
Posted by Ryan de Laplante on August 11, 2007 at 11:45 AM PDT #
Is there a CLDC version available for download somewhere yet? I have been working intermittently on a project for a little while now, which could leverage such a thing to allow users to create their own content for the app.
Posted by Joel Schnall on August 15, 2007 at 03:45 PM PDT #
This all looks great! I really would like to learn this, though I have no idea were to start. I have no programing skills, but I really want to learn this! Can anybody give me any pointers were to start or simple tutorials to get me up and running? Thank you.
Posted by Chris Phillips on August 18, 2007 at 02:48 PM PDT #
Nice Article
Posted by sohbetkanallari on August 25, 2008 at 06:55 AM PDT #
<a href="http://www.yapitec.com" title="Dübel - Hırdavat - El Aletleri" target="_blank">Dübel - Hırdavat - El Aletleri</a>
Posted by dübel on December 31, 2008 at 05:28 AM PST #
http://geciktirici.seksmarketim.biz
Posted by Geciktirici on December 31, 2008 at 05:31 AM PST #
NOTE: It seams like that such feature is not present in the final JavaFX release 1.0
Posted by Mike on January 20, 2009 at 11:27 AM PST #
http://www.smsmatbaa.com
Posted by matbaa on June 22, 2009 at 10:04 AM PDT #
thank you
http://www.tavlaoynasana.com
Posted by Tavla Oyna on July 02, 2009 at 06:54 PM PDT #
nice article
thank you
http://www.erozyon.info
Posted by Erozyon on July 02, 2009 at 06:54 PM PDT #