JavaScript Animations, Part II: Nested Animations - Doc JavaScript
Nested Animations
An animation can be nested within another animation. For example, one element can revolve around a second elemenet, while that second element is moving in a different direction. This may seem like a lot of math, but it's not. We'll take advantage of CSS-P to get the job done. Take a look at the following HTML definition:
<DIV ID="balls" STYLE="position: absolute; left: -->
200; top: 50; width: 150; height: 150;">
<DIV ID="ball1" STYLE="position: absolute; left: -->
50; top: 50; width: 50;"><IMG SRC="ball1.gif" -->
WIDTH="50" HEIGHT="50"></DIV>
<DIV ID="ball2" STYLE="position: absolute; left: -->
125; top: 62; width: 25;"><IMG SRC="ball2.gif" -->
WIDTH="25" HEIGHT="25"></DIV>
</DIV>
As you can see, this definition includes three elemenets -- one parent and two children. The left
and top
properties of the inner elements are measured in relation to the parent element. We set their position
property to absolute
so they are positioned at the specified coordinates, relative to the left top corner of the window. The relative
value positions the element with respect to the normal document flow. Now let's take another look at our animation()
constructor function:
function animation(id) {
this.element = (NS4) ? document[id] : document.all[id].style;
this.active = 0;
this.timer = null;
this.name = id + "Var";
eval(this.name + " = this");
this.show = show;
this.hide = hide;
this.left = left;
this.top = top;
this.moveTo = moveTo;
this.glide = slideBy;
this.lineSlide = lineSlide;
this.slideTo = slideTo;
this.circle = circle;
this.circleSlide = circleSlide;
}
The function accepts one string, specifying the value of the element's ID
attribute. However, we cannot use it to animate a nested element. Therefore, we need to modify the function:
function animation() {
var args = animation.arguments;
if (NS4) {
this.element = window; // the window object
for (var i = 0; i < args.length; i++) {
this.element = this.element.document[args[i]];
}
} else {
this.element = document.all[args[args.length - 1]].style;
}
this.active = 0;
this.timer = null;
this.name = args[args.length - 1] + "Var";
eval(this.name + " = this");
this.show = show;
this.hide = hide;
this.left = left;
this.top = top;
this.moveTo = moveTo;
this.slideBy = slideBy;
this.lineSlide = lineSlide;
this.slideTo = slideTo;
this.circle = circle;
this.circleSlide = circleSlide;
}
First, we assign the array of the function's arguments to a local variable. But before we continue, take a look at the script that invokes the nested animations (corresponding to the above HTML definitions):
<SCRIPT LANGUAGE="JavaScript1.2">
<!--
document.write("<SCRIPT SRC='animate.js'></SCRIPT>");
onload = start;
function start() {
anim1 = new animation("balls");
if (!anim1.element) return;
anim2 = new animation("balls", "ball2");
anim1.circle(100, 90, 90, 3, -2, 100);
anim2.circle(62, 0, null, 0, 3, 25);
}
// -->
</SCRIPT>
If we want to reference the element named "ball2
," which is nested within "balls
," we need to specify both elements, from top to bottom:
anim2 = new animation("balls", "ball2");
For Internet Explorer 4.0x, we simply set the element
property to:
this.element = document.all[args[args.length - 1]].style;
args[args.length - 1]
represents the last element in the array. Explorer exposes all elements as properties of the document.all
object, regardless of their level. Navigator, on the other hand, utilizes a hierarchical structure, where a nested element is reflected as a property of its parent's document
object. For example, the following code represents the element "ball2
" in our example:
document.layers.balls.document.layers.ball2 // or
document.balls.document.ball2
In Explorer, the same element is referenced:
document.all.ball2 // or
ball2
Back to the animation
function itself. If the user is running Navigator 4.0x, the following code is executed:
this.element = window; // the window object
for (var i = 0; i < args.length; i++) {
this.element = this.element.document[args[i]];
}
The animation object's element
property is initialized to reflect the topmost window
object. We then loop through the function's arguments, moving down the hierarchy to the final element (the nested one). The element
property always references the current element, so this.element.document[args[i]]
actually reflects the next one (which is a property of the current element's document
object).
Created: May 21, 1998
Revised: May 21, 1998
URL: https://www.webreference.com/js/column19/nested.html