[GIS] How to add a simple interface to mapserver CGI application

guimapfilemapserver

I have a simple mapserver test page which shows information from shapefiles (cities, rivers, lakes, points of interest) etc. The result is a static PNG image. I want to add a simple interface so users would not have to modify the URL manually.

Options that I want to provide:

  • zoom in;
  • zoom out;
  • reset the map (back to default view with no zoom);
  • center map;
  • legend;
  • scalebar;
  • reference map;
  • show information about an object user clicked.

I know that map properties can be changed via URL but I am not sure about the way to do it. What I'm thinking is adding buttons in the template file and using javascript onClick events. When buttons are clicked, JavaScript redirects happen and additional parameters and parameter values are assigned to the URL.

I have read http://mapserver.org/cgi/ and this is what I have come up with.

In the example given below, button "Change map size" succesfully changes map dimensions to 800 by 400. I know that a full page reload happens, that is ok with me.

Is this the intended way of providing a simple GUI to a mapserver page? I want to stick to mapserver CGI, and not use PHP/Python mapserver API.

template.html:

<!-- MapServer Template -->
<html>
<head>
<title>Mapserver Template HTML Document</title>
<script type="text/javascript">
function zoomIn()
{
    console.log('zoomIn call');
}

function zoomOut()
{
    console.log('zoomOut call');
}

function reset()
{
    console.log('reset call');
    window.location.assign("http://localhost:1025/cgi-bin/mapserv.exe?map=C:/MS4W/ms4w/apps/gis/mapfile.map")
}

function switchRegionVisibility()
{
    console.log('switchRegionVisibility call');
    window.location.assign("http://localhost:1025/cgi-bin/mapserv.exe?map=C:/MS4W/ms4w/apps/gis/mapfile.map")
}

function changeMapSize()
{
    console.log('changeMapSize call');
    window.location.assign("http://localhost:1025/cgi-bin/mapserv.exe?map=C:/MS4W/ms4w/apps/gis/mapfile.map&map_size=800+400")
}
</script>
</head>
<body bgcolor=#AAAAAA>
<h2>Template</h2>
<img src="[img]" border=1>
<hr>
<input type="button" onclick="zoomIn()" value="+" id="zoomIn" />
<input type="button" onclick="zoomOut()" value="-" id="zoomOut" />
<input type="button" onclick="reset()" value="Reset" id="reset" />
<input type="button" onclick="switchRegionVisibility()" value="Disable regions" id="switchRegionVisibility" />
<input type="button" onclick="changeMapSize()" value="Change map size" id="changeMapSize" />
</body>
</html>

Best Answer

After a lot of trials and errors, I have come up with solution which has this functionality:

  • zoom in;
  • zoom out;
  • center map;
  • legend (embedded into map, check section LEGEND );
  • scalebar (embedded into map, check section SCALEBAR).
  • reference map (displayed nex to map, check section REFERENCE).
  • make persistent changes to map (for example, I click a button, layer x becomes hidden and stays hidden even when I keep zooming in/out of the map)

I also wanted to show information about an object user clicked. But that can only be achieved with MapServer WMS, but I'm only using MapServer CGI.

Tested on mapserver 6.0.3 (as part of MS4W package) and also 6.4.3 (as part of OSGeo4W package).

Below are contents of mapfile and template files. I tried to cut them down to make them easier to understand.

mapfile.map:

MAP
    NAME country_map
    STATUS ON
    SIZE 800 500

    EXTENT 313187.4 146161.56 766469.92 470367.64

    UNITS METERS
    SHAPEPATH "shapefiles"
    IMAGECOLOR 155 155 155

    SCALEBAR
        IMAGECOLOR 255 255 255
        LABEL
            COLOR 0 0 0 
            SIZE SMALL
        END
        SIZE 150 5
        COLOR 255 255 255
        BACKGROUNDCOLOR 0 0 0
        OUTLINECOLOR 0 0 0
        UNITS kilometers
        INTERVALS 5
        STATUS EMBED
    END   

    LEGEND
      STATUS EMBED
      POSITION UL
      KEYSIZE 18 12
      LABEL
        TYPE BITMAP
        SIZE MEDIUM
        COLOR 255 0 0
      END
    END

    REFERENCE
        IMAGE 'img/reference.png'
        SIZE 400 250
        EXTENT 313187.4 146161.56 766469.92 470367.64
        STATUS ON
        MINBOXSIZE 1
        MAXBOXSIZE 300
        COLOR -1 -1 -1
        OUTLINECOLOR 0 0 0
        MARKERSIZE 8
        MARKER 'star'
    END

    WEB
        TEMPLATE "template.html"
        IMAGEPATH "C:/MS4W/ms4w/Apache/htdocs/gis/output/"
        IMAGEURL "/gis/output/"
    END

# country background
    LAYER
    NAME "country_background_layer"
    DATA country_background_layer
    STATUS ON
    TYPE POLYGON
        CLASS
            NAME "Latvija" # shown in legend
            STYLE
                COLOR 0 255 0
            END
        END
    END 

# lakes
    LAYER
        NAME "lake_layer"
        DATA lake_layer
        STATUS ON
        TYPE POLYGON
        CLASS
            NAME "Lakes" # shown in legend
            STYLE
                COLOR 0 0 255
            END
        END
    END  

# cities
    LAYER
        NAME "city_layer"
        DATA city_layer
        STATUS ON
        TYPE POLYGON
        CLASS
            NAME "Cities" # shown in legend
            STYLE
                COLOR 255 0 0
            END
        END
    END  

END

template.html

<!-- MapServer Template -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/transitional.dtd">
<html  dir="ltr" lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>MapServer CGI</title>
</head>
<style>
#left
{
    padding: 3px;
    display: block;
    float: left;
}

#right
{
    padding: 3px;
    display: block;
    float: left;
}

p.title
{
    font-weight: bold;
    text-align: center;
    background-color: #ccc;
}

</style>
<body>
    <form method="GET" action="mapserv.exe">
        <input type="hidden" name="map" value="[map]">
        <input type="hidden" name="imgext" value="[mapext]">
        <input type="hidden" name="imgxy" value="149.5 199.5">
        <input type="hidden" name="program" value="[mapserv.exe]">
        <div id="container">
            <div id="left">
                <input type="image" name="img" src="[img]" style="border:1; border: 1px solid black; width:800; height:500">
            </div>

            <div id="right">

                <p class="title">Reference map:</p>
                <input type="image" name="ref" src="[ref]" border="0" />

                <p class="title">Zoom:</p>
                <select name="zoom" size="5">
                    <option value="3" [zoom_3_select]> Zoom in 3 times
                    <option value="2" [zoom_2_select]> Zoom in 2 times
                    <option value="1" [zoom_1_select]> Center map
                    <option value="-2" [zoom_-2_select]> Zoom out 2 times
                    <option value="-3" [zoom_-3_select]> Zoom out 3 times
                </select>

                <p class="title">Layers:</p>
                <table>
                    <tr>

                        <td>
                            <input type="checkbox" name="layer" id="country_background_layer" value="country_background_layer"[country_background_layer_check] />Country<br />
                        </td>

                        <td>
                            <input type="checkbox" name="layer" id="city_layer" value="city_layer"[city_layer_check] />Cities<br />
                        </td>

                        <td>
                            <input type="checkbox" name="layer" id="lake_layer" value="lake_layer"[lake_layer_check] />Lakes<br />
                        </td>
                    </tr>
                </table>
                <input type="submit" name="submit" value="Refresh">
            </div>
        </div>
    </form>
</body>
</html>
Related Question