The previous section illustrated the use of polygons by adding two simple polygons to the map. However, the polygons provided no extra functionality, and were both shaded in the same way. By shading polygons in different colours, we can add thematic meaning to the map, as we did with differential shading of lines. We can also present further information by adding information to be included on a pop-up window. The following listing shows the code of a revised polygon example; this uses the same data file as the previous example (here's the associated files: poly_eg2.html; poly_eg1_data.js).
Code for poly_eg2_setup.js
var map; // The map object
var myPoly;
var myCentreLat = 53.81;
var myCentreLng = -1.52;
var initialZoom = 12;
function infoCallback(infowindow) {
return function() {
infowindow.open(map);
};
}
/*
* addPoly
*/
function addPoly(polyPath,myInfo,line_colour,fill_colour) {
/*
* Construct the polygon
*/
myPoly = new google.maps.Polygon({
paths: polyPath,
strokeColor: line_colour,
strokeOpacity: 0.8,
strokeWeight: 3,
fillColor: fill_colour,
fillOpacity: 0.35
});
var infowindow = new google.maps.InfoWindow({
content: myInfo,
position: polyPath[0]
});
google.maps.event.addListener(myPoly,
'click', infoCallback(infowindow));
myPoly.setMap(map);
}
function initialize() {
var myCentre =
new google.maps.LatLng(myCentreLat,myCentreLng);
var myOptions = {
zoom: initialZoom,
center: myCentre,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(
document.getElementById("map_canvas"),myOptions);
for (id in os_polydata) {
var polyPath = []; // An empty array
/*
* Read through points
*/
var thisBoundary = os_polydata[id].boundary;
for (pt in thisBoundary) {
var osPt = new OSRef(thisBoundary[pt].easting,
thisBoundary[pt].northing);
var llPt = osPt.toLatLng(osPt);
llPt.OSGB36ToWGS84();
var myLatLng = new google.maps.LatLng(llPt.lat,llPt.lng);
polyPath.push(myLatLng);
}
var fillShade = 256*(os_polydata[id].value/100);
var fillShadeHex = parseInt(fillShade).toString(16);
var fillColour = '#'+fillShadeHex+fillShadeHex+fillShadeHex;
var info = "<div><h1>" + os_polydata[id].title +
"</h1><p>" + os_polydata[id].description +
"</p></div>";
addPoly(polyPath,info,"#000000",fillColour);
}
}
This example adds a function for adding polygons to the map that is similar
to the function used to add multiple markers. The function is called addPoly()
,
and it takes as its parameters an array of LatLng
points
(polyPath
), some text to be used for an infowindow, a line colour
and a fill colour. Again, we have to use a callback function to make sure that
we get distinct infowindows for each polygon, however the function used is
slightly different to that used in the markers example (and thus should really
have been given a different name!). Infowindows can be attached to markers, or
to any given LatLng
point on the map; they cannot be attached in a general
manner to a polygon: we have to say where we want them to pop up.
We can do this by setting the position
parameter of the
infowindow object.
var infowindow = new google.maps.InfoWindow({
content: myInfo,
position: polyPath[0]
});
Here we have used the first point in our polygon
(polyPath[0]
), although a more appealing placement would probably
require us to iterate through all points and calculate a centroid. Given that
the position is set, we do not need to supply a marker reference to the
callback function.
google.maps.event.addListener(myPoly,
'click', infoCallback(infowindow));
The setup file also illustrates the dynamic generation of a fill shade from
a value read from the data file (in this case,
os_polydata[id].value
).
var fillShade = 256*(os_polydata[id].value/100);
var fillShadeHex = parseInt(fillShade).toString(16);
var fillColour = '#'+fillShadeHex+fillShadeHex+fillShadeHex;
First , we convert the value into a number
between 0 and 256. The example above assumes that all values are in the range 0
to 100. We then convert this to a hexadecimal number: we use the builtin
JavaScript function parseInt()
to convert fillShade
to an integer, and then run the method toString(16)
on the result
of parseInt()
. The method toString()
converts a
number to a string. It can take an optional radix (base) value as a parameter;
hexadecimal is base 16, so using toString(16) converts a numeric value to a
string containing a hexadecimal version of that number. Finally, we construct a
string called fillColour as a standard Google Maps colour reference: a '#
' plus
three hex values for red, green and blue (hex numbers are often preceded by a '#
'). Here we have used the same value for
red, green and blue, so we will get a variable shade of grey.
Having calculated a fill colour, we call our addPoly()
function for each
polygon.
The code in the figure above is relatively simple – it creates only shades of grey,
and as mentioned, it assumes that the attribute term will vary between 0 and
100.Some basic error correction for values outside this range is included.
The variable fillValue
is used as a
term to determine the shading level, and is intially set as a copy of the raw
data value. If this value is less than 0 or greater than 100, it is modified
to be 0 or 100 respectively. However, a better approach would be to have a
preparatory loop that reads through the data file and determines the range of
the shading variable, and then sets the shading accordingly.
The above example used two polygons only. It is possible to add more polygons, and also possible to add much more complex polygons than simple squares. Look at the listing below; it contains extracts from a larger data file, that contains boundary definitions for five wards in central and north Leeds. It is loaded by an HTML and map setup file that are identical to those used in the previous example apart from a) the designation of the appropriate data file and b) the initial zoom level specified (poly_eg3.html; poly_eg3_setup.js).
Extract of code from poly_eg3_data.js
var os_polydata = [{
'title': 'Kirkstall',
'description': '08DAFR',
'value': 27,
'boundary': [
{'easting':424937.406702199,'northing': 437355.594025358},
{'easting':425253.500142493,'northing': 437616.812329601},
{'easting':425343.187182577,'northing': 437517.593897509},
{'easting':425753.812206959,'northing': 437609.499945594},
{'easting':426193.406191368,'northing': 437497.90647349},
{'easting':426149.000431327,'northing': 437284.687145292},
{'easting':426434.000111593,'northing': 436914.812200947},
{'easting':426354.499823518,'northing': 436667.999528717},
{'easting':426469.593327626,'northing': 436420.281640487},
{'easting':426607.312111754,'northing': 436494.812456556},
{'easting':426763.000047899,'northing': 436317.593896391},
{'easting':427104.000240217,'northing': 436471.312680534},
{'easting':427125.687536237,'northing': 436375.312680445},
{'easting':427039.812848157,'northing': 436340.687144413},
{'easting':427186.000112293,'northing': 436297.499944372},
{'easting':427056.906480173,'northing': 436077.094184167},
{'easting':427119.687920231,'northing': 435708.093735823},
{'easting':427820.687600884,'northing': 435260.500263407},
{'easting':428024.592625074,'northing': 434796.093734974},
{'easting':428505.687281522,'northing': 434549.687590744},
{'easting':428096.906481141,'northing': 434024.187174255},
{'easting':427612.593392690,'northing': 434195.312934414},
{'easting':427315.093744413,'northing': 434180.687142401},
{'easting':427323.906288421,'northing': 434343.187750552},
{'easting':427155.999984265,'northing': 434714.500390898},
{'easting':426998.499568118,'northing': 434630.40643882},
{'easting':426748.812527886,'northing': 434694.593830879},
{'easting':426432.844015591,'northing': 435168.656679321},
{'easting':426276.312303446,'northing': 435118.312743274},
{'easting':426101.093615282,'northing': 435268.406567414},
{'easting':425949.781231142,'northing': 435610.500391732},
{'easting':426075.812079259,'northing': 435800.499495909},
{'easting':426049.687791235,'northing': 435984.687400081},
{'easting':425899.312367095,'northing': 436006.593832101},
{'easting':425253.812462493,'northing': 436409.000232476},
{'easting':424902.094062166,'northing': 436409.093416476},
{'easting':424774.906094047,'northing': 436665.499944715},
{'easting':424453.312749748,'northing': 436835.093800873},
{'easting':424557.812973845,'northing': 437049.499945073},
{'easting':424937.406702199,'northing': 437355.594025358}]
},
{
'title': 'Weetwood',
'description': '08DAGG',
'value': 12,
'boundary': [
{'easting':428588.310769599,'northing': 436488.17488855},
{'easting':427825.078512888,'northing': 436514.798888575},
{'easting':427480.093936567,'northing': 436298.187048373},
{'easting':427080.406256195,'northing': 436298.687784373},
{'easting':427104.000240217,'northing': 436471.312680534},
{'easting':426763.000047899,'northing': 436317.593896391},
{'easting':426607.312111754,'northing': 436494.812456556},
{'easting':426500.312303654,'northing': 436394.500392462},
{'easting':426354.499823518,'northing': 436667.999528717},
{'easting':426434.000111593,'northing': 436914.812200947},
//...
{'easting':428943.187185929,'northing': 435455.312167588},
{'easting':428573.898993585,'northing': 434715.399462899}]
}
]
The co-ordinates were derived in a fairly lengthy manual manner: the polygon
data were derived from a set of polygon boundaries downloaded from UKBorders (although fortunately, there
are easier ways than this of converting polygon data). The MIF file format
available from UKBorders presents
the polygons as a series of easting, northing pairs, with one pair per
line. For a relatively small set of wards such as this, it was possible to
edit the resulting file manually, to prefix each line with "{'easting':
"
and to add other bits of text
as required. However, this is time consuming and is clearly not a suitable
approach for larger amounts of data. The other properties (the title,
description, and fill colour) was added manually for each polygon. Here's what the data looks like:
For the sake of simplicity, the polygons have been shaded in various intensities of grey. It would of course be quite easy to work out different red, green and blue values, in order to use colours.
Whilst polygons are useful, there are limits on how many can be added to a map before it becomes unwieldy (slow to load and respond to clicks).