reptile7's JavaScript blog
Sunday, February 24, 2013
 
Sister Image Ray
Blog Entry #280

In today's post we will take up Peter Gehrig's "trailing images" script, the second of two scripts offered by Section 7 of the JavaScript subsector of Lissa Explains It All. The trailing images script complements the floating images script we've been discussing in the last couple of entries in that it sends a beam of images on a common diagonal and bouncing path in the viewport area. As the beam forms and moves, the position of the beam's first image is used to set the positions of the following images so as to create a "trail" of the first image.

Lissa provides a bounce.html demo page for the trailing images script; the bounce.html demo works with IE 4+, Netscape 4.x, and Opera 5-9.2. As far as I am aware, Peter has not updated the trailing images script (at least I couldn't find an update at fabulant.com) - it is up to us to bring the script into the modern era.

The beam images

For the bounce.html demo, Lissa works with a set of thirteen starry.gif images.

// URL of your image. Attention: big images will slow down the script!
var your_image = "starry.gif";
var numberofimages = 12;
/* numberofimages actually represents the index of the beam's last image - if you want numberofimages to represent the "number of images", then you'll have to change <= to < in the script's for loop conditions. */


Here's starry.gif, which can be downloaded as an abstar6.gif file at Lissa's Cursor Images page:
The starry.gif image
Regarding the // URL of your image comment, the beam can be composed of different images vis-à-vis just one image, although the latter is what Lissa chose to do.

The starry.gif image is preloaded in the usual manner:

var imgpreload = new Image( );
imgpreload.src = your_image;


IE 5.x and Netscape 4.x were the current versions of IE and Netscape respectively when the trailing images script was written in the summer of 2000. IE 4+ will position the img element but Netscape 4.x won't, so Peter wrapped the beam images in span elements.

var spancontent = new Array( );
for (i = 0; i <= numberofimages; i++) {
    spancontent[i] = "<img src='" + your_image + "'>";
    document.write("<span id='span" + i + "' style='position:absolute;'></span>");
    document.close( ); }


The spancontent elements are loaded into the span+i spans after the page loads by the script's setValues2( ) function: the IE code* for this process is given below.
*From here onward, wherever the script features an IE part and a Netscape part I will specify the IE part.

function setValues2( ) {
    if (document.all) {
        for (i = 0; i <= numberofimages; i++) {
            var thisspan = eval("document.all.span" + i);
            thisspan.innerHTML = spancontent[i]; ... } ... }
    /* Meant-for-Netscape layerObject-based code for writing spancontent to the page. */ ... }


Pre-beam

When the page loads

<body id="thisbody" bgcolor="black" onload="setValues( );" style="width:100%;overflow-x:hidden;overflow-y:hidden;">
<!-- No use is made of the body id. -->


the script's setValues( ) function is called. The setValues( ) function body comprises a single command that calls the aforementioned setValues2( ) function after a two-second delay.

function setValues( ) { var firsttimer = window.setTimeout("setValues2( );", 2000); }
/* No use is made of the firsttimer timer. */


There is no need for the intermediacy of the setValues( ) function, of course; setValues2( ) can be called directly by either the body element start-tag or (per my preference) a JavaScript statement.

window.onload = function ( ) { window.setTimeout("setValues2( );", 2000); }

No starry.gif images are visible when the page loads as the span+i spans are empty at that time. The setValues2( ) function respectively fills the spans with starry.gif images (vide supra) and then immediately places the spans - all thirteen of them - in the page's upper-left-hand corner:

var thisspan = eval("document.all.span" + (i) + ".style");
thisspan.posLeft = 0;
thisspan.postop = 0;


The setValues2( ) function also
(a) gets, but does not act on, the viewport dimensions, and
(b) calls a moveball( ) function, which mediates the span-image movement.

var marginbottom, marginright;
...
marginbottom = document.body.clientHeight - 5;
marginright = document.body.clientWidth - 5;
...
moveball( );


Here's the moveball( ) function:

// Average vertical distance between the images
var stepy = 20;
// Speed
var tempo = 40;

function moveball( ) {
    if (document.all) {
        checkposition( );
        makesnake( );
        document.all.span0.style.posTop += stepy;
        timer = window.setTimeout("moveball( );", tempo); }
    /* Netscape part */ }


The moveball( ) function first calls a checkposition( ) function, which bounces the image beam when it hits a viewport edge and which we'll deal with later as it doesn't do anything right now. Subsequently the moveball( ) function calls a makesnake( ) function, which iteratively creates the image beam and moves it around the viewport area.

Quit dreaming and get on the beam

In this section we assume a viewport width of at least 285 pixels, otherwise the beam's first image will hit the right edge of the viewport before the beam has 'unfurled'.

for (i = 0; i <= numberofimages; i++) {
    xpos[i] = 0;
    ypos[i] = 0; }
// Average horizontal distance between the images
var stepx = 20;
function makesnake( ) {
    for (i = numberofimages; i >= 1; i--) {
        xpos[i] = xpos[i - 1];
        ypos[i] = ypos[i - 1]; }
    if (document.all) {
        xpos[0] = document.all.span0.style.posLeft + stepx;
        ypos[0] = document.all.span0.style.posTop + stepy;
        for (i = 0; i <= numberofimages; i++) {
            var thisspan = eval("document.all.span" + (i) + ".style");
            thisspan.posLeft = xpos[i];
            thisspan.posTop = ypos[i]; } }
    /* Netscape stuff */ }


The trailing images script's makesnake( ) function has a lot in common with the makesnake( ) function of Peter's cursor trailer script, which we discussed in Blog Entry #277. Here are the highlights:

• Left and top offsets for the span+i spans are respectively stored in xpos and ypos arrays, which are declared and initialized in the top-level part of the code.

• The xpos/ypos span offsets are calculated in reverse order (12 to 0 indexwise) but are actually set in forward order (0 to 12 indexwise).

• Successive span offsets are initially separated horizontally and vertically by stepx and stepy lengths, respectively; unfortunately, the stepx/stepy values are not fixed but are subject to 'drift' in the script's checkposition( ) function - more on this later.

As shown above, the moveball( ) function is recursively re-called every tempo (40) milliseconds; note that a document.all.span0.style.posTop += stepy; assignment precedes the setTimeout( ) operation.

In the first moveball( ) iteration
(0) The span0 span moves to (xpos[0],ypos[0]) = (20,20) via the makesnake( ) function and then to (20,40) via the pre-setTimeout( ) posTop assignment.
(1-12) All of the other spans remain at the viewport origin.

In the second moveball( ) iteration
(0) The span0 span moves to (40,60) via the makesnake( ) function and then to (40,80) via the pre-setTimeout( ) posTop assignment.
(1) The span1 span picks up the span0 span's coordinates from the first makesnake( ) run and moves to (xpos[1],ypos[1]) = (20,20).
(2-12) All of the other spans remain at the viewport origin.

In the third moveball( ) iteration
(0) The span0 span moves to (60,100) via the makesnake( ) function and then to (60,120) via the pre-setTimeout( ) posTop assignment.
(1) The span1 span picks up the span0 span's coordinates from the second makesnake( ) run and moves to (40,60).
(2) The span2 span picks up the span1 span's coordinates from the second makesnake( ) run and moves to (xpos[2],ypos[2]) = (20,20).
(3-12) All of the other spans remain at the viewport origin.

And so on. After thirteen moveball( ) iterations the image beam is complete:

The starry.gif image beam

If we were to both calculate and set the span offsets in forward order

for (i = 0; i <= numberofimages; i++) {
    xpos[i] = i ? xpos[i - 1] : document.all.span0.style.posLeft + stepx;
    ypos[i] = i ? ypos[i - 1] : document.all.span0.style.posTop + stepy;
    var thisspan = eval("document.all.span" + (i) + ".style");
    thisspan.posLeft = xpos[i];
    thisspan.posTop = ypos[i]; }


then we wouldn't have a beam: the span1-span12 spans would move as a single unit (they'd all move as a single unit if we also commented out the pre-setTimeout( ) posTop assignment).

As the moveball( ) cycle continues the beam moves on a southeastern path until it hits the bottom edge of the viewport, at which point the checkposition( ) function kicks in. We'll go through the checkposition( ) function in detail in the following entry.

Thursday, February 14, 2013
 
When the Butterfly Hits the Wall
Blog Entry #279

We continue today our analysis of Peter Gehrig's floating images script. We have one last script function to consider, namely, the checkposition( ) function, which bounces the span+i spans when they hit the edges of the viewport. As for the script's setValues( ), checkmovement( ), and movepictures( ) functions, the checkposition( ) function body comprises separate if statements that respectively cater to IE and Netscape; we will work with the IE statement in the discussion below.

function checkposition( ) {
    if (document.all) {
        for (i = 0; i <= numberofimages; i++) {
            var thisspan = eval("document.all.span" + i + ".style");
            ... } ... } ... }


Each if statement in turn contains another four if statements that respectively bounce the spans at the viewport's four edges. Here's the IE statement code that handles the right-edge action:

if (thisspan.posLeft > marginright - imgwidth[i]) {
    thisspan.posLeft -= Math.abs(stepx[i] + 1);
    stepx[i] = randommaker(floatingspeed) * -1; /* Alternatively: stepx[i] = -randommaker(floatingspeed); */ }


Recall that marginright was set to document.body.clientWidth-5 by the corresponding IE statement in the setValues( ) function and that imgwidth[i], the span-link-image width, is 35 (pixels). If a span's style.posLeft (left edge) moves within a 40px-wide buffer abutting the right edge of the viewport:

(1) The span's stepx[i] horizontal step is incremented and the span is shifted leftward by stepx[i]+1 pixels.

(2) A new, negative stepx[i] is calculated for the span by feeding floatingspeed (5) to the randommaker( ) function and then multiplying the rand return by -1.

The checkposition( ) function is called before the movepictures( ) function for a reason: a span's starting style.posLeft offset could be inside the marginright-imgwidth[i] buffer; in this situation the Math.abs( ) operation keeps the span moving leftward (more precisely, it prevents any rightward movement) if a single stepx[i]+1 shift does not push the span's style.posLeft out of the buffer. That said, the thisspan.posLeft -= Math.abs(stepx[i] + 1); statement is in fact unnecessary as the movepictures( ) function by itself will push the span out of the buffer sooner or later (within a second), regardless of the span's style.posLeft/stepx[i] values.

The corresponding if statements for the viewport's other three edges are given below. The posLeft/posTop assignments in these statements are again unnecessary. I have no idea why the stepx[i] shift in the right-edge statement is incremented whereas the stepx[i]/stepy[i] shifts in the other statements are not.

var marginleft = 0;
var margintop = 0;
...

if (thisspan.posLeft < marginleft) { // For the left edge
    thisspan.posLeft += Math.abs(stepx[i]);
    stepx[i] = randommaker(floatingspeed); }
if (thisspan.posTop > marginbottom - imgheight[i]) { // For the bottom edge
    thisspan.posTop -= Math.abs(stepy[i]);
    stepy[i] = randommaker(floatingspeed) * -1; }
if (thisspan.posTop < margintop) { // For the top edge
    thisspan.posTop += Math.abs(stepy[i]);
    stepy[i] = randommaker(floatingspeed); }


A span is bounced rightward if its style.posLeft moves to the left of marginleft, the viewport's left edge; it is bounced upward if its style.posTop (top edge) is initially positioned in or moves within a 40px-high marginbottom-imgheight[i] buffer at the bottom of the viewport; it is bounced downward if its style.posTop moves above margintop, the viewport's top edge.

The horizontal scrollbar thing, revisited

Let's get back to the marginright-imgwidth[i] right buffer for a moment. If a span is outside the buffer, then the -5 subtraction built into marginright should prevent the span from bumping into the right edge of the viewport and generating a horizontal scrollbar
(a) on the IE side whether or not a vertical scrollbar is initially present
(b) and on the Netscape side if a vertical scrollbar is not initially present
(recall that 4 is the highest stepx[i] value)
(c) but not on the Netscape side if a vertical scrollbar is initially present as the scrollbar's width is included in Netscape's window.innerWidth-5 marginright.
A corresponding set of circumstances applies to the marginbottom-imgheight[i] bottom buffer and the generation of a vertical scrollbar. In practice on my computer, (b) pans out but (a) and (c) don't: I end up getting horizontal and vertical scrollbars with IE 5.1.6 but not with Netscape 4.61 whether or not any scrollbars are initially present. (IE 5.x and Netscape 4.x were the current versions of IE and Netscape respectively when the floating images script was crafted in the summer of 2000.)

Lissa dealt with the scrollbar generation problem by giving the body element overflow-x:hidden; and overflow-y:hidden; stylings.

<body id="thisbody" bgcolor="#ffcc00" onload="setValues( );" style="width:100%;overflow-x:hidden;overflow-y:hidden;">

We first encountered the overflow-x and overflow-y style properties in our discussion of Peter Gehrig's cursor trailer script, for which I thought they were superfluous, but I would agree that they are useful in the present case. The overflow-x and overflow-y properties are dimensional versions of the standard CSS overflow property and are themselves on track to be standardized. Back in the day overflow-x and overflow-y were IE only (and didn't work on the Mac platform); today they are supported by all of the major browsers. However, if overflow-x and overflow-y are both set to hidden, then it would probably be a good idea to replace the overflow-x:hidden;overflow-y:hidden; declarations with a single overflow:hidden; declaration as W3Schools reports that overflow-x and overflow-y do not work properly in IE 8 and earlier.

More retool

In this section I'll describe the additional changes I would make to the floating images script.

Structure

First and foremost, I would throw out the span+i span wrappers and the your_image_link link wrappers and just work with a bttr0.gif/bttr1.gif/bttr2.gif/bttr3.gif/bttr4.gif set of images.

.floatingimage { position: absolute; }
...
for (i = 0; i < your_image.length; i++) document.write("<img id='img" + i + "' class='floatingimage' src='bttr" + i + ".gif'>");


In the setValues( ), movepictures( ), and checkposition( ) functions, I would reference the images via a globally declared floats array.

var floats = new Array(5);
if (document.getElementById)
    window.onload = function ( ) {
        for (i = 0; i < your_image.length; i++) floats[i] = document.getElementById("img" + i);
        setValues( ); }


Although modern browsers support the original script's document.all.span code, getting the images with the getElementById( ) method is clearly the better way to go. Moreover, defining the floats array when the page loads makes it unnecessary to create thisspan-type object references over and over again in the script's functions.

Positioning

Naturally, we want to replace the nonstandard posLeft/posTop property pair with the standard left/top property pair. When writing offsets a simple substitution of the latter for the former will suffice:

// Initial positioning in the setValues( ) function:
for (i = 0; i < your_image.length; i++) {
    floats[i].style.left = randommaker(marginright) + "px";
    floats[i].style.top = randommaker(marginbottom) + "px"; }


The px unit specifications are not necessary if the user's browser is running in quirks mode but I encourage you to put them there anyway.

When reading and subsequently operating on offsets in the movepictures( ) and checkposition( ) functions the situation is more complicated because left and top are strings that include unit identifiers; for these operations we'll need to 'numberify' left and top via the top-level parseInt( ) function.

function movepictures( ) {
    for (i = 0; i < your_image.length; i++) {
        floats[i].style.left = parseInt(floats[i].style.left, 10) + stepx[i] + "px";
        floats[i].style.top = parseInt(floats[i].style.top, 10) + stepy[i] + "px"; } }


Miscellaneous

• The script's layer object code is only supported by Netscape 4.x - throw it out. The three if(document.all) gates can be traded in for a single if(document.getElementById) gate that guards the window.onload functionality.

• The -5 subtractions of the marginbottom/marginright definitions can themselves be subtracted if the document body's overflow is hidden.

// The source for my original demo put these statements in the window.onload function body.
marginright = window.innerWidth ? window.innerWidth : document.body.clientWidth;
marginbottom = window.innerHeight ? window.innerHeight : document.body.clientHeight;


• The var x, y; declaration in the first script element can be removed: no use is made of these variables.

Demo

Spring is in the air...
butterfly
butterfly
butterfly
butterfly
butterfly


Further study

The How do I make floating images? subsection's Peter Gehrig link to http://www.24fun.com/fast/index.html is dead; however, there are several floating images scripts at fabulant.com that you may want to check out:
(1) Image Gallery with Floating Thumbnails
(2) JavaScript 3D-Slideshow
(3) Floating YouTube Video
(4) Floating Images Animation
(5) New-Year-Animation: Floating Luckycharms Script
(Unfortunately, most of the images accompanying these scripts were not saved by the Internet Archive - the Floating Luckycharms Script images are there but the rest of them are gone - but at least the code is still available.)

We'll move on to Section 7's trailing images script in the following entry.

Monday, February 04, 2013
 
Float Like a Butterfly
Blog Entry #278

In today's post we will take up Peter Gehrig's "floating images" script, the first of two scripts offered by Section 7 of the JavaScript subsector of Lissa Explains It All. The floating images script moves a set of images on diagonal, bouncing paths in the viewport area. The floating images script's effect is almost identical to that of the Bounce All Around script of Lisha Sterling's "How to Create a JavaScript Animation" tutorial, which we discussed in the Animation #4 section of Blog Entry #210.

Most of the floating images script code (excluding its body element start-tag) is provided in two textarea fields on the Section 7 javascript7.shtml page. Lissa's instruction for the script element held by the second textarea field - put this code immediately after the above body tag - is fine, but her instruction for the script element held by the first textarea field - add this [code] immediately after your </head> tag and before the <body> tag - would violate the html element's HEAD, BODY content model, i.e., the html element cannot validly have a script element child. The first script can be deployed in the document head (recommended) or as the first child of the body element, but you shouldn't put it between the document head and the document body.

Lissa provides a float.html demo page for the floating images script; the float.html demo works with IE 4+, Netscape 4.x, and Opera 5-9.2. I'll give you my own demo at the end of our discussion.

The floating images and their wrappers

For the float.html demo, Lissa works with a set of five images:

// URLs of floating images - add as many images as you like.
// ATTENTION: Too many images will slow down the floating effect.
var your_image = new Array( );
your_image[0] = "yourimage.gif";
your_image[1] = "yourimage.gif";
your_image[2] = "yourimage.gif";
your_image[3] = "yourimage.gif";
your_image[4] = "yourimage.gif";


She specifically fills the your_image array with bttr1.gif, bttr2.gif, bttr3.gif, bttr4.gif, and bttr5.gif butterfly images. The images are preloaded with the following code:

var imgpreload = new Array( );
for (i = 0; i <= your_image.length; i++) {
    imgpreload[i] = new Image( );
    imgpreload[i].src = your_image[i]; }


The for loop actually creates six Image objects - the src of the imgpreload[5] Image is undefined - replacing the <= operator with the < operator sorts out the situation.

Each image is placed in a your_image_link link:

// You may add links for each image separately.
// In case you do not want to link a picture just add a '#' instead of a URL.
var your_image_link = new Array( );
your_image_link[0] = "http://www.yourlink.com";
your_image_link[1] = "http://www.yourlink.com";
your_image_link[2] = "http://www.yourlink.com";
your_image_link[3] = "#";
your_image_link[4] = "http://www.yourlink.com";

var numberofimages = your_image.length - 1;
var spancontent = new Array( );

for (i = 0; i <= numberofimages; i++) {
    spancontent[i] = "<a href='" + your_image_link[i] + "'><img src='" + your_image[i] + "' border='0'></a>"; }


(The numberofimages variable should really be set to your_image.length, but whatever.)
This is bad design in my book: links should not be attached to moving elements. But let's keep going for now. As you might guess from the spancontent array declaration, the your_image_link/your_image content is itself loaded into span elements:

function setValues( ) { ...
    for (i = 0; i <= numberofimages; i++) {
        var thisspan = eval("document.all.span" + i);
        thisspan.innerHTML = spancontent[i]; ... } ... }

...
<body onload="setValues( );">
...

for (i = 0; i <= numberofimages; i++) {
    document.write("<span id='span" + i + "' style='position:absolute;'></span>");
    document.close( ); }


Without getting into the details, the span wrappers are required by both IE 4.x and Netscape 4.x - but not by later browsers - to position the link-image structure(s).

The script unnecessarily defines imgwidth and imgheight arrays that respectively hold the widths and heights of the your_image images (more precisely, the widths/heights of the span wrappers):

var imgwidth = new Array( );
var imgheight = new Array( );
for (i = 0; i <= numberofimages; i++) {
    imgwidth[i] = 10;
    imgheight[i] = 10; }


function setValues( ) { ...
    for (i = 0; i <= numberofimages; i++) {
        var thisspan = eval("document.all.span" + i);
        imgwidth[i] = thisspan.offsetWidth;
        imgheight[i] = thisspan.offsetHeight; } ... }


All five butterfly images are 35px by 35px; this information can and should be specified in the imgpreload Image constructor:

imgpreload[i] = new Image(35, 35);

As noted in the windowheight vs. pageheight section of Blog Entry #272, offsetWidth/offsetHeight returns the content+padding+border width/height of an element. On my computer, a span wrapper adds no thickness to an underlying image and the span offsetWidth/offsetHeight is equal to the image width/height as long as the image is borderless. With IE 4.x, Netscape 4-9, and Camino, the link wrappers impart a solid 2px border (the border color is either blue or #0000ee, depending on the browser) to the images in the absence of the border='0' attribute.

Initial positioning

Loading the script document triggers a setValues( ) function. The setValues( ) function body comprises separate meant-for-IE and meant-for-Netscape if statements that carry out a common set of tasks:
(1) they get the width and height of the viewport;
(2) they load the links-images into the span wrappers;
(3) in conjunction with a randommaker( ) function, they give the spans random left and top offsets in the viewport area;
(4) they get the widths and heights of the spans;
(5) they call a checkmovement( ) function, which mediates the span-link-image movement.
Access to the IE block proceeds through an if(document.all) gate; access to the Netscape block proceeds through an if(document.layers) gate.

The IE block code for tasks (2) and (4) was given in the preceding section; I would just as soon not discuss the corresponding Netscape block code as it involves document.layerID and document.layerID.document expressions that are only supported by Netscape 4.x. So let's turn to tasks (1) and (3).

Viewport dimensions

var marginbottom, marginright;
// In the IE block:
marginbottom = document.body.clientHeight - 5;
marginright = document.body.clientWidth - 5;
// In the Netscape block:
marginbottom = window.innerHeight - 5;
marginright = window.innerWidth - 5;


We've been through the body.clientHeight/body.clientWidth/innerHeight/innerWidth thing several times previously so there's no need to rehash it again - just remember that the user's browser must be running in quirks mode for body.clientHeight/body.clientWidth to return the viewport dimensions. The -5 subtractions effectively create 'buffers' that will later prevent the floating images from bumping into the right and bottom edges of the viewport if no scrollbars are present - more on this when we discuss the script's checkposition( ) function.

Starting offsets

// In the IE block:
var thisspan = eval("document.all.span" + (i) + ".style");
thisspan.posLeft = randommaker(marginright);
thisspan.posTop = randommaker(marginbottom);
/* The Netscape block assigns the randommaker( ) returns to layerObject.left and layerObject.top expressions. */


function randommaker(range) {
    rand = Math.floor(range * Math.random( ));
    if (rand == 0) { rand = Math.ceil(range / 2); }
    return rand; }


(Man, what is it with the eval( ) code? Even back in the day with a level-4 browser it wasn't necessary: on the IE side we could reference a span object with document.all("span"+i); on the Netscape side we could reference a corresponding layer object with document.layers["span"+i]. Above and beyond its superfluity - not to mention its other problems - it just looks ugly; we'll chuck it in due course.)

The posLeft and posTop style object properties have a number data type (the standard CSS left and top properties have a string data type); although the randommaker( ) function only returns integers, posLeft and posTop can also be floating-point numbers. In the absence of prior left and top settings, posLeft and posTop lengths are given px units by the browser. As noted in the Trail it section of the previous entry, posLeft and posTop are supported by IE, Google Chrome, Safari, and Opera, but not by Mozilla's browsers. Interestingly, Mozilla's browsers would handle the eval("document.all.span"+(i)+".style") operation without incident.

The randommaker( ) function outputs a random integer in the range running from 1 to range-1, inclusive; its body can be written as a single statement if desired:

return 1 + Math.floor((range - 1) * Math.random( ));

Moving the pictures

Both setValues( ) if statements conclude with a checkmovement( ); call to a checkmovement( ) function. Here's checkmovement( ):

var tempo = 20, timer;
function checkmovement( ) {
    if (document.all) {
        checkposition( );
        movepictures( );
        timer = window.setTimeout("checkmovement( );", tempo); }
    if (document.layers) {
        checkposition( );
        movepictures( );
        timer = window.setTimeout("checkmovement( );", tempo); } }


The checkmovement( ) function body comprises two if statements that have different conditions but are otherwise identical: there is of course no reason not to merge the statements into a single if (document.all || document.layers) { ... } statement (well, other than the fact that we want to lose the script's layer code, but we'll get to that later). The checkmovement( ) function calls initially a checkposition( ) function and then a movepictures( ) function and finally itself after a delay of tempo (20) milliseconds. We'll look at the movepictures( ) function first as it's a lot simpler than the checkposition( ) function.

// Average speed of the floating images: higher means faster
var floatingspeed = 5;
var stepx = new Array( );
var stepy = new Array( );

for (i = 0; i <= numberofimages; i++) {
    stepx[i] = randommaker(floatingspeed);
    stepy[i] = randommaker(floatingspeed); }


function movepictures( ) {
    if (document.all) {
        for (i = 0; i <= numberofimages; i++) {
            var thisspan = eval("document.all.span" + (i) + ".style");
            thisspan.posLeft += stepx[i];
            thisspan.posTop += stepy[i]; } }
    /* Corresponding meant-for-Netscape layerObject-based code */ }


In the top-level part of the code we calculate sets of random stepx horizontal steps and random stepy vertical steps for the span-link-image movement by feeding a floatingspeed (5) value to the randommaker( ) function. The stepx and stepy values range from 1 to 4, inclusive (not only is floatingspeed not the average [step length] of the floating images but it lies outside the step length range); the movepictures( ) function respectively assigns these values to the style.posLeft and style.posTop properties of the span+i spans in order to move the spans along diagonal paths in the viewport area.

Go back and look at the randommaker( ) function: note that the if (rand == 0) { rand = Math.ceil(range / 2); } conditional prevents a return of 0. It wouldn't be a problem if a span was initially positioned at the left or top edge of the viewport, as would happen respectively if the span's style.posLeft or style.posTop was set to 0 in the setValues( ) function; however:
(1) if a span's initial stepx[i] is 0 and its initial stepy[i] is not 0, then it will follow a purely vertical path;
(2) if a span's initial stepy[i] is 0 and its initial stepx[i] is not 0, then it will follow a purely horizontal path;
(3) if a span's initial stepx[i] and stepy[i] are both 0, then it won't move at all after its initial positioning.
That stepx[i] and stepy[i] are never 0 means that all of the spans follow diagonal paths all of the time once they are set in motion.

Check the position

Going through the checkposition( ) function may take a while so let's save it for the next entry.


Powered by Blogger

Actually, reptile7's JavaScript blog is powered by Café La Llave. ;-)