Adobe
Products
Creative Suite
Photoshop Family
Acrobat Family
Flash Platform
Digital Marketing Suite
Digital Publishing Suite
More products
Solutions
Digital marketing solutions
Digital media solutions
Education
Financial services
Government
Web Experience Management
More solutions
Learning Help Downloads Company
Store
Adobe Store for home and home office
Education Store for students, educators, and staff
Business Store for small and medium businesses
Other ways to buy
Search
 
Info Sign in
Welcome,
My cart
My orders My Adobe
My Adobe
My orders
My information
My preferences
Sign out
Why sign in? Sign in to manage your account and access trial downloads, product extensions, community areas, and more.
Adobe
Products Sections   Search  
Solutions Company
Help Learning
Sign in Welcome, My orders My Adobe
Qty:
Purchase requires verification of academic eligibility
Subtotal
Review and Checkout
Adobe Developer Connection / Flex Developer Center /

Building interactive maps with Flex

by Matt Sheehan

Matt Sheehan
  • flexmappers.com

Content

  • Getting started
  • Adding zoom
  • Extending the application

Modified

7 March 2010

Page tools

Share on Facebook
Share on Twitter
Share on LinkedIn
Bookmark
Print
components Flash Builder

Requirements

Prerequisite knowledge

General familiarity with Flex and ActionScript 3.

User level

Intermediate

Required products

  • Flash Builder 4 (Download trial)

Additional Requirements

Modest Maps ActionScript 3 release

  • Download

It has never been easier to build interactive online maps with Flex. There is a wide range of APIs now available. The focus of this article is building a simple map application using the open-source Modest Maps Flex API. Modest Maps offers a number of advantages over other Flex mapping APIs including the ability to point at multiple basemap providers and direct access to the source code. In this article, you will first learn how to build a basic interactive map with zoom and pan functionality. You will then extend the application to include multiple providers and markers. Working examples of the application can be accessed at different stages of development via links referenced in the text.

Getting started

Before you start coding, you can try the sample application for this section. To view the source, right-click the map and select View Source.

After installing Flash Builder 4 and downloading the Modest Maps AS3 archive, open Flash Builder 4 and create a Flex project called mymodestmap. Unzip the contents of the Modest Maps AS3 archive. Copy and paste the com and gs directories from the lib directory in the archive to the src directory of  your mymodestmap Flex project. You could use the supplied SWC, but for this exercise  use the actual source. Now open mymodestmap.mxml, which is in the src/(default package) directory of our Flex project. The first steps are to add an init() function that is called when the application's creation is complete, a container for the map, and some import statements. You can copy the following code into mymodestmap.mxml:

<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/halo" minWidth="1024" minHeight="768" creationComplete="init()"> <fx:Script> <![CDATA[ import mx.core.UIComponent; import com.modestmaps.TweenMap; import com.modestmaps.mapproviders.OpenStreetMapProvider; import com.modestmaps.geo.Location; private function init():void { } ]]> </fx:Script> <mx:Canvas id="mappanel" width="100%" height="97%"/> </s:Application>

Your first map will be accessing the OpenStreetMap open source basemap. You'll add this as a UIComponent to the mappanel canvas. You'll need to add some declarations and the initial latitude (lat), longitude (long), and zoom level. The lat/long marks the center of the map. To find the lat/long of a location, there is an excellent tool you can use: Google Maps Latitude, Longitude Popup.

The Map class is at the core of the Modest Maps API. The code below creates an instance of TweenMap, which extends Map. The new TweenMap is given a height, width, and a provider. TweenMap is a recent addition to the code base. It improves the fading of tiles and zoom in and out around a fixed point. Next, the code sets the map center and zoom of the TweenMap instance. Finally, the mapCore() function creates the display object hierarchy. Copy the following code to mymodestmap.mxml:

<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/halo" minWidth="1024" minHeight="768" creationComplete="init()"> <fx:Scrip> <![CDATA[ import mx.core.UIComponent; import com.modestmaps.TweenMap; import com.modestmaps.mapproviders.OpenStreetMapProvider; import com.modestmaps.geo.Location; [Bindable]private var _map:TweenMap; private var _mapUI:UIComponent; [Bindable]private var _initialLat:Number = 40.668903; [Bindable]private var _initialLong:Number = -111.680145; [Bindable]private var _initialZoom:Number = 6; private function init():void { _map = new TweenMap(mappanel.width, mappanel.height, true, new OpenStreetMapProvider()); _map.setCenterZoom(new Location(_initialLat, _initialLong), _initialZoom); mapCore(); } private function mapCore():void { _mapUI = new UIComponent(); _mapUI.addChild(_map); mappanel.addChild(_mapUI); } </fx:Script> <mx:Canvas id="mappanel" width="100%" height="97%"/> </s:Application>

Now run the application. There you have it—a map of the Western United States. The map can also be panned, in the same way you pan Google Maps. Try it. Welcome to the world of slippy maps.

Adding zoom

So far so good. You have created a basic interactive map. The next step is to add a zoom capability. There are a number of ways this can be done. Modest Maps comes with a several controls that you can use. This example uses the zoom slider and also enables mouse wheel zoom. You can implement this by adding to the existing code. For the zoom slider, add the following to the import statements:

import com.modestmaps.extras.ZoomSlider;

Add the following lines to the mapCore() function:

var zoomslider:ZoomSlider = new ZoomSlider(_map); zoomslider.x = mappanel.width - zoomslider.width*2; zoomslider.y = 30; _mapUI.addChild(zoomslider);

It is not the most stylish slider, but you can easily rectify that by accessing and editing the source.

To enable the mouse wheel zoom you will need to add more code and a new function. Add this to the declarations:

private var _mouseWheelZoomCenter:Location; private var _mouseWheelZoom:int;

To handle any mouse wheel events, add a listener in the mapCore() function:

_map.addEventListener(MouseEvent.MOUSE_WHEEL, mouseWheelHandler);

The event handler is below:

private function mouseWheelHandler(e:MouseEvent):void { if (e.delta < 0) { _map.zoomOut(); } else if (e.delta > 0) { _map.zoomIn(); } _mouseWheelZoomCenter = _map.getCenter(); _mouseWheelZoom = _map.getZoom(); }

This code tracks the direction of the mouse wheel and zooms accordingly. I like a hand icon when I pan. To add one, you first need an additional import statement:

import com.modestmaps.extras.HandCursor;

Then add it to the mapCore() function as follows:

var handcursor:HandCursor = new HandCursor(map); mapUI.addChild(handcursor);

Your code should now look like this:

<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/halo" minWidth="1024" minHeight="768" creationComplete="init()"> <fx:Script> <![CDATA[ import mx.core.UIComponent; import com.modestmaps.TweenMap; import com.modestmaps.mapproviders.OpenStreetMapProvider; import com.modestmaps.geo.Location; import com.modestmaps.extras.ZoomSlider; import com.modestmaps.extras.HandCursor; Bindable]privatevar _map:TweenMap; private var_mapUI:UIComponent; [Bindable]private var_initialLat:Number = 40.668903; [Bindable]private var_initialLong:Number = -111.680145; [Bindable]private var_initialZoom:Number = 6; private var_mouseWheelZoomCenter:Location; private var_mouseWheelZoom:int; private var_mouseWheelZoomCenter:Location; private var_mouseWheelZoom:int; private function init():void { _map = new TweenMap(mappanel.width, mappanel.height, true, new OpenStreetMapProvider()); _map.setCenterZoom(new Location(_initialLat, _initialLong), _initialZoom); mapCore(); } private function mapCore():void { _map.addEventListener(MouseEvent.MOUSE_WHEEL, mouseWheelHandler); _mapUI = new UIComponent(); _mapUI.addChild(_map); var zoomslider:ZoomSlider = new ZoomSlider(_map); zoomslider.x = mappanel.width - zoomslider.width*2; zoomslider.y = 30; _mapUI.addChild(zoomslider); var handcursor:HandCursor = new HandCursor(_map); _mapUI.addChild(handcursor); mappanel.addChild(_mapUI); } private function mouseWheelHandler(e:MouseEvent):void { if (e.delta < 0) { _map.zoomOut(); } else if (e.delta > 0) { _map.zoomIn(); } _mouseWheelZoomCenter = _map.getCenter(); _mouseWheelZoom = _map.getZoom(); } </fx:Script> <mx:Canvas id="mappanel" width="100%" height="97%"/> </s:Application>

Run the application. Try the slider and mouse wheel. Notice how the pan hand cursor grips as you mouse down and pan.

Zoom into West Valley City. Notice the amazing detail. I say "amazing" since OpenStreetMap is a purely voluntary effort. The mapping is being done by people like you and me. I have no association with OpenStreetMap, but I encourage you to go to their web site and get involved.

Extending the application

You can try a working example and download the code for this section.

In this section, you'll extend the code for the application you just built. In this section you'll give the user the ability to switch basemap providers and add points of interest, better known as markers. In this case, the application will load XML data and add markers to the map based on data from this XML. In addition, the application will display a draggable information box, actually a Flex TitleWindow. The information will be updated after a user clicks a marker.

Dynamically changing basemap providers

Currently the application displays vector roads data provided by OpenStreetMap. Now you'll add satellite imagery from Microsoft Virtual Earth. Inside of your mymodestmap project create a new Flex MXML application and name it myadvancedmodestmap. Copy and paste the code in mymodestmap.mxml to myadvancedmodestmap.mxml, and then add the following import statement:

import com.modestmaps.mapproviders.yahoo.YahooHybridMapProvider;

Add two buttons to allow the user to switch basemap providers. Insert this code below the mappanel canvas:

<mx:HBox width="100%" horizontalAlign="right"> <mx:Button label="OpenStreetMap" click="handleChangeProvider(event)"/> <mx:Button label="Virtual Earth" click="handleChangeProvider(event)"/> </mx:HBox>

To handle the button clicks, include the following handler function for switching providers. First handleChangeProvider() removes the previous children of mapanel, and then it repopulates the container.

private function handleChangeProvider(event:Event):void { mappanel.removeAllChildren(); if(event.target.label == "Virtual Earth") { _map = new TweenMap(mappanel.width, mappanel.height, true, new YahooHybridMapProvider()); } else { _map = new TweenMap(mappanel.width, mappanel.height, true, new OpenStreetMapProvider()); } if(_mouseWheelZoomCenter != null && _mouseWheelZoom > 0) { _map.setCenterZoom(_mouseWheelZoomCenter, _mouseWheelZoom); } else { _map.setCenterZoom(new Location(_initialLat, _initialLong), _initialZoom); } mapCore(); }

When you run the application you should now be able to switch between basemap providers.

Adding markers

Interactive maps contain markers to highlight points of interest (POI). It is easy to add markers by pulling data from a georeferenced feed such as RSS or geoRSS. For simplicity, this example will create markers using XML data provided in the declarations section as follows:

private var srcXML:XML = <root> <location> <name>Alta Ski Resort</name> <lat>40.588063</lat> <long>-111.637659</long> <description>Home of the Greatest Snow on Earth</description> </location> <location> <name>Crested Butte Resort</name> <lat>38.899932</lat> <long>-106.964249</long> <description>Amazing skiing with small town charm</description> </location> </root>;

To add markers, you'll need to create a new Actionscript class. In the src/com directory create a new directory named custom. In the custom directory create a new Actionscript class that extends Sprite and name it PointMarker. This class is a simple Sprite, which contains setters and getters and to which you will add a Bitmap. The class is as follows:

package com.custom { import mx.core.UIComponent; import flash.display.Sprite; public class PointMarker extends Sprite { private var _nName:String; private var _nMarker:String; private var _nDescription:String; public function set resortName(name:String):void { _nName = name; } public function get resortName():String { return _nName; } public function set resortDesc(description:String):void { _nDescription = description; } public function get resortDesc():String { return _nDescription; } } }

Now return to myadvancedmodestmap.mxml to load the XML data, create markers for each location, and add them to the map. In myadvancedmodestmap.mxml, import the new class:

import com.custom.PointMarker;

Add a new declaration:

private var resortMarker:PointMarker;

Add a new function called addMarkers() to place the markers on the map:

private function addMarkers():void { for each (var resort:XML in srcXML.location){ resortMarker = new PointMarker(); var markerImage:Bitmap = new MarkerImage() as Bitmap; markerImage.x = -markerImage.width/2 markerImage.y = -markerImage.height/2 resortMarker.addChild(markerImage); resortMarker.resortName = resort.name; resortMarker.resortDesc = resort.description; _map.putMarker(new Location(resort.lat, resort.long), resortMarker); } }

Call addMarkers() from the mapCore() function:

addMarkers();

Lastly, just above the init() function embed the marker:

[Embed(source="img/marker.png")] protected var MarkerImage:Class;

You'll need to create an img directory under src. Create an image called marker.png and add it to this directory or download the source image from the FlexMappers site.

There you have it. Run the application and you should see Alta and Crested Butte ski resorts marked on the map.

Adding a marker information box

As a final step you will add code to display marker information in a draggable information box. To do this, you will need to create a new MXML component and add listeners to the markers. In the com/custom directory add a new MXML component called InfoPane. Here is the class code for the component, which is a TitleWindow. It simply displays labels in the TitleWindow, and updates them when a user clicks a marker.

<?xml version="1.0" encoding="utf-8"?> <mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml" width="300" height="300" creationComplete="init()" alpha="0.7"> <mx:Script> <![CDATA[ import flash.geom.Rectangle; private var _containerheight:Number; private var _containerwidth:Number; [Bindable] private var _ntitle:String = "Welcome"; [Bindable] private var _ndesc:String = "My first Flex interactive map"; private function init():void{ this.titleBar.addEventListener(MouseEvent.MOUSE_DOWN, moveWindow); this.titleBar.addEventListener(MouseEvent.MOUSE_UP, stopWindow); } public function set ptitle(value:String):void{ _ntitle = value; } public function set pdesc(value:String):void{ _ndesc = value; } public function set containerWidth(width:Number):void{ _containerwidth = width; } public function set containerHeight(height:Number):void{ _containerheight = height; } private function moveWindow( evt:MouseEvent ):void{ var limitdrag:Rectangle = new Rectangle(0, 0, _containerwidth-this.width, _containerheight-this.height); this.startDrag(false, limitdrag); } private function stopWindow( evt:MouseEvent ):void{ this.stopDrag(); } ]]> </mx:Script> <mx:VBox horizontalAlign="center" width="100%" height="100%" verticalAlign="middle"> <mx:Label id="ntitle" text="{_ntitle}" fontSize="16"/> <mx:Label id="ndesc" fontSize="12" text="{_ndesc}"/> </mx:VBox> </mx:TitleWindow>

Finally, update myadvancedmodestmap.mxml to import the new component and add a declaration:

import com.custom.infoPanel; private var _panel:infoPanel;

In the mapCore() function add the new component and size it:

_panel = new infoPanel(); _panel.containerHeight = mappanel.height; _panel.containerWidth = mappanel.width; mappanel.addChild(_panel);

In the addMarkers() function add the listener at this point to addMarkers function:

resortMarker.addEventListener(MouseEvent.CLICK, handleMouseClick);

Finally, add one more new function to handle marker clicks:

private function handleMouseClick(event:MouseEvent):void { _panel.ptitle = event.target.resortName; _panel.pdesc = event.target.resortDesc; }

That's all there is to it. Run the application. In the top left you should now see an information box. The alpha is set to 0.7 so the map can be seen through the panel. You can also drag the panel within the bounds of the map. Click on a marker and see the panel update with marker-specific information.

Where to go from here

Modest Maps and OpenStreetMap are fully open source. This article walked you through the creation of an open source mapping application using these sources. It's the start of a journey. The field of online mapping and the GeoWeb is still in its infancy, but it's growing quickly. It is an exciting and broad field.

Here are a few ideas for extending the application:

  • Style the zoom slider
  • Add a listener and handler for marker MouseOver and display a label next to the marker.
  • When the user pans, the application does not store the current center of the map. Switching providers does not reflect the previous center point. What's the fix?
  • Add georeferenced imagery and video.

Here are some of the resources you can refer to:

  • Modest Maps
  • Modest Maps API
  • ActionScript 3.0 Reference for the Adobe Flash Platform


This work is licensed under a Creative Commons Attribution-Noncommercial 3.0 Unported License.

More Like This

  • Flex 3 Component Solutions excerpt: Introducing hierarchal data and components
  • Flex 3 Component Solutions excerpt: Audio and video components
  • Creating components and enforcing separation of concerns with Flex
  • Creating Flex components
  • Defining and using new skin parts in a Spark skin | Adobe Developer Connection
  • Using Flash media components to play video in Flex projects
  • Building a simple dashboard using Flex 3 with ILOG Elixir
  • Building an icon-checkbox component with Flex 3
  • Introducing Adobe Flex 4.6 SDK
  • What's new in Flex 4.6 SDK and Flash Builder 4.6

Tutorials & Samples

Tutorials

  • Flex mobile performance checklist
  • Flex and Maven with Flexmojos – Part 3: Journeyman
  • Migrating Flex 3 applications to Flex 4.5 – Part 4

Samples

  • Twitter Trends
  • Flex 4.5 reference applications
  • Mobile Trader Flex app on Android Market

Flex User Forum

More
02/07/2012 Newbie - Views
01/24/2012 How to navigate through the views without losing content?
02/07/2012 ActionScript rounding issue
02/07/2012 Setting Value of Static Const

Flex Cookbook

More
01/20/2012 Skinnable Transform Tool
12/12/2011 Date calculations using 'out-of-the-box' functions
12/05/2011 String replaceAll in ActionScript
12/04/2011 Flex: Validate/revert editable Datagrid input value

Products

  • Creative Suite
  • Photoshop Family
  • Acrobat Family
  • Flash Platform
  • Digital Marketing Suite
  • Digital Publishing Suite
  • Mobile apps

Solutions

  • Digital marketing
  • Digital media
  • Web Experience Management

Industries

  • Education
  • Financial services
  • Government

Help

  • Product help centers
  • Orders and returns
  • Downloading and installing
  • My Adobe

Learning

  • Adobe Developer Connection
  • Adobe TV
  • Training and certification
  • Forums
  • Design Center

Ways to buy

  • Adobe Store
  • For students and educators
  • For small and medium businesses
  • For enterprises
  • Special offers

Downloads

  • Adobe Reader
  • Adobe Flash Player
  • Adobe AIR
  • Adobe Shockwave Player

Company

  • News room
  • Partner programs
  • Corporate social responsibility
  • Career opportunities
  • Investor Relations
  • Events
  • Legal
  • Contact Adobe
Choose your region United States (Change)
Choose your region Close

North America

Europe, Middle East and Africa

Asia Pacific

  • Canada - English
  • Canada - Français
  • Latinoamérica
  • México
  • United States

South America

  • Brasil
  • Africa - English
  • Österreich - Deutsch
  • Belgium - English
  • Belgique - Français
  • België - Nederlands
  • България
  • Hrvatska
  • Česká republika
  • Danmark
  • Eastern Europe - English
  • Eesti
  • Suomi
  • France
  • Deutschland
  • Magyarország
  • Ireland
  • Israel - English
  • Italia
  • Latvija
  • Lietuva
  • Luxembourg - Deutsch
  • Luxembourg - English
  • Luxembourg - Français
  • Middle East and North Africa - English
  • Moyen-Orient et Afrique du Nord - Français
  • Nederland
  • Norge
  • Polska
  • Portugal
  • România
  • Россия
  • Srbija
  • Slovensko
  • Slovenija
  • España
  • Sverige
  • Schweiz - Deutsch
  • Suisse - Français
  • Svizzera - Italiano
  • Türkiye
  • Україна
  • United Kingdom
  • Australia
  • 中国
  • 中國香港特別行政區
  • Hong Kong S.A.R. of China
  • India - English
  • 日本
  • 한국
  • New Zealand
  • Pacific - English
  • 台灣

Southeast Asia

  • Includes Indonesia, Malaysia, Philippines, Singapore, Thailand, and Vietnam - English

Copyright © 2012 Adobe Systems Incorporated. All rights reserved.

Use of this website signifies your agreement to the Terms of Use and Online Privacy Policy (updated 07-14-2009).

Ad Choices

Reviewed by TRUSTe: site privacy statement