Semi-transparent image overlays #

One of my goals on the online campus map project has been to leverage the capabilities of modern browsers as much as possible. With 95%+ of visitors using "modern" browsers (i.e. MSIE 5.5+, Mozilla, Safari, Opera), it makes no sense to design for what used to be the lowest common denominator in the previous design (Netscape 2.0, I kid you not). This doesn't mean going crazy with DHTML and JavaScript, but if a bit of client-side code can save us a server round-trip and boost interactivity, then why not.

When the user picks a building from the drop down (development site), we want to highlight the building that was picked (so that when the user is led to its page with the zoomed-in map, they know roughly where they are). The current system generates images with crosshairs on the building on the fly (cached for later use) and sends the client that. Not only does this necessitate an extra CGI request, but making a whole new image each time is a bit much.

The solution I have implemented is to pre-generate a set of overlays, one per building, with a crosshair in the right place in an otherwise empty, transparent image. To actually put the overlay on top the image, we use the following set of nested <div>s:

<div id="imageMapContainer" style="width: 800px; height: 700px; position: absolute;">
  <img src="imagemap.png" usemap="#campusmap" id="imageMap" alt="Campus Map" width="800" height="700" />
  <div id="overlay" style="display: none; width: 800px; height: 700px; position: absolute; top: 0; left: 0;" >
    <img src="images/blank.gif" usemap="#campusmap" id="overlayImage" alt="Overlay" width="800" height="700" />
  </div>
</div>

(I have inlined the styles to make it apparent what's going on). The basic idea is to have a div of the exact same size on top of the image, an effect accomplished by using absolute positioning relative to the imageMapContainer <div>. One thing to note is that the overlay uses the same client-side image map as the regular image, since when it is being displayed clicks do not go through even a mostly transparent image. The overlay image's src attribute is initially set to a completely transparent image of the spacer.gif variety for reasons that will become clear shortly.

  var overlay = document.getElementById("overlay");
  var overlayImage = document.getElementById("overlayImage");
  var overlayImageSrc = "buildings/" + buildingID + "overlay.png";
					
  overlay.style.display = 'block';

  // MSIE 5.x/6.x must be treated specially in order to make them use the PNG alpha channel
  if (overlayImage.runtimeStyle)
    overlayImage.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" +
                                       overlayImageSrc +
                                       "', sizingMethod='scale')";
  else
    overlayImage.src = overlayImageSrc;

As it can be seen, the code for swapping in an overlay image is relatively straightforward. The only trick is that we have to special-case MSIE since it doesn't support PNG alpha in a normal fashion. The AlphaImageLoader filter is applied behind the regular image loaded by the <img> tag, which is why we need the completely transparent GIF in the first place. Using the presence of the runtimeStyle property as a way of detecting MSIE seems like a safe bet, since that is a proprietary extension unlikely to be added to any other browser. As a side note, I'm using PNG despite the gamma annoyance since it's what J2SE 1.4.2 can generate out of the box, and because anti-aliased transparent edges are nice. I envy those who can live in the future, browser-wise.

Post a Comment