Next page | Contents page |

Images & simple animation

It is only fairly recently, with HTML5, that JavaScript has become able to manipulate pixels, through the graphics context associated with the HTML <canvas> element. But from its earliest days it has been able to load and display images and animate them in a simple way.

HTML has an element for displaying images and here is an example, with its result.

  <img src="im/swan.jpg" width="300" height="450" alt="Photo of a swan">

The value of the src attribute is the path to the file, in this case in a subdirectory called im (for images). The width and height values are in pixels but we just give the numerical value. Width and height are optional attributes but if you don't tell the browser how much space to allow it can end up shuffling the page around as it loads which would be very irritating to the reader.

The width and height attributes should specify the actual size of the image in the file to avoid wasting resources on scaling to fit (wasting download time too if the image is really bigger than stated).

The alt attribute is also optional but it should be written because it enables speaking browsers to say what the element is about, for visually impaired users.

Animating with a set of images

So far we have used no JavaScript but what that can do is to change the image to provide some animation. Move your mouse around and see what happens to the next image.

15 photos of the bear have been taken carefully, on a tripod, so that the body does not move, only the head. They have all been cropped and scaled so that they are all the same size. The images are stored in files named ken1.jpg, ken2.jpg, ... ken15.jpg. A JavaScript function invoked in the usual way by the onload event then loads them all into an array in memory, as follows.

var ims = new Array (16);
var imgEl;

function start ()
  for (var j = 1; j <= 15; j++)
    ims [j] = new Image ();
    ims [j].src = "im/ken" + j + ".jpg";
  imgEl = document.getElementById ("kenni");
  imgEl.leftX = imgEl.offsetLeft;
  imgEl.rightX = imgEl.leftX + imgEl.width;
  imgEl.topY = imgEl.offsetTop;
  imgEl.bottomY = imgEl.topY + imgEl.height;
  document.addEventListener ("mousemove", handleMove, false);

In this case the image element in the HTML has the id "kenni" and the width and height to which all of the 15 image files have been scaled:

  <img id="kenni" style="margin-left:40%" src="im/ken8.jpg" width="150" height="150"/>

(ken8.jpg is the middle one of the sequence in which the head looks straight ahead, so that if JavaScript is disabled the image is a sensible one.)

The last line of the start () function above specified handleMove () as the function to be invoked whenever the mouse moves. That function must be responsible for replacing the image from the array depending on the direction of the mouse relative to the centre of the image. To achieve that we need the following JavaScript.

function getMousePoint (ev) // Caters for older browsers
  if (ev.pageX || ev.pageY) return { x: ev.pageX, y: ev.pageY }

  return { x: ev.clientX + document.body.scrollLeft + document.documentElement.scrollLeft,
           y: ev.clientY + document.body.scrollTop  + document.documentElement.scrollTop };

function handleMove (event)
  var pt = getMousePoint (event);
  var row, col;
  if (pt.x < imgEl.leftX - imgEl.width) col = 1;
  else if (pt.x < imgEl.leftX) col = 2;
  else if (pt.x > imgEl.rightX + imgEl.width) col = 5;
  else if (pt.x > imgEl.rightX) col = 4;
  else col = 3;  

  if (pt.y < imgEl.topY) row = 0;
  else if (pt.y > imgEl.topY + imgEl.height) row = 2;
  else row = 1;

  imgEl.src = ims [row * 5 + col].src;

Notice how properties leftX etc for imgEl have been invented so that their values could be calculated once in start () and then simply used in the handler. That is a principle worth remembering, though it is hardly essential here because there is little to calculate.

We then imagine the page as being a table of 3 rows each having 5 columns. The middle row, row 1, is the one containing the image. Whenever the mouse is above that the row number is 0 and so on. Similarly for the columns. The index number of the image required from the array is then easy to calculate. Note that the image is moved from memory, the original file does not have to be reloaded from disc (or downloaded again from a server in the more general case, which might be very time consuming).

And that is all we need for animating the image as the mouse moves. Enjoy making your own animations.

Next page | Contents page |