13.10 Animating Circular Element Paths
NN 6, IE 5
13.10.1 Problem
You want to animate the position
of an element in a circular path.
13.10.2 Solution
To animate a positioned element along a circular path, link the
animeCirc.js library (Example 13-3 in the Discussion) to your page and invoke the
initCircAnime( ) function with five parameters in
the following sequence:
ID of animated element (as string)
x coordinate of start/end point of circle
y coordinate of start/end point of circle
Even integer value specifying the number of render points in the
circle
Integer value of relative radius of the circle
A typical set of values to put an element into motion might be as
follows:
initCircAnime("rounder", 200, 200, 36, 10);
13.10.3 Discussion
The process for circular animation is similar to the straight-line
animation of Recipe 13.9, but trigonometry assists in prescribing the
path for the element. Example 13-3 shows the
animeCirc.js
library containing the code that performs the animation.
Example 13-3. The animeCirc.js library for circular animation
// animation object holds numerous properties related to motion
var anime = new Object( );
// initialize default anime object
function initAnime( ) {
anime = {elemID:"",
xStart:0,
yStart:0,
xCurr:0,
yCurr:0,
next:1,
pts:1,
radius:1,
interval:null
};
}
// stuff animation object with necessary explicit and calculated values
function initCircAnime(elemID, startX, startY, pts, radius) {
initAnime( );
anime.elemID = elemID;
anime.xCurr = anime.xStart = startX;
anime.yCurr = anime.yStart = startY;
anime.pts = pts;
anime.radius = radius;
// set element's start position
document.getElementById(elemID).style.left = startX + "px";
document.getElementById(elemID).style.top = startY + "px";
// start the repeated invocation of the animation
anime.interval = setInterval("doCircAnimation( )", 10);
}
function doCircAnimation( ) {
if (anime.next < anime.pts) {
var x = anime.xCurr +
Math.round(Math.cos(anime.next * (Math.PI/(anime.pts/2))) * anime.radius);
var y = anime.yCurr +
Math.round(Math.sin(anime.next * (Math.PI/(anime.pts/2))) * anime.radius);
document.getElementById(anime.elemID). style.left = x + "px";
document.getElementById(anime.elemID). style.top = y + "px";
anime.xCurr = x;
anime.yCurr = y;
anime.next++;
} else {
document.getElementById(anime.elemID).style.left = anime.xStart + "px";
document.getElementById(anime.elemID).style.top = anime.yStart + "px";
clearInterval(anime.interval);
}
}
The library begins by defining an abstract animation object that gets
initialized each time a circular path runs. Your scripts invoke the
initCircAnime( ) function, which assigns parameter
values to the anime object's
properties. The function that executes repeatedly in response to
setInterval( ) comes at the
library's end.
The smoothness of the circular motion is controlled by the number of
points along the circle at which the display should be updated. This
value becomes the upper limit of anime.next in the
if clause of doCircAnimation(
). To accomplish a full circle, the value by which
Math.PI is divided in the next two lines must be
one-half the maximum value in the condition. For any given
combination of values, the radius of the circle is controlled by the
multiplier at the end of the two statements containing
Math.PI. The value (preserved as
anime.radius) is not a straight pixel measure, but
rather a factor that governs the radius. The larger the number, the
larger the radius.
If you assign larger values for anime.pts (such as
72), the animation is smoother because the arcs between refresh
points are much smaller. This also means that the motion is slower
because the interval time (at 10 milliseconds) is essentially
whirling as quickly as it can. On the other hand, too few refresh
points, while faster, may appear too jerky for your users.
13.10.4 See Also
Recipe 13.9 for straight-line animation; Recipe 3.7 for creating a
custom object.
|