reptile7's JavaScript blog
Wednesday, March 23, 2011
 
Elastic Ball, Everlastic Ball
Blog Entry #209

Today's post returns us to the topic of animation as we take up HTML Goodies' "How to Create a JavaScript Animation" tutorial, which was authored by Lisha Sterling and, like the last two tutorials we've analyzed, originally appeared at WebReference.com.

We were introduced to JavaScript animation by HTML Goodies' JavaScript Primers #28 ("Putting it all together: Animation"), which we covered in Blog Entry #45. Subsequently in Blog Entry #147 we discussed and demonstrated a Netscape "JavaScript animation" example in response to a comment on HTML Goodies' "So, You Want a SlideShow, Huh?" tutorial. Both of these occasions featured a script that automatedly fills a fixed img placeholder with a cyclic series of images.

In contrast, "How to Create a JavaScript Animation" addresses the automated translational movement of an image. The author draws an analogy between the tutorial's code and the stop-motion animation that underpins motion pictures and television, but I would argue that 'live action' is a better description of what we'll be doing as we really will be moving an img placeholder from point A to point B across the screen.

The tutorial's first page begins with some general remarks about animation and its translation to the Web, and then briefly discusses JavaScript's two tools for carrying out an automative process in a controlled manner (vis-à-vis the uncontrolled operation of a for/while loop):
(1) the setTimeout( ) method of the window object; and
(2) the setInterval( ) method of the window object.
We are quite well-versed in the setTimeout( ) method at this point (we used it in both of our prior animation excursions, e.g.) but have in fact never made use of the setInterval( ) method before; the tutorial's demos all employ the setInterval( ) method so perhaps we should chat about it a bit.

The setInterval( ) method invokes a function or line of code every time the specified amount of time passes, quoting Microsoft. There are two syntaxes for the setInterval( ) method; the syntax utilized by the tutorial code is:

var intervalID = window.setInterval(codeString, delay);
// We'll see the other syntax below.


The above command will execute the codeString every delay milliseconds; this repeating execution can be stopped by feeding the intervalID return to a window.clearInterval( ) command:

window.clearInterval(intervalID);

Contra the tutorial, intervalID is not an "object" but a low-value integer (0, 1, 2 ..., depending on the browser) that, interestingly, undergoes incrementation upon re-calling the original setInterval( ) command.

The setTimeout( ) method goes back to JavaScript 1.0, the first version of JavaScript; setInterval( ) is a later-generation method that (on the Netscape side) was implemented in JavaScript 1.2. According to irt.org, Microsoft support for setInterval( ) began with MSIE 4, so it's possible that Microsoft developed setInterval( ) before Netscape did. Specification-wise, the window object's various timer methods had a "DOM Level 0" status back in 2011 but they are now part of HTML5.

The tutorial's second and third pages provide code and accompanying demos for four related animations:
(1) Animation #1 moves a small image of a ball (ball.gif) horizontally from left to right indefinitely, i.e., the image's movement does not stop at the right edge of the viewport.
(2) Animation #2 moves the ball.gif image horizontally from right to left indefinitely.
(3) Animation #3 moves the ball.gif image horizontally from left to right and stops that movement at the right edge of the viewport.
(4) Animation #4 moves the ball.gif image in a diagonal, bouncing, stays-in-the-viewport, somewhat-speed-randomized manner that, the author notes at the end of the tutorial, is reminiscent of the motion of the ball in the classic Pong video game (play it here).

Unfortunately, the tutorial does not offer a code download package; however, the code for the first three animations is combined/externalized in a balls.js script. The ball.gif image is located here; alternatively, you can download it [A small orange ball] from me here and now (right-click on the ball and then choose the Save Image As... or equivalent command from the contextual menu that pops up). At no point does the tutorial detail the ball.gif image's underlying HTML - a crucial omission, as we'll see below.

Animation #1

(N.B. In following the tutorial's demo instructions, you will find it much easier to track the ball.gif image's position on the page if you keep your browser's "zoom level" at 100%, i.e., don't increase it from its default setting.)

Let me begin by giving you that underlying HTML as it appears in the source of the tutorial's second page (OK, I've tweaked it a bit):

<img id="ball1" src="/img/2007/11/ball.gif" alt=""
style="position: absolute; left: 200px; top: 390px; visibility: hidden;">


Initially hidden, the ball.gif image is visibilized by clicking the Click here link in the Making Things Move section's first paragraph

<a href="javascript:viewBall( );">Click here</a>

which calls the balls.js script's viewBall( ) function

function viewBall( ) {
    document.images["ball1"].style.visibility = "visible"; }


which switches the image's CSS visibility property to visible.

The now-visible ball.gif image (more specifically, its upper-left-hand corner) is situated 200px to the right of the document's left edge and 390px below the document's top edge. The tutorial's second page contains three anchors that when clicked vertically drop the image via a showmeBall( ) function

function showmeBall(yAxis) {
    document.images["ball1"].style.top = yAxis + "px"; }


to demo locations for Animations #1, #2, and #3, respectively.

Let's go to and click the first of these anchors, a Bring the Ball Here so we can see it... link

<a href="javascript:showmeBall('820');">Bring the Ball Here so we can see it...</a>
<!-- It's not necessary to quote the 820, which will be stringified when it's concatenated with the px unit identifier. -->


that increases the image's style.top value to 820px. To the right of the anchor is a Try it link

<a href="javascript:var t = window.setInterval('goRight( )', 80);">Try it</a>

that when clicked calls the Animation #1 goRight( ) function

function goRight( ) {
    document.images["ball1"].style.left = parseInt(document.images["ball1"].style.left) + 5 + "px"; }


which make[s] the ball move 5 pixels to the right every 80 milliseconds and whose code is given above the first anchor.

The author's discussion of goRight( )'s style.left-setting statement could definitely use some help.
But what's with the parseInt( ) around document.images["ball1"].style.left? The actual content of the variable document.images["ball1"].style.left is an object not a number, so we need to extract the number out of the object in order to perform a mathematical function on it. parseInt( ), as I'm sure you've guessed by now, parses the integer out of a variable.
document.images["ball1"].style.left is not an "object" but a reference expression for a CSS property. And when read or written dynamically, the values of all CSS properties, without exception, have a string data type - see the CSS2 Extended Interface section of the DOM Level 2 Style Specification.

The top-level parseInt( ) function acts on a string and will extract an integer from that string if and only if the integer appears at the beginning of the string, e.g., parseInt( ) will extract 200 from 200px but not from px200 (for which parseInt( ) would return NaN) - it does not generally extract an integer "out of" a string.
There's one more gotcha you should know about before we move on. In order to use the style position addresses to move an object around the window, you need to give the item an explicit style to start with. You can either declare that style in a CSS style sheet, in the HTML itself, or to declare starting style coordinates in your JavaScript.
Ouch! It is not true that the goRight( ) function would be able to read the image's style.left value if we were to set the image's position-related properties in a CSS style sheet:

#ball1 { position: absolute; left: 200px; top: 390px; }
/* However, we can set the initial visibility value in this way as we won't have to read that value later. */


See the Remarks section of Microsoft's style object page for more on this. On the other hand, we can indeed read these properties if we set them "in the HTML itself" (as is done above, and that's why the image HTML should be specified in the tutorial text) or if we set them JavaScriptically:

function positionBall( ) {
    document.getElementById("ball1").style.position = "absolute";
    document.getElementById("ball1").style.left = "200px";
    document.getElementById("ball1").style.top = "390px"; }
window.onload = positionBall;


In sum: We extract the integer at the beginning of the image's style.left setting (200px), add 5 to it, and tack on a px unit identifier to give an incremented style.left setting (205px), whose assignment to document.images["ball1"].style.left moves the image 5 pixels to the right; do this over and over again every 80 milliseconds and you have a 'go right' animation.

Additional comments

(1) For calling a function, the first setInterval( ) parameter can be specified as a function pointer (vis-à-vis a stringified function call), a syntax Mozilla recommends:

var t = window.setInterval(goRight, 80);

(2) In the goRight( ) function, the parseInt(document.images["ball1"].style.left) + 5 + "px" expression is interpreted left to right, so there's no need to parenthesize the arithmetic part thereof.

(3) I see that Mozilla now recommends that we always specify (emphasis in original) the parseInt( ) radix parameter to eliminate reader confusion and to guarantee predictable behavior. Different implementations produce different results when a radix is not specified.

document.images["ball1"].style.left = parseInt(document.images["ball1"].style.left, 10) + 5 + "px";

(4) A relatively positioned image works just as well and would have made it easier for the author to coordinate the animation demos with the tutorial text. Try it below - clicking the button will visibilize the ball.gif image with a position:relative;left:0px; 'style address'.




(I use push buttons for my interface elements as it rubs me the wrong way to use links for non-link purposes.)

Animation #2

The Making Things Move section also hosts Animation #2. Clicking the Animation #2 Bring the Ball Here... demo anchor drops the image to top:1420px; at the HTML Goodies version of the tutorial and to top:1220px; at the WebReference version of the tutorial. (Why the discrepancy? I have no idea.) Clicking the adjacent Go Left link moves the image 5 pixels to the left every 80 milliseconds via a goLeft( ) function that repeatedly subtracts 5px from document.images["ball1"].style.left:

function goLeft( ) { document.images["ball1"].style.left = (parseInt(document.images["ball1"].style.left) - 5) + "px"; }
/* The parentheses surrounding goLeft( )'s subtraction operation are unnecessary; the right side of the statement is again interpreted left to right. */


We'll go through Animations #3 and #4 in the following entry.

reptile7

Comments: Post a Comment

<< Home

Powered by Blogger

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