The problem
Jquery has powerful animation functions, but the animation calls are tied too closely to the queried objects. If we make an animation, we can't reuse it on new queries. Nor can we manipulate or compose those animations to form new animations. This makes building a large complex animation a hassle.
Domain Analysis
The goal is to write composable animation functions, which themselves can be used to create bigger more complex functions. Essentially, we separate the animation from the query, and make the animation a building block that can be reused.
Today these kinds of animations are written by chaining many calls to jQuery's animate. Others use pure Javascript and animate via timers and events. Other tools include dedicated animation software, like Flash or various Javascript plugins.
Language Constructs
Our programs are made from first class functions, closures, and objects. The AnimObjects are javascript objects containing the parameters that specify the animation's behavior. First class functions allow us to pass methods around and chain our animations together, allowing us to build more complex program.
The semantics of our program follow regular javascript function calls to create the animation sequences, and regular jQuery calls to execute them.
example code for an animation
anim0 = createAnim({left:”+=200px”}, {top:”+=200px”});
$('div').execAnim(anim0);
Demo
anim1 = createAnim("moveRight", {opacity:0.5});
$("#one").execAnim(anim1);
anim2 = createAnim({top:"+=150px"},{width:"+=50px", height:"+=50px"})
$("#two").execAnim(anim2);
anim3 = combineAnim(anim1, anim2);
$("#three").execAnim(anim3);
anim4 = squashAnim(createAnim(anim3, {top:"-=200px"}));
$("#four").execAnimLoop(anim4, 2);
Implementation
The implementation is an internal domain language written with javascript and jQuery's method for writing plugins. We abstract animation sequences into an array of objects, and create operator functions that can manipulate these sequences. Any animation sequence can be pieced together or merged, making the animations composable and reuseable. Underneath, this is done with clever array traversal, hash manipulation, and regexes.
We then create executor functions that can perform/carry out the animation sequence. And they do this by making use of jQuery's animate function.
Finally, our “expressability” feature is done by having a hash, store string to animObjects. The animObjects are valid animation sequences that can be carried out.
What you are proud of
We're most proud of the combine function. It allows us to merge and splice two different animation sequences together and form a new animation sequence that can have a totally different behavior.
Mistakes
One of our goals was “Expressability.” The idea was that instead of individually stating which parameter you wanted tweaked to form the animation, you could simply pass a string, like “moveRight” into createAnimation, and it would smartly know what to do. Unfortunately it gets hard to predict what a user would try to say, and you lose too much expressive power that it is an almost useless feature.
What we would do differently
Given more time, we would have liked to explore and implement richer and more powerful animation effects such as rotate, distort, and possibly even 3D.
Saturday, December 19, 2009
Friday, December 18, 2009
The Final Write Up
This is the final write up.
Project Overview:
The domain of this project is animation in web pages. Specifically with regard to jQuery. The problem with jQuery animation is that the animation function is closely tied to the dom elements that you query. This prevents animations from being reused or composed - making more complex animations difficult.
Our project - essentially an internal domain language built on top of jQuery and javascript - separates the animation calls from the dom elements and abstracts them into anim Objects. These animObjects are composable, and can be reused in newer animations. The idea is that web animators would be able to use our plugin to have more flexibility and power when working on larger more complex animations.
Example Demonstration of our Code:
Here, we have an example program written in jQuery. Assume #one, #two, #three, #four, and #five refer to divs already created and existing in the html code. For one reason or another, we want to have #one move right and then left, #two move down and then up, and then #three and #four move right, left, down, and then up. #five does the animation done by #three and #four but twice. Here is how it would look like in jQuery, using jQuery's animate function.
jQuery Animation Code
$('#one').animate({top:"+=200px"}).animate({top:"-=200px"});
$('#two').animate({left:"+=200px"}).animate({left:"-=200px"});
$('#three').animate({top:"+=200px"}).animate({top:"-=200px"})animate({left:"+=200px"}).animate({left:"-=200px"});
$('#four').animate({top:"+=200px"}).animate({top:"-=200px"})animate({left:"+=200px"}).animate({left:"-=200px"});
$('#five')animate({top:"+=200px"}).animate({top:"-=200px"})animate({left:"+=200px"}).animate({left:"-=200px"})animate({top:"+=200px"}).animate({top:"-=200px"})animate({left:"+=200px"}).animate({left:"-=200px"});
Two things stand out about jQuery's coding syntax for animations. For one, the dom element selected and the animation to use are closely tied together. The consequence is that although #three and #four both use the same animation, they need to spell it out both times. Furthermore, #five acts out the animation performed by #three and #four but twice. This means it needs to call animate 8 times. So this gets quite messy. And when animations get longer and more complex, can quickly become unmanageable. It would be much better if we could reuse the animations that we've created.
And thus enters the inspiration for our project. Here we have code that does the same thing as the code above.
Our Code
moveDU = createAnim({top:"+=200px"}, {top:"-=200px"});
moveRL = createAnim({left:"+=200px"}, {left:"-=200px"});
moveAround = createAnim(moveDownUp, moveRightLeft);
$('#one').execAnim(moveDU);
$('#two').execAnim(moveRL);
$('#three').execAnim(moveAround);
$('#four').execAnim(moveAround);
$('#five').execAnim(moveAround, moveAround);
Composability and Reuseability
Here, we created two animation sequences and stored them in containers. We then create a new animation sequence from the first two that we've created. Now we can proceed to use them on the divs. The animation sequences that we create can then be reused over and over on new dom elements. The animation sequences that we create are composable and can become the building blocks in newer animations.
Furthermore, we have created new operator methods that could act on animation sequences to give the user even more expressive power. For example:
moveDiagonal = combineAnim(moveDU, moveRL);
This animation sequence is created by combining our previous two animations and merging/splicing them together. The resulting animation moves right and down at the same time, resulting in a new behavior.
Expressabiliy. As we were creating our language, we thought, wouldn't it be neat if instead of constantly having to specify the CSS params to tweak each attribute when we animate, we could just tell it to move with a word? With that in mind, we decided to to implement expressability.
$('#one').createAnim("moveRight", "moveDown")
The idea behind expressability is that you just pass strings to createAnim, based on how you want the dom element to act, and createAnim would smartly translate the string into an executable animObject. This idea was unfortunately not explored further because it hampered expressability and due to the difficulty of predicting what a user would want to type.
The Three Demos
Demo 1
Since our plugin is focused on animation, demo 1 is about what kinds of operations our plugin will allow. We will perform simple animations on div squares. At each step, we animate the next square. And each square animation, as we will see, is really the result of previous animations composed, combined, or squash together. We show a short demonstration of each of the animation operator functions.
composeAnim() - takes animObjs, animArrays, or "strings" - returns one animArray
squashAnim() - takes an animArray, and compacts it all into one animObj. the animObj has the keys of all the animObjs in animArray as well as their values smartly combined.
combineAnim() - takes multiple animArrays, and merges animObjs of the same index together
These do all the dirty work of appending, mixing, and merging the animation arrays together. Finally, we have the three key execution functions.
execAnim() - takes arbitrary number of animArrays
execAnimLoop() - takes on animArray and a number of how many times to repeat it
execAnimCall() - takes an animArray and a function. Upon finishing, it calls the function
Demo 2
Demo 2 shows you the general pipeline of how someone who was using our plugin would probably create a complex animation. After the divs, each containing a .png image, are arranged on the html, we animate them.
However, the way we animate them isn't done by multiple tedious calls to animate. Instead we create a few animation sequences, and those sequences are used and reused to make new animation sequences. What started as a short animation in the end, becomes an animation sequence up to 4 anim objects long (longer ones are possible, but this is a demo). We use our execAnimLoop function to call that 4x as well. If this were done with just animate, the animate chain would be 16 calls long. Finally, we use some timers and some looping to achieve a nice looping animation.
Demo 3
This demonstration shows the usage of execAnimLoop and execAnimCall in an html page. It also shows the usage of createimg function that is included in the jQuery plugin that dynamically creates img elements in the scene so that we do not need hard code the images in the body of the html page. createimg function call will take in attributes of that image being defined and will use inline css to change the attributes. As for execAnimLoop, its purpose was stated in the first demonstration, is that it takes an animArray and a number of how many times to repeat it. The purpose of this function call is to create a continuous sequence of animations for an object.As for the other function, execAnimCall, it is best to understand the input that this function takes before knowing what it does. Since it takes an animArray and a function (which is a drawback call that calls the function after evaluating that animArray), it is able to interrupt the flow of movement of an object in a scene. The demonstration shows mario as he moves towards the blocks and suddenly reappears as a different type of mario character with a cape. This was made possible by the execAnimLoop that let mario continuously change his position to the right, and execAnimCall which made possible the changing of mario's img source and changing his movement to move left. Basically, the function of these two functions is move and change movement respectively.
This demonstration also shows the usage of javascripts timer functions: setInterval and clearInterval. setInterval's function is to allow a function call continuously without interruption. This function takes in a function and an integer n representing time in milliseconds. setInterval calls the function every n milliseconds. This function returns a variable id and with this id one is able to interrupt the function and halt it. This continuous interruption of calls will continue until it is disabled by the call to clearInterval. The usage of these two functions created the possibility of having two objects in the scene move continuously in parallel. If one wants an object move continuously without being interrupted, never call clearInterval on the variable id that setInterval returns, after executing a function after n milliseconds.
Studying a Language that Solves a Similar Problem:
In studying a language that solves a similar problem, we take a look at how the class for JavaScript class Animator.js animates objects, a brief description of it is as follows.
In the class Animator.js animations are implemented using composition in which the programmer employs several classes that interact with each other to provide complex behaviour. Furthermore, parameterisation classes accept arguments that alter their behaviour" instead of recurring to the usual inheritance.
We want to achieve a similar effect in jQuery by using this syntactic sugar:
$("#div").execAnimLoop([{left: "-=25px"}], 5);
$("#div").execAnimCall([{left: "-=25px"}, {left:; "+=10px"}],function() {
...
//body of drawback function call
...
);
We used execAnimLoop repeats executes the same animation the given number of times.
On the other hand, execAnimCall can be used to interrupt the movement of an object
by using a drawbackCall function whenever the given animation has ended. e.g. {left:; "+=10px"}
This interrupt is important because if we want to change the direction of an object in the
scene we would have to change the animation given into execAnimLoop.
An example of Animator.js solution to our problem is this:
Suppose we want to create an animator prototype in Animator.js the code would work as follows:
// This object controls the progress of the animation
ex1 = new Animator()
// the Animator's subjects define its behaviour
ex1.addSubject(updateButton);
function updateButton(value) {
$('ex1Button').innerHTML = "Progress: " + Math.round(value * 100) + "%";
}
The language basically creates an object that control animations. Once the control xis created a method is called (addSubject) with an object parameter. This parameter is a div that can be modified.
One limitation of the language is that since it is written in JavaScript there is no rotation. Aside from that limitation there is no other limitations except for 3D animations which are really difficult to do.
Implementation
For our implementation in jQuery, we implement animation effectively by translating jQuery's animate function calls. In order to separate the query from the animate call, we abstract away the argument that jQuery's animate would normally take into objects, which we call animObjects. We abstract away the call to the jQuery's animate function by wrapping it inside "execAnim" functions, which can operate on arrays of animObjects. Then by making various operators for merging and concatenating different animArrays, we effectively achieve animative composability. animObjs could be saved, reused, and spliced smartly together, and execAnim would be able to carry out the animation.
Project Overview:
The domain of this project is animation in web pages. Specifically with regard to jQuery. The problem with jQuery animation is that the animation function is closely tied to the dom elements that you query. This prevents animations from being reused or composed - making more complex animations difficult.
Our project - essentially an internal domain language built on top of jQuery and javascript - separates the animation calls from the dom elements and abstracts them into anim Objects. These animObjects are composable, and can be reused in newer animations. The idea is that web animators would be able to use our plugin to have more flexibility and power when working on larger more complex animations.
Example Demonstration of our Code:
Here, we have an example program written in jQuery. Assume #one, #two, #three, #four, and #five refer to divs already created and existing in the html code. For one reason or another, we want to have #one move right and then left, #two move down and then up, and then #three and #four move right, left, down, and then up. #five does the animation done by #three and #four but twice. Here is how it would look like in jQuery, using jQuery's animate function.
jQuery Animation Code
$('#one').animate({top:"+=200px"}).animate({top:"-=200px"});
$('#two').animate({left:"+=200px"}).animate({left:"-=200px"});
$('#three').animate({top:"+=200px"}).animate({top:"-=200px"})animate({left:"+=200px"}).animate({left:"-=200px"});
$('#four').animate({top:"+=200px"}).animate({top:"-=200px"})animate({left:"+=200px"}).animate({left:"-=200px"});
$('#five')animate({top:"+=200px"}).animate({top:"-=200px"})animate({left:"+=200px"}).animate({left:"-=200px"})animate({top:"+=200px"}).animate({top:"-=200px"})animate({left:"+=200px"}).animate({left:"-=200px"});
Two things stand out about jQuery's coding syntax for animations. For one, the dom element selected and the animation to use are closely tied together. The consequence is that although #three and #four both use the same animation, they need to spell it out both times. Furthermore, #five acts out the animation performed by #three and #four but twice. This means it needs to call animate 8 times. So this gets quite messy. And when animations get longer and more complex, can quickly become unmanageable. It would be much better if we could reuse the animations that we've created.
And thus enters the inspiration for our project. Here we have code that does the same thing as the code above.
Our Code
moveDU = createAnim({top:"+=200px"}, {top:"-=200px"});
moveRL = createAnim({left:"+=200px"}, {left:"-=200px"});
moveAround = createAnim(moveDownUp, moveRightLeft);
$('#one').execAnim(moveDU);
$('#two').execAnim(moveRL);
$('#three').execAnim(moveAround);
$('#four').execAnim(moveAround);
$('#five').execAnim(moveAround, moveAround);
Composability and Reuseability
Here, we created two animation sequences and stored them in containers. We then create a new animation sequence from the first two that we've created. Now we can proceed to use them on the divs. The animation sequences that we create can then be reused over and over on new dom elements. The animation sequences that we create are composable and can become the building blocks in newer animations.
Furthermore, we have created new operator methods that could act on animation sequences to give the user even more expressive power. For example:
moveDiagonal = combineAnim(moveDU, moveRL);
This animation sequence is created by combining our previous two animations and merging/splicing them together. The resulting animation moves right and down at the same time, resulting in a new behavior.
Expressabiliy. As we were creating our language, we thought, wouldn't it be neat if instead of constantly having to specify the CSS params to tweak each attribute when we animate, we could just tell it to move with a word? With that in mind, we decided to to implement expressability.
$('#one').createAnim("moveRight", "moveDown")
The idea behind expressability is that you just pass strings to createAnim, based on how you want the dom element to act, and createAnim would smartly translate the string into an executable animObject. This idea was unfortunately not explored further because it hampered expressability and due to the difficulty of predicting what a user would want to type.
The Three Demos
Demo 1
Since our plugin is focused on animation, demo 1 is about what kinds of operations our plugin will allow. We will perform simple animations on div squares. At each step, we animate the next square. And each square animation, as we will see, is really the result of previous animations composed, combined, or squash together. We show a short demonstration of each of the animation operator functions.
composeAnim() - takes animObjs, animArrays, or "strings" - returns one animArray
squashAnim() - takes an animArray, and compacts it all into one animObj. the animObj has the keys of all the animObjs in animArray as well as their values smartly combined.
combineAnim() - takes multiple animArrays, and merges animObjs of the same index together
These do all the dirty work of appending, mixing, and merging the animation arrays together. Finally, we have the three key execution functions.
execAnim() - takes arbitrary number of animArrays
execAnimLoop() - takes on animArray and a number of how many times to repeat it
execAnimCall() - takes an animArray and a function. Upon finishing, it calls the function
Demo 2
Demo 2 shows you the general pipeline of how someone who was using our plugin would probably create a complex animation. After the divs, each containing a .png image, are arranged on the html, we animate them.
However, the way we animate them isn't done by multiple tedious calls to animate. Instead we create a few animation sequences, and those sequences are used and reused to make new animation sequences. What started as a short animation in the end, becomes an animation sequence up to 4 anim objects long (longer ones are possible, but this is a demo). We use our execAnimLoop function to call that 4x as well. If this were done with just animate, the animate chain would be 16 calls long. Finally, we use some timers and some looping to achieve a nice looping animation.
Demo 3
This demonstration shows the usage of execAnimLoop and execAnimCall in an html page. It also shows the usage of createimg function that is included in the jQuery plugin that dynamically creates img elements in the scene so that we do not need hard code the images in the body of the html page. createimg function call will take in attributes of that image being defined and will use inline css to change the attributes. As for execAnimLoop, its purpose was stated in the first demonstration, is that it takes an animArray and a number of how many times to repeat it. The purpose of this function call is to create a continuous sequence of animations for an object.As for the other function, execAnimCall, it is best to understand the input that this function takes before knowing what it does. Since it takes an animArray and a function (which is a drawback call that calls the function after evaluating that animArray), it is able to interrupt the flow of movement of an object in a scene. The demonstration shows mario as he moves towards the blocks and suddenly reappears as a different type of mario character with a cape. This was made possible by the execAnimLoop that let mario continuously change his position to the right, and execAnimCall which made possible the changing of mario's img source and changing his movement to move left. Basically, the function of these two functions is move and change movement respectively.
This demonstration also shows the usage of javascripts timer functions: setInterval and clearInterval. setInterval's function is to allow a function call continuously without interruption. This function takes in a function and an integer n representing time in milliseconds. setInterval calls the function every n milliseconds. This function returns a variable id and with this id one is able to interrupt the function and halt it. This continuous interruption of calls will continue until it is disabled by the call to clearInterval. The usage of these two functions created the possibility of having two objects in the scene move continuously in parallel. If one wants an object move continuously without being interrupted, never call clearInterval on the variable id that setInterval returns, after executing a function after n milliseconds.
Studying a Language that Solves a Similar Problem:
In studying a language that solves a similar problem, we take a look at how the class for JavaScript class Animator.js animates objects, a brief description of it is as follows.
In the class Animator.js animations are implemented using composition in which the programmer employs several classes that interact with each other to provide complex behaviour. Furthermore, parameterisation classes accept arguments that alter their behaviour" instead of recurring to the usual inheritance.
We want to achieve a similar effect in jQuery by using this syntactic sugar:
$("#div").execAnimLoop([{left: "-=25px"}], 5);
$("#div").execAnimCall([{left: "-=25px"}, {left:; "+=10px"}],function() {
...
//body of drawback function call
...
);
We used execAnimLoop repeats executes the same animation the given number of times.
On the other hand, execAnimCall can be used to interrupt the movement of an object
by using a drawbackCall function whenever the given animation has ended. e.g. {left:; "+=10px"}
This interrupt is important because if we want to change the direction of an object in the
scene we would have to change the animation given into execAnimLoop.
An example of Animator.js solution to our problem is this:
Suppose we want to create an animator prototype in Animator.js the code would work as follows:
// This object controls the progress of the animation
ex1 = new Animator()
// the Animator's subjects define its behaviour
ex1.addSubject(updateButton);
function updateButton(value) {
$('ex1Button').innerHTML = "Progress: " + Math.round(value * 100) + "%";
}
The language basically creates an object that control animations. Once the control xis created a method is called (addSubject) with an object parameter. This parameter is a div that can be modified.
One limitation of the language is that since it is written in JavaScript there is no rotation. Aside from that limitation there is no other limitations except for 3D animations which are really difficult to do.
Implementation
For our implementation in jQuery, we implement animation effectively by translating jQuery's animate function calls. In order to separate the query from the animate call, we abstract away the argument that jQuery's animate would normally take into objects, which we call animObjects. We abstract away the call to the jQuery's animate function by wrapping it inside "execAnim" functions, which can operate on arrays of animObjects. Then by making various operators for merging and concatenating different animArrays, we effectively achieve animative composability. animObjs could be saved, reused, and spliced smartly together, and execAnim would be able to carry out the animation.
Friday, December 11, 2009
Demo at the Upcoming Poster Session
After some feedback from our professor, we realized that most likely we won't trying to create 3D animations since it would be overly ambitious given our time frame. We will, however, focus on making a nice elegant solution to 2D animations.
The three Things we wish to demo at the upcoming poster session:
1) We plan to show a composable animations demo. Currently jQuery can already do some animations like "bounce" and "shake", but many of them cannot be combined together to create a more complex animation. In our composable animations demo, we hope to show the library functions that we've developed, and how they can all be stacked and combined to create a more complex piece.
2) Code and Syntax. We plan to show the off the coding syntax and style that we've created. A quick look at the syntax and our explanation and reasoning on why we think it's intuitive, simple, and elegant.
3) Crazy animation. Using our plugin, we create the most complex and crazy animation that we can think of. This is to demonstrate the power and ability of our plugin.
The three Things we wish to demo at the upcoming poster session:
1) We plan to show a composable animations demo. Currently jQuery can already do some animations like "bounce" and "shake", but many of them cannot be combined together to create a more complex animation. In our composable animations demo, we hope to show the library functions that we've developed, and how they can all be stacked and combined to create a more complex piece.
2) Code and Syntax. We plan to show the off the coding syntax and style that we've created. A quick look at the syntax and our explanation and reasoning on why we think it's intuitive, simple, and elegant.
3) Crazy animation. Using our plugin, we create the most complex and crazy animation that we can think of. This is to demonstrate the power and ability of our plugin.
Subscribe to:
Posts (Atom)