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.

Comments: Post a Comment

<< Home

Powered by Blogger

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