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.htm) 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 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:
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:
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.htm) 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 book.
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.htm) 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:
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.htm) 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:
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:
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 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:
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 book. |
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.htm) 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:
You should now understand how JavaScript works with images. Continue with one of the following:
I need to eliminate an image entirely, rather than changing its source. Is there a way to do this? | |
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. | |
I created a JavaScript program on a page with images, and my event handlers don't seem to be working. What's wrong? | |
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. | |
I'd like to create a clock using text instead of graphics. This should be easy, right? | |
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. |