Adobe
Products
Acrobat
Creative Cloud
Creative Suite
Digital Marketing Suite
Digital Publishing Suite
Elements
Photoshop
Touch Apps
Student and Teacher Editions
More products
Solutions
Creative tools for business
Digital marketing
Digital media
Education
Financial services
Government
Web Experience Management
More solutions
Learning Help Downloads Company
Buy
Home use for personal and home office
Education for students, educators, and staff
Business for small and medium businesses
Licensing programs for businesses, schools, and government
Special offers
Search
 
Info Sign in
Welcome,
My cart
My orders My Adobe
My Adobe
My orders
My information
My preferences
My products and services
Sign out
Why sign in? Sign in to manage your account and access trial downloads, product extensions, community areas, and more.
Adobe
Products Sections Buy   Search  
Solutions Company
Help Learning
Sign in Sign out My orders My Adobe
Preorder Estimated Availability Date. Your credit card will not be charged until the product is shipped. Estimated availability date is subject to change. Preorder Estimated Availability Date. Your credit card will not be charged until the product is ready to download. Estimated availability date is subject to change.
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

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

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
07/25/2011 Flash Player Debug Issues - Safari 5.1 & Chrome 13
04/22/2012 Loader png - wrong color values in BitmapData
04/22/2012 HTTPService and crossdomain.xml doesn't work as expected
04/23/2012 Memory related crashes in Flex application

Flex Cookbook

More
04/06/2012 How to detect screen resize with a SkinnableComponent
02/29/2012 Embed Stage3D content inside Flex application components
02/15/2012 Custom WorkFlow Component
02/09/2012 Using Camera with a MediaContainer instead of VideoDisplay

Products

  • Acrobat
  • Creative Cloud
  • Creative Suite
  • Digital Marketing Suite
  • Digital Publishing Suite
  • Elements
  • Mobile Apps
  • Photoshop
  • Touch Apps
  • Student and Teacher Editions

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

  • For personal and home office
  • For students, educators, and staff
  • For small and medium businesses
  • For businesses, schools, and government
  • 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
  • Security
  • 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
  • 台灣

Southeast Asia

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

Copyright © 2012 Adobe Systems Incorporated. All rights reserved.

Terms of Use | Privacy Policy and Cookies (Updated)

Ad Choices

Reviewed by TRUSTe: site privacy statement