reptile7's JavaScript blog
Wednesday, March 06, 2013
I'm Waiting for the Bounce
Blog Entry #281

We return now to our ongoing deconstruction of Peter Gehrig's trailing images script. At this point we have created a beam of thirteen starry.gif images and moved the beam to the bottom of the viewport via the script's moveball( ) and makesnake( ) functions. When the top edge of the beam's first image falls below the marginbottom (document.body.clientHeight-5), the image is bounced upward by the script's checkposition( ) function with an assist from the script's randommaker( ) function.

function randommaker(range) {
    rand = Math.floor(range * Math.random( ));
    return rand; }
function checkposition( ) {
    if (document.all) { ...
        if ( > marginbottom) { // At the bottom edge
            stepy = (stepy + randommaker(2)) * -1;
   -= 1; } ... } ... }

Recall that the stepy vertical step is initialized to 20 in the top-level part of the code. The stepy = (stepy + randommaker(2)) * -1; statement calculates a new, negative stepy - either -20 or -21, depending on whether the randommaker( ) rand value is 0 or 1, respectively - that will move the image beam upward via the stepy assignments in the makesnake( ) and moveball( ) functions.

For its part, the -= 1; statement shifts the beam's first image upward by a single pixel. Technically we are acting on the image's span0 span container vis-à-vis the image itself, but (at least on my computer) the span+i spans add no 'girth' to the starry.gif images.

The starry.gif image is 45px by 45px. Most or all of the first image will be below the viewport's bottom edge when the span0 span's posTop becomes greater than marginbottom; however, if we set the body element's overflow to hidden, as we should, then a vertical scrollbar will not be generated.

The stepx horizontal step is also initialized to 20 in the top-level part of the code, and is still 20. With stepx positive and stepy negative, the first image begins to move northeastward; the rest of the beam bounces and follows the first image as the moveball( ) function continues to iterate.

Depending on the width and height of the viewport, the beam will move to the viewport's (a) top edge or (b) right edge.

var margintop = 0;
if ( < margintop) { // At the top edge
    stepy = (stepy + randommaker(2)) * -1; += 1; }
if ( > marginright) { // At the right edge
    stepx = (stepx + randommaker(2)) * -1; -= 1; }

(a) When the top edge of the beam's first image rises above the margintop, the beam bounces and then moves southeastward or southwestward, depending on whether stepx is positive or negative, respectively.

(b) When the left edge of the beam's first image moves to the right of the marginright (document.body.clientWidth-5), the beam bounces and then moves northwestward or southwestward, depending on whether stepy is negative or positive, respectively.

In due course the beam will move/bounce to the viewport's left edge.

var marginleft = 0;
if ( < marginleft) { // At the left edge
    stepx = (stepx + randommaker(2)) * -1; += 1; }

When the left edge of the beam moves to the left of the marginleft, the beam bounces and then moves southeastward or northeastward, depending on whether stepy is positive or negative, respectively.

The stepx/stepy blues

If we comment out the left-edge clause's rightward 1px posLeft shift - a shift that in theory should not be necessary - then it is possible for the beam's first image to be trapped at the left edge of the viewport and then move leftward, thereby dragging the beam out of sight; this results from the fact that the stepx = (stepx + randommaker(2)) * -1; statement can produce a new stepx whose absolute value is less than that of the old stepx - e.g., stepx can go from -20 to 19 - and it specifically occurs when || > |stepx|, which (in the absence of the posLeft shift) causes the < marginleft if condition to be true indefinitely, and thus the beam doesn't bounce.

If we comment out the other 1px posLeft/posTop shifts, an analogous phenomenon can occur at the viewport's top edge but not at its right or bottom edge; in the latter cases the new |stepx| or |stepy| is always greater than or equal to the old |stepx| or |stepy|, and therefore the relevant if condition is true for only one moveball( ) iteration and the beam bounces. Even with the left-edge and top-edge shifts in place, the first image can get stuck briefly at the viewport's left or top edge, but these shifts do prevent the beam from moving off-viewport.

A related issue: it is possible for |stepx| and |stepy| to creep upward (20-2121-2222 etc.) or downward (20-2019-1918 etc.) indefinitely - not good, needless to say.

A smoother trail

You may remember that we worked with a similar checkposition( ) function in Peter's floating images script; this function adjusted stepx and stepy in a simpler way that did not give rise to the aforedescribed problems. Consider its left-edge clause:

var marginleft = 0, floatingspeed = 5;
function randommaker(range) { return 1 + Math.floor((range - 1) * Math.random( )); }

if (thisspan.posLeft < marginleft) { // At the left edge
    thisspan.posLeft += Math.abs(stepx[i]);
    stepx[i] = randommaker(floatingspeed); }

The new stepx[i] is confined to a 1 to 4 range; similarly, the top edge's new stepy[i] is confined to a 1 to 4 range, the right edge's new stepx[i] is confined to a -1 to -4 range, and the bottom edge's new stepy[i] is confined to a -1 to -4 range. Significantly, the new stepx[i]/stepy[i] values are always positive or always negative, i.e., they can't switch back and forth between positive and negative as in the trailing images script, thereby eliminating any need for thisspan.posLeft/thisspan.posTop shifts.

Applying this approach to the trailing images script's checkposition( ) function

stepx = - (18 + randommaker(5)); // At the right edge
stepx = 18 + randommaker(5); // At the left edge
stepy = - (18 + randommaker(5)); // At the bottom edge
stepy = 18 + randommaker(5); // At the top edge

enables us to suppress stepx/stepy creep and get rid of the 1px posLeft/posTop shifts.


A more proactive approach to controlling the directionality of a bouncing image is offered by the Bounce All Around script of Lisha Sterling's "How to Create a JavaScript Animation" tutorial, which uses
(a) a dirx = 1 expression to dictate left-to-right movement,
(b) a dirx = 0 expression to dictate right-to-left movement,
(c) a diry = 1 expression to dictate up-to-down movement, and
(d) a diry = 0 expression to dictate down-to-up movement.

// Initial beam movement is rightward and downward
var dirx = 1;
var diry = 1;
if (diry && parseInt(document.getElementById("span0"), 10) > marginbottom) { // At the bottom edge
    // Vertical movement changes from downward to upward
    diry = 0;
    stepy = - (18 + randommaker(5)); }


Bounce, bounce, bounce...

The above demo parallels my floating images script demo in various ways, e.g., it discards the span+i span wrappers and directly works with the starry.gif images, it organizes the images as a trails array, it moves/bounces the images by writing and reading their style.left/ properties, etc. - see Blog Entry #279 (in particular its More retool section) for a fuller discussion of these features.

In the name of completeness

• The How do I make trailing images? subsection again includes a dead link to I am not able to give you an updated link because, as noted in the previous entry, Peter has not updated the trailing images script. I said last time that my attempt to find a trailing images script at came up empty-handed; the other day I went through the scripts at Peter's "Kostenlose DHTML und JavaScript Text Animationen" page and there wasn't anything there either.

• Lissa again instructs the reader to place the trailing images script's move/bounce code (the script element in the first textarea field) between the document head and the document body. Doing this violates the content model of the html element: place the code in the document head instead.

• Lissa's you can add or subtract images aside evidently pertains to the numberofimages setting (vis-à-vis composing the beam of different images). It is of course up to you to decide how large of a beam you want, although I would argue that the original numberofimages = 12 is the right number of images to use.

We have one last Peter Gehrig script at Lissa Explains It All to cover, that being Section 6's How do I block my document source? script, which we'll run through quickly in the next post.

Comments: Post a Comment

<< Home

Powered by Blogger

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