JavaScript Animations, Part II: Nested Animations - Doc JavaScript | WebReference

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 elementproperty 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).

http://www.internet.com


Created: May 21, 1998
Revised: May 21, 1998

URL: http://www.webreference.com/js/column19/nested.html