Chapter 12
Working with Graphics in JavaScript
CONTENTS
One of the most challenging-and most rewarding-uses of a programming
language is creating graphic applications and games. In this chapter
you'll look at some techniques you can use for graphic pages-or
to add excitement to any Web page.
Now don't get too excited-JavaScript is a young language, and
a simple one, so it will be quite a while before someone writes
a version of DOOM in JavaScript. However, you can create uniquely
dynamic Web content. JavaScript includes several features, including
dynamic images, that aren't even available in Java.
You will explore some simple examples of these techniques in this
chapter. For an example of a large-scale graphic application-in
this case, a poker solitaire game-see Chapter 15, "Real-Life
Examples III."
Let's start with an ultra-simple example of graphics in JavaScript.
In Chapter 5 "Accessing Window Elements as Objects,"
you used a simple JavaScript event handler to create back and
forward buttons, which enable the user to perform the same function
as the browser's arrow buttons. To improve on this idea, let's
make some spiffy-looking graphic buttons.
Listing 12.1 demonstrates this technique. Notice that there are
no script tags or event handlers-this is an example of calling
JavaScript through a URL, which you'll see more of in Chapter
14, "Debugging JavaScript Programs."
Netscape's view of this page is shown in Figure 12.1. This could
also be done with event handlers; as a matter of fact, the latest
versions of JavaScript enable you to include an event handler
directly within the <IMG>
tag, without making the image a link.
Figure 12.1 : Graphical back and forward buttons on a
Web page.
Listing 12.1. (GRBACK.asp) A simple example of graphic back
and forward buttons.
<HTML>
<HEAD><TITLE>Graphic Back and Forward Buttons</TITLE>
</HEAD>
<BODY>
<H1>Graphical Back and Forward Buttons</H1>
<HR>
This page allows you to go back or forward to pages in the history list.
These should be equivalent to the back and forward arrow buttons in the
browser's toolbar.
<HR>
<A HREF="javascript:history.back();">
<IMG BORDER = 0 SRC="left.gif">
</A>
<A HREF="javascript:history.forward();">
<IMG BORDER = 0 SRC="right.gif">
</A>
<HR>
</BODY>
</HTML>
Although this example works, it's nothing special. You can make
back buttons, forward buttons, and other graphics more interactive
by using dynamic images, described in the next section.
One of the most recent, and most exciting, features added to JavaScript
is the capability of dynamically changing images. This means you
can create images that "magically" change; this could
be used for clocks, images that change when you click them, or
even simple animations.
The images in a Web page are reflected in an array, just like
form elements. By modifying the properties of the array items,
you can replace the image with a different one. This enables you
to create dynamically changing content on the page without even
using frames.
This technique isn't perfect for all applications. Before you
get started, note the following limitations:
- You can only change existing images in the page-you can't
add new ones or remove an image entirely.
- You can replace an image with a larger or smaller image, but
this may not look good, because the text won't be reformatted
to match.
- Any image you use will have to be loaded from the server;
this makes this technique impractical for complicated animations
or large images.
You can change images dynamically by using the images
array. This array contains an item for each of the images defined
in the page. Each image can also have a name. In the object hierarchy,
each image object is a child
of the document object.
Each image object has the
following properties:
- border represents the
BORDER attribute of the <IMG>
tag; this defines whether a border is drawn around a linked image.
- complete is a flag that
tells you whether the image has been completely loaded. This is
a Boolean value (true or false).
- height and width
reflect the corresponding image attributes. This is for information
only; you can't change an image's size dynamically.
- hspace and vspace
represent the corresponding image attributes, which define the
image's placement on the page. Again, this is a read-only attribute.
- name is the image's name.
You can define this with the NAME
attribute in the image definition.
- lowsrc is the value of
the LOWSRC attribute. This
is a Netscape-specific attribute that enables you to specify a
low-resolution image to be loaded before the "real"
image.
- src is the image's source,
or URL. This is the value you can change to change images dynamically.
For most purposes, the src
attribute is the only one you'll use. However, you can also change
the lowsrc attribute. This
defines a low-resolution image to load first and will be used
only when you change the src
attribute.
The image object has no methods.
It does have three event handlers you can use:
- The onLoad event occurs
when the image finishes loading.
- The onAbort event occurs
if the user aborts the page before the image is loaded.
- The onError event occurs
if the image file is not found or is corrupt.
Although you can't add an image to the page dynamically, you can
create an independent image
object. This enables you to specify an image that will be loaded
and placed in the cache, but not displayed on the page.
This may sound useless, but it's a great way to work with modem-speed
connections. Once you've preloaded an image, you can replace any
of the images on the page with the image-and because it's already
cached, the change happens instantly.
You can cache an image by creating a new image
object, using the new keyword.
Here's an example:
Image2 = new Image();
Image2.src = "arrow1.gif";
Note |
The new keyword, and its other uses for object-oriented programming, are described in Chapter 4 "Using Built-In Objects and Custom Objects."
|
Here's a quick example to show off JavaScript's dynamic image
feature. The HTML document in Listing 12.2 includes five images;
these are some fancy pictures of numbers from one to five. By
using the selection lists and the GO button, you can place a different
image in any position. Figure 12.2 shows how the page looks after
a few changes.
Figure 12.2 : A page that enables you to change images
dynamically.
Listing 12.2. (NEWIMAGE.asp) An example of dynamic images.
<HTML>
<HEAD><TITLE>Image Changing Example</TITLE>
<SCRIPT>
//function to change an image's URL
//done "the long way" for clarity
function ChangeImg() {
// current position
x = parseInt(document.form1.pos.selectedIndex);
p = parseInt(document.form1.pos.options[x].value);
// new image value
x = document.form1.newimg.selectedIndex;
i = document.form1.newimg[x].value
// change the image URL
document.images[p].src = i + ".gif";
}
</SCRIPT>
</HEAD>
<BODY>
<H1>On-the-fly Image Changing</H1>
<hr>
The JavaScript functions on this page allow the images below to be replaced
without reloading the page.
<P>
Select the image position to change (numbers 0 through 4), and select the image
to place there (numbers 1 through 5). Then press the GO button to
replace the image. (Notice that since all 5 images were loaded and cached
when you loaded this page, the change happens VERY quickly.)
<HR>
<IMG SRC="1.gif" HEIGHT="80" WIDTH="80">
<IMG SRC="2.gif" HEIGHT="80" WIDTH="80">
<IMG SRC="3.gif" HEIGHT="80" WIDTH="80">
<IMG SRC="4.gif" HEIGHT="80" WIDTH="80">
<IMG SRC="5.gif" HEIGHT="80" WIDTH="80">
<HR>
<FORM name="form1">
<b>Position:</b>
<SELECT NAME="pos">
<OPTION VALUE="0">0
<OPTION VALUE="1">1
<OPTION VALUE="2">2
<OPTION VALUE="3">3
<OPTION VALUE="4">4
</SELECT>
<b>New Image:</b>
<SELECT NAME="newimg">
<OPTION VALUE="1">1
<OPTION VALUE="2">2
<OPTION VALUE="3">3
<OPTION VALUE="4">4
<OPTION VALUE="5">5
</SELECT>
<INPUT TYPE="button" VALUE="GO" onClick="ChangeImg();">
</FORM>
<HR>
</BODY>
</HTML>
The work of this program is done in the ChangeImg()
function. This function is called by the GO button. It reads the
current value of the selection lists; the first specifies the
image index to change, and the second specifies the new image
to place there.
Notice that the images change very quickly-almost instantly. This
is because all five of the images were already in the cache. If
you wish to use images that are not displayed at first, you can
preload them.
As a slightly more complex example, let's create a clock that
uses JavaScript to display the current time. There are many JavaScript
clocks out there on the Web, but this one is unique: using the
dynamic image features, it updates the time without reloading
the page or a frame.
The hardest part of this task is to create the images: the digits
zero through nine, a colon to separate the time, and a slash to
separate the date. You won't have to do this, because we've included
some appropriate images on the CD-ROM accompanying this guide.
Listing 12.3 shows the HTML and JavaScript source for the clock
program, and Netscape's view of it is shown in Figure 12.3.
Figure 12.3 : Netscape's output of the clock example.
Listing 12.3. (CLOCK.asp) A graphical clock with time and date.
<HTML>
<HEAD><TITLE>Yet Another Silly JavaScript Clock</TITLE>
<SCRIPT>
//javascript clock script
function Clock() {
D = new Date();
hh = D.getHours();
mm = D.getMinutes();
ss = D.getSeconds();
yy = D.getYear();
mt = D.getMonth() + 1;
dd = D.getDate();
// change the digit images
document.images[8].src = Url(hh/10);
document.images[9].src = Url(hh%10);
document.images[11].src = Url(mm/10);
document.images[12].src = Url(mm%10);
document.images[14].src = Url(ss/10);
document.images[15].src = Url(ss%10);
// time above, date below
document.images[0].src = Url(mt/10);
document.images[1].src = Url(mt%10);
document.images[3].src = Url(dd/10);
document.images[4].src = Url(dd%10);
document.images[6].src = Url(yy/10);
document.images[7].src = Url(yy%10);
// set timeout for next time (half second)
window.setTimeout("Clock()",500);
}
// converts 4 (numeric) to "c4.gif"
function Url(num) {
num = Math.floor(num);
return "c" + num + ".gif";
}
</SCRIPT>
</HEAD>
<BODY onLoad="window.setTimeout('Clock();',3000)">
<H1>A Graphical Clock in JavaScript</H1>
<hr>
This clock uses JavaScript's images[] array to update the time every half
second. It uses the current local time from the client computer. The images
below are dynamically replaced with the current time.
<HR>
<img src="c6.gif" HEIGHT=20 WIDTH=15><img src="c7.gif" HEIGHT=20 WIDTH=15>
<img src="slash.gif" HEIGHT=20 WIDTH=13><img src="c8.gif" HEIGHT=20 WIDTH=15>
<img src="c9.gif" HEIGHT=20 WIDTH=15><img src="slash.gif" HEIGHT=20 WIDTH=13>
<img src="c0.gif" HEIGHT=20 WIDTH=15><img src="c0.gif" HEIGHT=20 WIDTH=15>
<img src="c0.gif" HEIGHT=20 WIDTH=15><img src="c1.gif" HEIGHT=20 WIDTH=15>
<img src="colon.gif" HEIGHT=20 WIDTH=9><img src="c2.gif" HEIGHT=20 WIDTH=15>
<img src="c3.gif" HEIGHT=20 WIDTH=15><img src="colon.gif" HEIGHT=20 WIDTH=9>
<img src="c4.gif" HEIGHT=20 WIDTH=15><img src="c5.gif" HEIGHT=20 WIDTH=15>
<HR>
Note: The clock doesn't start updating until the page (including the images) loads.
The initial time and date value uses all 10 digits, so they will be cached for
fast updates.
<HR>
</BODY>
</HTML>
Let's take a look at how this program works:
- When the page first loads, the date and time are set to a
bogus value that includes all the digits-as you may have guessed,
this is so they'll all end up in the cache.
- An onLoad() event handler
is used in the document body to begin updating the time three
seconds after the page loads. This gives all the images time to
load.
- The Clock() function
does the actual work. This function is called by a timeout every
half-second, because there's no way to call it each time the time
changes. This function reads the current time and changes the
images in the document for each digit.
- An extra function, Url(),
converts numeric values to complete URLs for the image graphics.
If you've browsed the Web at all in the last year, I'm sure you
noticed the advertising banners at the top of many Web pages,
encouraging you to visit another page. Opinions are mixed about
Web advertising, but with the commercialization of the Web, it
was bound to happen.
At risk of making Web advertisements even more annoying (or more
exciting, depending on your attitude) here's another application
for dynamic images. You'll include an advertisement banner on
a page and use JavaScript to replace it every few seconds with
a new banner.
This could be used to display different banners, in the hope of
catching the user's eye. You could also use this technique to
rotate between different sponsors. This example uses JavaScript
to change the banners and also to link to the appropriate sponsor
when a banner is clicked.
For the moment, it simply displays a dialog indicating the appropriate
sponsor when the banner is clicked. The end result of this idea
is shown in Listing 12.4, and the output is shown in Figure 12.4.
Figure 12.4 : Netscape's output of the advertising banner
example.
Listing 12.4. (ADVERTS.asp) Using JavaScript to rotate advertisement
banners.
<HTML>
<HEAD>
<TITLE>Rotating Advertisements</TITLE>
</HEAD>
<SCRIPT LANGUAGE="JavaScript">
// global variable for current sponsor
var sponsor = 1;
// function to link to appropriate sponsor
// (for demonstration, displays a dialog instead)
function GoSponsor() {
window.alert("Sponsor number to link to:" + sponsor);
}
// function to rotate image (currently uses 3 images)
function rotate() {
if (++sponsor > 3) sponsor = 1;
document.images[0].src = "banner" + sponsor + ".gif";
window.setTimeout('rotate();',5000);
}
</SCRIPT>
<BODY onLoad="window.setTimeout('rotate();',5000);">
<h1>Rotating Advertisement Banners</h1>
<hr>
<A HREF="javascript:GoSponsor();">
<IMG NAME="banner" SRC="banner1.gif">
</A>
<hr>
The image above is being rotated between three different graphics. Clicking
on a banner will send you to the banner's corresponding sponsor. (For this
example, clicking will simply display a message in a dialog.)
<hr>
</BODY>
</HTML>
This program uses two functions:
- The rotate() function
switches to a new banner every five seconds. The sponsor
variable stores the current sponsor.
- The GoSponsor() function
is called when the banner is clicked. Currently, it displays a
dialog indicating the sponsor. In a real-world application, you
could use a series of if
statements to link to the appropriate sponsor by changing the
window.location value.
Tip |
You might be tempted to speed up the timer in this example and use it for animation. This will work, but only if you preload each image first. In addition, JavaScript animations aren't very fast. You may want to look into
GIF animations, which provide a good alternative. See appendix C, "Online JavaScript Resources," for more information
|
A common use for graphics on the Web is in image maps-large images
with clickable areas. Each area can link to a separate page. There
are two types of image maps:
- Server-side image maps
require a CGI script to interpret the user's actions.
- Client-side image maps
are embedded in HTML, and require no interaction with the server.
This is a newer standard and not officially part of HTML, but
it is supported by most browsers.
You may have already guessed that JavaScript can't work with server-side
image maps, because it has no link to the server. However, client-side
image maps and JavaScript work well together.
You can use client-side image maps with JavaScript in three ways:
- As with any link, you can link areas of the map to javascript:
method URLs to execute functions.
- Each <AREA> tag,
which defines a clickable area, can have event handlers: onMouseOver,
onMouseOut, and onClick.
These function in the same way as the corresponding link and image
event handlers.
- Each <AREA> tag
is reflected in an area object.
These objects are part of the links
array, and have the same properties.
As an example of using a client-side image map with JavaScript,
let's create a simple image map menu for a fictional company.
(The company's name isn't important, but it's obviously not a
graphic design company.)
To create a client-side map, you need to do two things:
- Use your favorite graphics application to create the actual
graphic as a GIF or JPEG image.
- Create a MP definition that describes areas in the image.
- Include the image in the document, using the USEMAP
attribute to point to the map definition.
Note |
Several shareware programs enable you to create image maps without hassle. One of them, Map This!, is included on the CD-ROM accompanying this guide.
|
Listing 12.5 shows the example client-side image map definition.
This uses both javascript:
links and event handlers to perform functions. Rather than link
to an actual page, clicking on the areas will display a message
in a text field (see Figure 12.5). In addition, the onMouseOver
event handlers display a description in the status line for each
area.
Figure 12.5 : An example of an image map in JavaScript.
Listing 12.5. (IMAGEMAP.asp) Using a client-side image map
with JavaScript.
<HTML>
<HEAD>
<TITLE>Image Map Example</TITLE>
<SCRIPT LANGUAGE="JavaScript">
function update(text) {
document.form1.text1.value = text;
}
</SCRIPT>
</HEAD>
<BODY>
<MAP NAME="map1">
<AREA SHAPE=RECT COORDS="14,15,151,87" HREF="javascript:update('service');"
onMouseOver="window.status='Service Department'; return true;">
<AREA SHAPE=RECT COORDS="162,16,283,85" HREF="javascript:update('sales');"
onMouseOver="window.status='Sales Department'; return true;">
<AREA SHAPE=RECT COORDS="294,15,388,87" HREF="javascript:update('info');"
onMouseOver="window.status='Information'; return true;">
<AREA SHAPE=RECT COORDS="13,98,79,178" HREF="javascript:update('email');"
onMouseOver="window.status='Email Us'; return true;">
<AREA SHAPE=RECT COORDS="92,97,223,177" HREF="javascript:update('products');"
onMouseOver="window.status='Products'; return true;">
<AREA SHAPE=RECT COORDS="235,98,388,177" HREF="javascript:update('our staff');"
onMouseOver="window.status='Our Staff'; return true;">
<AREA SHAPE=default HREF="javascript:update('No item selected.');"
onMouseOver="window.status='Please select an item.'; return true;">
</MAP>
<h1>Client-Side Image Map Example</h1>
<hr>
The image map below uses JavaScript functions in each of its areas. Moving over
an area will display information about it in the status line. Clicking on an area
places the name of the area in the text field below the image map.
<hr>
<IMG SRC="imagemap.gif" USEMAP="#map1">
<hr>
<FORM NAME="form1">
<b>Clicked Item:</b>
<INPUT TYPE="text" NAME="text1" VALUE="Please select an item.">
</FORM>
<hr>
</BODY>
</HTML>
This program uses a single JavaScript function called update();
this function simply places an item in the text field form1.text1.
The text is sent directly by the link in each area definition.
In this chapter, you explored several uses of JavaScript in working
with graphics, and you learned the following:
- How to create graphic back and forward buttons
- How to use the dynamic images technique to change images "on
the fly"
- Applications of dynamic images, including a clock and a method
for rotating advertisements
- How to use JavaScript with client-side image maps
You should now understand how JavaScript works with images. Continue
with one of the following:
- To review the rest of the objects in the object hierarchy,
see Chapter 5 "Accessing Window Elements as Objects."
- To add more multimedia features, such as sound and video,
see Chapter 13, "Working with Multimedia and Plug-Ins."
- To learn techniques for debugging JavaScript programs and
review the differences between browser versions, see Chapter 14,
"Debugging JavaScript Programs."
- For an example of a complete graphical application in JavaScript,
see Chapter 15, "Real-Life Examples III."
Q: | I need to eliminate an image entirely, rather than changing its source. Is there a way to do this?
|
A: | Not officially; you can't remove an image. However, you can replace it with a blank image of the same size, which should produce the same effect-and a one-color GIF is a very small
file. Remember, you can't do anything that would change the layout of the text.
|
Q: | I created a JavaScript program on a page with images, and my event handlers don't seem to be working. What's wrong?
|
A: | JavaScript requires you to use HEIGHT and WIDTH attributes on all IMG tags. Adding these will most likely make the event handlers work properly. See Chapter 14 for other debugging techniques.
|
Q: | I'd like to create a clock using text instead of graphics. This should be easy, right?
|
A: | It's easy, but only if you use a text field in a form. As for normal text in the page, there's no way to change it. You could keep the clock in a separate frame, though, and update
the entire frame. An example in Chapter 9 "Using Frames, Cookies, and Other Advanced Features," does exactly `hat.
|
|