You are here:   GIS Web Map Tutorial II > Map Tools
  |  Login

Map tools

  

Sometimes when we are working with maps on the web we need to do things like draw lines or polygons, add points, measure distances.   Let's start with the drawing since those really all fall into the same category.  We will start with our existing map code from the prior tutorial.  If you don't have that code please check out the tutorial pages Map Controls and Map Panel Layout.

To this code we will need to add four new global variables at the top of the script tag.  I placed mine under Demographics.  The first variable is vectors.  This will be a layer that will hold our vector drawings including points, lines and polygons.  You will see in the code that another layer is created for the actual drawing and once the drawing is complete it is moved to the vectors layer.  We don't have to write special code for that to happen but we do need to know that it does.

The next variable we will add is controls.  This will hold an object of the drawing controls we will be using which will be OpenLayers.Handler.Point, OpenLayers.Handler.Path, OpenLayers.Handler.Polygon, and for fun we'll also add a DragFeature control.

The next two variables are both style variables.  One will hole the style information for the points and the other will hold the info for lines and polygons.  Name these styleMapPoint and styleMapLines.  When you are done with that your global variables should look like this:

        var map;
        var Demographics;
        var vectors;
        var controls;
        var styleMapPoint;
        var styleMapLines;
        // Avoid pink error tiles
        OpenLayers.IMAGE_RELOAD_ATTEMPTS = 5;
        OpenLayers.Util.onImageLoadErrorColor = "transparent";

So now we can start defining our styles.  We'll do that directly under where we added our Demographics layer to the map.  The first thing we will do is tell OpenLayers to use the best render method allowed by the browser with the following code.

              // allow testing of specific renderers via "?renderer=Canvas", etc
               var renderer = OpenLayers.Util.getParameters(window.location.href).renderer;
               renderer = (renderer) ? [renderer] : OpenLayers.Layer.Vector.prototype.renderers;

Next we can define the styles.  The point style we will make the same color blue we had used for our side panel with a fill color of white.  We will give it a radius of 8 and a stroke width of 3.  The lines and polygons we want a little different.  We'll make them with a radius of 4, stroke of 2 and a fill opacity of 70%.  The colors we will leave the same.  You can of course change any of these to fit your needs.  You can even add an externalGraphic property and point to an image.  We won't do that today but here is the code for the styles.

               styleMapPoint = new OpenLayers.StyleMap({
                    'pointRadius': 8,
                    'strokeWidth': 3,
                    'strokeColor': '#164667',
                    'fillColor' : '#ffffff'


                });
                styleMapLines = new OpenLayers.StyleMap({
                    'pointRadius': 4,
                    'strokeWidth': 2,
                    'strokeColor': '#164667',
                    'fillColor': '#ffffff',
                    'fillOpacity': 0.7


                });

Now that we have the styles created we can create the layer.  We will call it Vector Layer, but you may choose to call it something/anything else when you build your applications later.  Notice we are passing in the renderer and the style map we just made.  We are passing in the point one to begin but it really doesn't matter which one you start with.

               vectors = new OpenLayers.Layer.Vector("Vector Layer", {
                   renderers: renderer, styleMap: styleMapPoint
               });


               map.addLayer(vectors);

Ok now we're making progress!  The controls are next.  First we have to create them in the object then add them to the map which we will do in a for loop.

              controls = {
                   point: new OpenLayers.Control.DrawFeature(vectors,
                                OpenLayers.Handler.Point),
                   line: new OpenLayers.Control.DrawFeature(vectors,
                                OpenLayers.Handler.Path),
                   polygon: new OpenLayers.Control.DrawFeature(vectors,
                                OpenLayers.Handler.Polygon),
                   drag: new OpenLayers.Control.DragFeature(vectors)
               };


               for (var key in controls)
               {
                   map.addControl(controls[key]);
               }

Now we just need a way to switch between the tools.  We can make a function called toggleControl which we will pass in which control we want active.  This function will be placed after our initialize functions code block closes.  We will need to check which control is being asked for then activate it and change the style.  Because we know that OpenLayers places the drawing layer at the end of the array of layers we will change the style of that drawing layer.  If there is no match we will deactivate the control.

function toggleControl(which)
        {
           
            for (key in controls)
            {
                var control = controls[key];
               
                if (which == key)
                {
                    control.activate();
                    if (which == 'line' || which == 'polygon')
                    {
                        map.layers[map.layers.length - 1].styleMap = styleMapLines;
                    }
                    else if (which == 'point')
                    {
                        map.layers[map.layers.length - 1].styleMap = styleMapPoint;
                    }
                } else
                {
                    control.deactivate();
                }  
            }
        }

Perfect!  Now we just need to hook buttons to the function.  I will just use plain input buttons for now, we can fancy them up some other time.  Let's drop them in our side panel at the bottom. 

                <br />
                <br />
                <input type="button" onclick="toggleControl('point')" value="Create Point" style="width:150px;" /><br />
                <input type="button" onclick="toggleControl('line')" value="Create Line" style="width:150px;"/><br />
                <input type="button" onclick="toggleControl('polygon')" value="Create Polygon" style="width:150px;"/><br />
                <input type="button" onclick="toggleControl('drag')" value="Drag Feature" style="width:150px;"/><br />
                <input type="button" onclick="toggleControl('')" value="Navigate" style="width:150px;"/><br />

You can save your map and check it out.  It should look like http://giswebmapclass.freevar.com/GISII5.html Your complete code should look like mine below.

<html>
<head>
    <script src="http://openlayers.org/api/OpenLayers.js" type="text/javascript"></script>
    <style type="text/css">
        html
        {
            height: 100%;
        }
        body
        {
            height: 100%;
            margin: 0px;
            padding: 0px;
        }
        #map_canvas
        {
            height: 100%;
            float: left;
            width: 75%;
        }
        .olcontrolattribution
        {
            bottom: 10px !important;
        }
        #mapinfo
        {
            float: left;
            width: 25%;
            height: 100%;
            background-color: #164667;
            overflow: auto;
            color: White;
        }
        #innerMapinfo
        {
            margin: 5px;
        }
    </style>
    <script type="text/javascript">
        var map;
        var Demographics;
        var vectors;
        var controls;
        var styleMapPoint;
        var styleMapLines;
        // Avoid pink error tiles
        OpenLayers.IMAGE_RELOAD_ATTEMPTS = 5;
        OpenLayers.Util.onImageLoadErrorColor = "transparent";
        function initialize()
        {
            map = new OpenLayers.Map("map_canvas", {
                controls: [
                        new OpenLayers.Control.Navigation(),
                        new OpenLayers.Control.PanZoomBar(),
                        new OpenLayers.Control.LayerSwitcher({ 'ascending': false }),
                        new OpenLayers.Control.Permalink(),
                        new OpenLayers.Control.ScaleLine({ displaySystem: 'english', divisions: 2 }),
                        new OpenLayers.Control.Permalink('permalink'),
                        new OpenLayers.Control.MousePosition(),
                        new OpenLayers.Control.OverviewMap(),
                        new OpenLayers.Control.KeyboardDefaults()
                    ]
            });
            var mapbase = new OpenLayers.Layer.ArcGIS93Rest("ArcGIS Server Layer",
           "http://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/export",
           { layers: "show:0", dpi: 96, FORMAT: "png24" }, { attribution: "Sources: Esri, DeLorme, NAVTEQ, TomTom, USGS, Intermap, iPC, NRCAN, Esri Japan, METI, Esri China (Hong Kong), Esri (Thailand)" });
            map.addLayer(mapbase);
            Demographics = new OpenLayers.Layer.ArcGIS93Rest("USA Median Net Worth",
               "http://server.arcgisonline.com/ArcGIS/rest/services/Demographics/USA_Median_Net_Worth/MapServer/export",
               { layers: "show:3",
                   transparent: true
               }, { isBaseLayer: false, opacity: .5 });
               map.addLayer(Demographics);




               // allow testing of specific renderers via "?renderer=Canvas", etc
               var renderer = OpenLayers.Util.getParameters(window.location.href).renderer;
               renderer = (renderer) ? [renderer] : OpenLayers.Layer.Vector.prototype.renderers;
               styleMapPoint = new OpenLayers.StyleMap({
                    'pointRadius': 8,
                    'strokeWidth': 3,
                    'strokeColor': '#164667',
                    'fillColor' : '#ffffff'


                });
                styleMapLines = new OpenLayers.StyleMap({
                    'pointRadius': 4,
                    'strokeWidth': 2,
                    'strokeColor': '#164667',
                    'fillColor': '#ffffff',
                    'fillOpacity': 0.7


                });
               vectors = new OpenLayers.Layer.Vector("Vector Layer", {
                   renderers: renderer, styleMap: styleMapPoint
               });


               map.addLayer(vectors);
               controls = {
                   point: new OpenLayers.Control.DrawFeature(vectors,
                                OpenLayers.Handler.Point),
                   line: new OpenLayers.Control.DrawFeature(vectors,
                                OpenLayers.Handler.Path),
                   polygon: new OpenLayers.Control.DrawFeature(vectors,
                                OpenLayers.Handler.Polygon),
                   drag: new OpenLayers.Control.DragFeature(vectors)
               };


               for (var key in controls)
               {
                   map.addControl(controls[key]);
               }
            map.setCenter(new OpenLayers.LonLat(-86.57, 34.65), 12);


        }
        function toggleControl(which)
        {
           
            for (key in controls)
            {
                var control = controls[key];
               
                if (which == key)
                {
                    control.activate();
                    if (which == 'line' || which == 'polygon')
                    {
                        map.layers[map.layers.length - 1].styleMap = styleMapLines;
                    }
                    else if (which == 'point')
                    {
                        map.layers[map.layers.length - 1].styleMap = styleMapPoint;
                    }
                } else
                {
                    control.deactivate();
                }  
            }
        }
    </script>
    <title>USA Median Net Worth</title>
</head>
<body onload="initialize()">
    <img src="/imapapps/portals/0/images/northArrow.png" style="position: absolute; right: 10px; bottom: 200px;
        z-index: 9001;" alt="North Arrow"/>
    <div id="mapinfo">
        <div id="innerMapinfo">
            <h3>
                USA Median Net Worth</h3>
            <p style="margin: 0px 5px 0px 5px;">
                This thematic map presents the median household net worth in the United States in
                2010. Net worth is total household wealth minus debt, secured and unsecured. Net
                worth includes home equity, equity in pension plans, net equity in vehicles, IRAs
                and Keogh accounts, business equity, interest-earning assets and mutual fund shares,
                stocks, etc. Examples of secured debt include home mortgages and vehicle loans;
                examples of unsecured debt include credit card debt, certain bank loans, and other
                outstanding bills. Forecasts of net worth are based on the Survey of Consumer Finances,
                Federal Reserve Board. These data are ESRI’s 2010 estimates. The geography depicts
                states at greater than 25m scale, counties at 1m to 25m scale, Census Tracts at
                250k to 1m scale, and Census Block Groups at less than 250k scale. The map is designed
                to be displayed with semi-transparency of about 50% for overlay on other basemaps,
                which is reflected in the legend for the map.
                <center>
                    <img src="/imapapps/portals/0/images/legend.png" alt="Legend" />
                </center>
                <br />
                Created by: BillyZ
                <br />
                <br />
                <input type="button" onclick="toggleControl('point')" value="Create Point" style="width:150px;" /><br />
                <input type="button" onclick="toggleControl('line')" value="Create Line" style="width:150px;"/><br />
                <input type="button" onclick="toggleControl('polygon')" value="Create Polygon" style="width:150px;"/><br />
                <input type="button" onclick="toggleControl('drag')" value="Drag Feature" style="width:150px;"/><br />
                <input type="button" onclick="toggleControl('')" value="Navigate" style="width:150px;"/><br />
            </p>
        </div>
    </div>
    <div id="map_canvas">
    </div>
</body>
</html>