In this recipe we will show how to fill different regions of a map with different colors. We will use the PolygonParser
class from the previous recipe in order to get the geographical boundaries of the Canadian provinces and we are going to combine it with the crime severity index data from Statistics Canada available at http://www.statcan.gc.ca/pub/85-004-x/2009001/t009-eng.htm. Provinces with a darker gray (more red color in the code), will have higher crime severity index while provinces that are of a lighter gray color (more yellow in the code) will have lower crime severity index. This is illustrated in the following screenshot:
This recipe greatly relies on the Parsing data to use as region fill recipe; we suggest you read it before continuing.
The following steps show you how to color a map:
CrimeData
class that has a name, a crime severity index, and a boundaries propertydata.push(new CrimeData("Prince Edward Island", 62.8, '{"type":"Polygon","coordinates":[[[-63.811,46.469],[-63.784,46.455],[-63.737,46.48],[-63.681,46.562],[-63.534,46.541],[-63.456,46.504],[-63.413,46.512],[-63.369,46.508],[-63.286,46.46],[-63.129,46.422],[-62.964,46.428],[-62.712,46.45],[-62.682,46.459],[-62.423,46.478],[-62.164,46.487],[-62.074,46.466],[-62.041,46.446],[-62.024,46.422],[-62.172,46.355],[-62.32,46.278],[-62.526,46.203],[-62.552,46.166],[-62.539,46.098],[-62.543,46.029],[-62.503,46.023]...));
_map = new Map(); _map.size = new Size(1000, 500); _map.center = new Location(-95.11, 52.57, "EPSG:4326"); _map.resolution = new Resolution(10000, "EPSG:900913"); var bing:Bing = new Bing("Ar3-LKk-acyISMevsF2bqH70h21mzr_FN9AhHfi7pS26F5hMH1DmpI7PBK1VCLBk","Aerial"); _map.addLayer(bing);
scaleRatio
value that will be used to determine the color of a region.for (i = 0; i < data.length; i++) { polygonVector = PolygonParser.parseData(data[i].boundaries); for (j = 0; j < polygonVector.length; j++) { polygonFeature = new PolygonFeature(polygonVector[j]); rule = new Rule(); green = 240 - Math.round((data[i].crimeSeverityIndex - minValue) * scalingFactor); color = (red << 16) | (green << 8) | blue; fill = new SolidFill(color, .8); stroke = new Stroke(0xffffff, 2); symbolizer = new PolygonSymbolizer(fill, stroke); rule.symbolizers.push(symbolizer); style = new Style(); style.rules.push(rule); polygonFeature.style = style; polygonFeature.addEventListener(MouseEvent.ROLL_OVER, _onFeatureOver); _polygonVector.push(polygonFeature); _crimeDataVector.push(data[i]); regionLayer.addFeature(polygonFeature); } }
HoveringLabel.as
, so that when a user rolls over a region we can display information about it.TitleSprite
, to indicate what our map is about.private function _onFeatureOver(event:MouseEvent):void { _hoveringLabel.x = mouseX - 75; _hoveringLabel.y = mouseY; _hoveringLabel.changeText( _crimeDataVector[_polygonVector.indexOf(event.target)].name, _crimeDataVector[_polygonVector.indexOf(event.target)].crimeSeverityIndex); }
A big part of the work was done in the previous recipe and we will re-use the PolygonParser
class to get the boundaries of every province in Canada. The parsing process returns a Polygon
instance, but in order to use it, we need to encapsulate it inside a PolygonFeature
class so that we can add it to the VectorLayer
class.
Let's take this moment to look in how many classes our data is encapsulated in. First we put it in a LinearRing
class, then a Polygon
class, then a PolygonFeature
class, then a VectorLayer
class, and finally into a Map
class. It's quite a long process, but it is not that difficult once you know it.
Now we need to calculate our scalingFactor
value. To do so we need to find our minimum and maximum crime severity index . Here is how we do it:
var scalingFactor:Number = 240 / (maxValue – minValue);
The 240
value is the range over which our color will change. With the scaling factor in hand, we can loop over the data and generate the visual for each province.
What we are going to do to get the color for each region is this: we start with the color yellow, which is no blue, maximum red (255 over 255), and a lot of green (240 over 255). Depending on whether the crime severity index is high or not, we are going to remove a lot of or a little green from our starting yellow, making our color more red (since there is no blue, removing green only leaves red). Using the scalingFactor
variable, we can calculate how much green we remove.
green = 240 - Math.round((data[i].crimeSeverityIndex - minValue) * scalingFactor);
Now that we computed our color, we need to assign it to the PolygonFeature
class. This process is a bit tedious too; simple but tedious. Most of the code in step 6 is about assigning the color to the PolygonFeature
class. We need to create instances of SolidFill
, Stroke
, PolygonSymbolizer
, Rule
, and Style
just to assign a color to a region, but once it is done it looks really great.
Now that we showed how to display data over regions you can modify our code to suit your needs.
The data from Natural Earth comprises the boundaries for all the regions of the Earth. Be it the regions of France or the prefectures of Japan, you can find the boundaries in the Natural Earth spreadsheets, available at https://www.google.com/fusiontables/DataSource?dsrcid=394713. Now all you need is data to be represented on a map.
For this recipe we used a color range of yellow going to red but you could use any color range just by using the technique we used but by modifying another color instead of the green.
What you could also do, is create the same region twice, the bottom one being white and the second one being a color of your choice. By modifying the alpha of the colored region, let's say from 0.5 to 1, you would get a range over that color (from light to dark).
3.15.219.217