phpmapscript imagemap creation

Doug Williams williams at WEBSAWYER.COM
Wed Jul 4 02:32:49 EDT 2007


Rodrigo,

Here is what I did to make the imagemap work using phpmapscript.  This is my first go round trying 
to create an imagemap, so others may have more sensible methods or more extended methods, but I 
never did get any specific information from anyone, nor could I find any complete information about 
FORMATOPTIONs which would be very helpful!!.  I had to feel my way through trying to piece 
together bits and pieces of scattered information,  found luckily by google searching which turned 
up one interesting old message from the list from someone that also did not have it working.  I never 
did find any response to that person that showed a working example.  Anyhow, I have also not ever 
tried to describe this process so bear with my rambling, long-winded description.

First I added a OUTPUTFORMAT to my mapfile.  I already had one OUTPUTFORMAT in my mapfile to 
improve the quality of images generated by mapserver.  Whichever OUTPUTFORMAT comes first in 
the map file is used when generating images, unless the script resets this, which has to be done in 
order to generate both the imagemap (which is not an actual image, but just some html code) and 
the map (which is the actual visual image that is displayed).  It would be possible to use more than 
one mapfile rather than resetting the outputformat used, but it is not necessary.  More on 
outputformats in a minute.  Also it is necessary to define a CLASSITEM for the layer that you want to 
use to define your imagemap.  The classitem is the attribute that is stuffed into the html and 
displayed when the mouse is held over map polygons (in this example, a simple one layer example).  
The other important connection between the map file and the script is that the image shown in the 
html output has to be the same dimensions as the IMAGESIZE defined in the map file.  The other 
necessary steps take place in the php script.  So hear is the mapfile stuff:

 OUTPUTFORMAT
     NAME imagemap
     DRIVER imagemap
     FORMATOPTION "MAPNAME=map_test"
     FORMATOPTION "TITLE=''  # this gets stuffed properly, you do not need to reference anything
                                                       # on the right side of the = sign
                                                       # in fact, you do not need this option at all.  But maybe 
                                                       # someday you will?
     MIMETYPE "text/html"          # this option is also not needed!
  END

OUTPUTFORMAT
  NAME jpeg
  DRIVER "GD/JPEG"
  MIMETYPE "image/jpeg"
  IMAGEMODE RGB
  EXTENSION "jpg"
  FORMATOPTION "QUALITY=100"
END

The first output format is used to generate the imagemap, the second is used to generate the actual 
map.  The script resets the format that is used.  Show you that in a second.  I don't really think the 
mimetype statement is necessary, but I have seen it used so I include it here.  I myself will actually 
end up using the FORMATOPTIONs for mouseover and mouseout shown in my earlier message, but I 
am not going to go into how I am going to take good advantage of them here because it will 
apparently be necessary for me to do some additional coding to get the effect I want, which I find 
works much better (immediate response on the web page with more inclusive attribute data detail), 
but is more complicated programmatically... more scripting on the server side and a script on the 
client side as well which is not needed with this method.  I won't describe the second output format, 
but the first defines a reference name for the outputformat; the driver which tells mapserver what to 
generate in terms of output, in this case the html code defining the areas of the imagemap with the 
coords; the name of the generated <map>, you use this name when declaring the usemap; and the 
formatoption to add a title for each defined area of the imagemap which is stuffed with the attribute 
data from the shapefile specified by the layer classitem (not really needed).  (Don't formatoption 
suppress="yes", or you will not get the areas in your <map>.)

So hear is my layer definition in my map file:

    LAYER
      NAME "lakes"   # this is a bad layer example because the polygons are small and so
                                  # the imagemap driver generates some bad <map> areas.  I'll process these 
out.
                                  # Typically one would likely be using this with maps that produce
                                  # larger features than a few worldwide lakes that are being squished to mere 
dots
                                  # in an image the size and way I am doing here.
      DATA esri/world/lakes
      STATUS on
      TYPE polygon
      CLASSITEM "NAME"  # this is the attribute field to list in the 'title' for each <map> area
      CLASS
        NAME "Lakes"
        COLOR -1 -1 -1
        OUTLINECOLOR 200 200 50
      END
    END

Well, it is something like that anyway, but the important part is the CLASSITEM line, which tells the 
imagemap driver what information you want stuffed in the map area title.  Again, the title 
formatoption above is not even needed, the imagemap driver just stuffs the classitem values into the 
title for each area.  It would be much nicer if all the attributes were made available with a reference 
mechanism so that one would have to declare something like formatoption "TITLE=[NAME]" with a 
way to escape characters like quotes ... maybe that is coming in the future.

The map file will also have the SIZE defined, such as:
  SIZE 600 300
which we will use in the script to define the width and height of the image returned to the browser.

So those are the mapfile necessities.  Easy enough.

The php script is not so bad either.

If you have created and displayed a map, then you know how to create your map object for creating 
the actual map:
 $map_path="/path/to/mapfile/directory";
 $map_file="mapfile.map";
 $map = ms_newMapObj($map_path.$map_file);

You may want to create another map object to deal with the imagemap, though you could just use 
the same object.
 $imagemap = ms_newMapObj($map_path.$map_file);

I draw the imagemap first, and the imagemap driver is set first in my map file, so draw() is using that 
driver.  It will be necessary to change this to the jpeg outputformat before drawing the other map (or 
png or gif or whatever you may be doing):
 $htmlmap = $imagemap->draw();
 $htmlmap->saveImage("/path/to/someplace/the/script/can/write/test.html", $imagemap);

This will generate a text file on the server.
test.html will be the:
 <map name="map_test">
  with areas and coords and titles
 </map>

I use the php require() command to write this into the html that I return to the browser.

To change the ouputdriver use the phpmapscript command:
$map->selectOutputFormat("jpeg");
and draw as before:
 $image=$map->draw();
 $image_url=$image->saveWebImage(MS_PNG,1,1,0);
I have mixed jpeg and png here ... probably not what you want, png is better for vector/line type 
stuff, jpeg is better for more real world type images (in my understanding).

So now you have an image of your map as before, and you have the imagemap information in a file 
that was written to the server.  I add the imagemap to the html output like this:
 <body>
<? require "/path/to/somplace/the/script/can/write/test.html" ?>

I just plop it in right after I send the html <body> tag. Then you need to display the image in an 
<img> tag.  The standard mapserver way is to place the image in a form <input> tag, but I have not 
tried this as I read stuff stating that imagemaps do not work in form <input type=image> elements 
(makes sense since there is no place to associate the needed usemap).  Fortunately I had already 
moved away from displaying my images in those elements because I wanted to be able to click on 
the map without sending the form automatically.  Not using the form element means you will have to 
send the img.x and img.y coordinates that get sent automatically when using the form element by 
some other method, but that goes beyond the scope of this discussion.  

So display the image like this:
<img src=<? echo $image_url; ?> usemap="#map_test" width=<? echo $map->width; ?> height=<? 
echo $map->height; ?> border=0>

or however you like to code.  If things turn out correctly, when you place the cursor over a polygon 
and leave it still for a couple of seconds, the title will appear by the cursor showing you the attribute 
data.  View the page source to see if the <map> looks like what you expect it to look like.

Those are the basic pieces.  Sorry it is not a very well laid out description.  If you have any questions, 
feel free to ask.  I am using a slightly more recent version of mapserver, but believe this has been 
around a while.  If the mapserver folks would like, I would be willing to produce something more in 
line with some of the howtos.

Best,
Doug



More information about the mapserver-users mailing list