If anyone is interested, I have also developed
an (swt) animation framework of my own in my company. Below is a design
document I scribbled up when I was planning features and api for the framework.
I am currently in the process of convincing management to release the code to
open source (let’s hope they have no objections)
Introduction
Transitions and animation are becoming
quickly very popular in various user interfaces. Mostly known from Flash and
web interfaces, these are quickly becoming popular in desktop applications as well.
In environments that provide easy to use API for supporting animations,
judicious use of smooth transitions between various UI states does not only
serve as pretty eye-candy for the user to admire, but it also increases
usability by drawing attention where it is due (highlighting changes) or
reducing perceived latency.
SWT as such does not provide any special
support for animation, thus implementing even such simple animations as sliding
message boxes or fade in/out effects, has to be implemented separately in each
individual case.
New animation framework, if implemented
correctly should make some of the pain of animating and transitioning go away
by introducing simple to use, streamlined API for choreographing desired widget
animations. Simple animations should be simple to create and run and complex
animations should be possible to create by composition of simple animations.
This API is not yet fully implemented - this
documentation aims to specify the requirements for the API and help to gain the
understanding in how this framework should be implemented.
Basic consideration when designing this API
are that it should be as descriptive as possible without enforcing any more
verbose initialization that is absolutely necessary.
Reading the code that initiates the
animation should yield automatic understanding what kind of animations are
applied and to which elements.
It should be possible to animate any
property of any object (not just SWT controls). In this sense, the animation
could be defined as gradual change of the value of a property of an object over
time.
Animating a change of a single property
should be as straight-forward as possible:
...
public
void animate1(Control control) {
Animator.start(
new
Move(control, new Point(0, 0), new Point(100, 100),
Easing.FAST, Easing.EaseInOutQuad);
)
}
...
The above code snippet would move the
control quickly from point (0,0) to (100, 100), starting up slowly, speeding up
and then slowing down again towards the end.
Basic signature of the animation constructor
should probably look something like this:
AnimationType(Object
target[, Object start], Object end[, int duration][, Easing ease]);
Where target is the target object (usually Control)
that will be animated, start is (an optional) start position of the property to
be animated, end is the end position of the property to be animated, duration
is the duration of the animation in milliseconds and easing is the progression
easing strategy.
For the sake of the brevity and readability,
start, duration and easing attributes could be optional. Start attribute would
have to default to whatever is the current position of the animated property;
duration would default to 1s; and easing would default to linear progression.
See also #Cascading animation attributes
Position of
an animation is just a generic term to represent a value of the animated
property. For example in case of Move animations, position is a Point in
2 dimensional plain. In case of Resize animation, position represents
dimensions of an object and in case of Foreground or Background animation, position
is a color.
To run multiple animations in parallel, you
would wrap these inside Parallel animation container:
...
Animator.start(
new
Parallel(
new
Move(control, new Point(100, 100), new Point(0, 0),
Easing.DEFAULT, Easing.EaseOutQuad),
new
Resize(control, new Point(0, 0), new Point(100, 100),
Easing.DEFAULT, Easing.EaseOutQuad)
);
}
...
The above code snippet would basically
"grow" the control from bottom right to top left by moving its upper
left corner from point (100,100) to (0,0) and at the same time resizing it from
size of (0,0) to (100,100) pixels.
Sometimes, it is necessary to run multiple
animations chained one after another, so that when one animation finishes,
another starts and so on, until the last animation has finished.
...
Animator.start(
new
Sequence(
new
Resize(control, new Point(0, 0), new Point(100, 100),
Easing.SLOW, Easing.EaseOutQuad),
new
Move(control, new Point(0, 0), new Point(0, 100),
Easing.SLOW, Easing.EaseOutQuad)
)
);
...
Above snippet first resizes the specified
control from (0,0) to (100,100) pixels and then move it horizontally from (0,0)
to (0,100).
By combining chained animations and parallel
animations, more complex animations can be created:
...
Animator.start(
new
Sequence(
new
Parallel(
new Resize(control, new Point(0, 0), new Point(100, 100),
Easing.FAST, Easing.EaseInQuad),
new Move(control, new Point(0,100), new Point(0,0),
Easing.FAST, Easing.EaseInQuad)
),
new
Move(control, new Point(0, 0), new Point(0, 200),
Easing.DEFAULT, Easing.Linear),
new
Parallel(
new Resize(control, new Point(100, 100), new Point(0, 0),
Easing.FAST, Easing.EaseOutQuad),
new Move(control, new Point(0, 200), new Point(0, 300),
Easing.FAST, Easing.EaseOutQuad)
)
)
);
...
Orchestrating an animation is a job of
special Animator object whose sole responsibility is to spawn new animation
thread when animation is started and manage the synchronization of the
animation thread and UI thread, tick off the animation frames at the suitable frame
rate and kill the animation thread when animation ends.
The two most important methods an animator
has are start(Animation) and run(Animation)
The difference between these two is that start(Animation) starts an animation in a separate thread and returns immediately,
while run(Animation) method returns only when the entire animation has completed.
In addition, the Animator and Animation
classes allow adding listeners to them that allow interested parties to get
notified of various animation related events like when an animation was
started, stopped, paused or resumed:
...
Animator.addListener(new
AnimationListenerAdapter() {
public
void animationFinished() {
/* perform follow-up actions here */
}
});
...

|
This feature would be
nice to have in future, but it really severely complicates the inner
workings of the animation framework, so at the moment this is not
implemented.
|
It should be possible to define common
animation attributes (animation target, length and easing strategy) for a
composite animation container (e.g. Sequence or Parallel) and have it cascade
through to contained animations.
The aim is to simplify animation definition
code as much as possible and increase its legibility.
...
Animator.start(
new
Sequence(control,
new
Parallel(Easing.FAST, Easing.EaseInQuad,
new Resize(new Point(0, 0), new Point(100, 100)),
new Move(new Point(0,100), new Point(0,0))
),
new
Move(new Point(0, 0), new Point(0, 200),
Easing.DEFAULT, Easing.Linear),
new
Parallel(Easing.FAST, Easing.EaseOutQuad,
new Resize(new Point(100, 100), new Point(0, 0)),
new Move(new Point(0, 200), new Point(0, 300))
)
)
);
...
Easing is acceleration, a change in speed.
When an object is moving, it has a velocity of some magnitude. When the object
is not moving, its velocity is zero. In the real world, velocity doesn’t
suddenly jump from one value to another. Most movements in nature have some
kind of easing. Organic processes typically involve forces. If the forces
aren’t in balance, acceleration is produced. Our minds make this connection between
acceleration and force intuitively. When we see the velocity of an object
gradually changing, we infer that some force is steadily pushing or pulling it.
As a result, animation usually looks more natural and fluid when it follows
similar rules.
There are three categories of easing:
ease-in, ease-out and ease-in-out. Ease in starts slow and speeds up towards
the end of the motion. Ease out is the opposite of ease-in — starting fast and
slowing down towards the end. Ease in-out is the combination, that starts by
easing in and finishes by easing out.
The framework contains three classes of
easing strategies for 7 easing variants: Quadratic easing (p(t) = t2), Cubic
(p(t) = t3) easing, Quartic (p(t) = t4) easing, Quintic (p(t) =
t5) easing, Sinusoidal (p(t) = sin(t × π⁄2)) easing, Exponential
(p(t) = 210(t-1)) easing and Circular (p(t) = 1 - √1 - t2) easing
Custom easing strategies can be implemented
by subclassing abstract Easing class.
| Roland
Tepp | R&D | Work: +372
697-6597 | Mobile: +372 556-12458 | MSN: roland14@xxxxxxxxxxxx | Google
Talk: luolong@xxxxxxxxx |http://www.videobet.com/
This
communication contains information which is privileged and confidential and is
exclusively intended only for the individual or entity named above
(recipient(s)). If you are not the intended recipient(s) or the person
responsible for delivering it to the intended recipient(s), you are hereby
notified that any review, disclosure, dissemination, distribution or
reproduction of this communication message in any way or act is prohibited. If
you receive this communication by mistake please notify the sender immediately
and then destroy any copies of it. Please note that the sender monitors e-mails
sent or received. Thank you.