Home  >  

Flex GeoWeb with Yahoo AS3 Services

Author photo
| | Comments (7)
AddThis Social Bookmark Button
Web map has become an important utility of our daily life. We use it to plan a trip for directions, we use it to virtually walk around a city in 3D, we use it to find an apartment or a house from map mashup applications and so on. What if we want to ask more complicate questions to the web map, questions such as "How many Starbucks stores within 5 miles range of a dream house I can't take my eyes off, and I can drive to some of those stores in 3 minutes from the dream house?" Obviously for questions like this, merely putting markers/push-pins on the map is not enough.

ᅠ This is where the geo spatial analysis enabled GeoWeb comes in.

To demonstrate how integrated geo spatial service, RIA technology, location based service and digital map can make our life easier, by answer questions like above one, I developed a geo spatial service enabled Flex Yahoo AS3 map application. The following is the details.

GeoWeb Yahoo
You can try this application here. For source code, right click the application and select View Source.

What the application does:
• Enter an address in free form, or
• Just one click on the map to a location, where the application will find the address of that clicked location.
• Enter what want to looking form, such as "starbucks", within how many miles range and how many minutes you want to drive to get there.
• The application will show the 5 miles circle around the address/location you specified and the drive time polygon covers the area you can reach within specified driving minutes.

I am sure you can find other use cases of this application rather than for a cup of latte. I'd like to hear from you on how would you think could use this type of application and how do you think can extend the application to be more useful.

What used to develop the application

Flex Builder 3
Yahoo Map for ActionScript 3.0 from Yahoo Flash Developer Center. In addition to AS3 map API, this library contains API for Yahoo web services such as Geocoding, Local Search and Traffic.
ESRI JavaScript API beta for ArcGIS 9.3, which is a full stack geo spatial technologies and tools.

Yahoo made some adjustment last year on how the Flash technology is used on Yahoo's web platform. They replaced the Flex based Yahoo map with JavaScript Yahoo Map. In the mean while, they accelerate the development works at Yahoo Flash Developer Center, where the latest Yahoo Map for ActionScript 3.0 replaced the old Flex 2 Map API, and AS3 based ASTRA Flash components library got frequent update as well.

ESRI is the leader in GIS (Geographic Information System) space. Their ArcGIS 9.3 server is currently in Beta. The JavaScript API coming with ArcGIS 9.3 server provides a lightweight way (or Google map API or Virtual Map API way) to consume REST based geo spatial services. As matter of fact, the new ESRI JavaScript API contains extensions for both Google Map API and Virtual Earth Map API. They are also working on Flex API that combines the digital map and geo spatial service. For now, let's see how Flex integrates Yahoo Map for AS3 with geo spatial service.


The User Interface

As shown on the screen shot above, the UI is very straight forward. Only thing worth mentioning is how the Yahoo map is displayed. Since the Yahoo API is pure AS3 implementation, there are two ways to use it. One, define the name space in MXML header so that the map can be laid out with MXML tag; Or, display the map straight out of ActionScript code. Since the map part of this application is very simple, I chose the later approach, using ActionScript code.

The map place holder is defined as such:

<mx:Panel id="mapBox" height="100%" width="80%" title="Map">
    <mx:UIComponent id="mapPanel" width="100%" height="100%"/>
</mx:Panel>
The UIComponent is required for the attachment of a Yahoo Map. The ActionScript code to add a map is:

var yahooID:String =  
          "YL7F_WTV34EbqM46jSc.RwH5sEB0O3N47nM42Z1pk2Uf0aKyNR_gRlA24h_i";          
        map = new YahooMap();  
        map.init(yahooID, mapPanel.width, mapPanel.height);
        mapPanel.addChild(map); 

That's it. We have a Flex Yahoo map to work with now. If you want to try out the Yahoo Map API, you need apply a Yahoo application ID as shown and used in above code. It only takes a minute or two to get it.

Geocoding

Geocoding is one of the most frequently used geo spatial services for GeoWeb applications. What it does is simple: Given an address, find the latitude and longtitute (the x/y coordinate) of the address on the map; Or, given a latitude/longtitute point on the map, find the address of that location (aka, reverse geocoding).

Good thing is Yahoo Map for AS3 contains Geocoding service API, which is very handy for this application. First, let's see how an address is geocoded:

   addressToFind = new Address(address.text); 
   addressToFind.addEventListener(
                            GeocoderEvent.GEOCODER_SUCCESS, 
                            handleGeocodeSuccess);
   addressToFind.geocode();

   ...

   private function handleGeocodeSuccess(event:GeocoderEvent):void  
   { 
      var result:GeocoderResult = addressToFind.geocoderResultSet.firstResult; 
     
      map.zoomLevel = result.zoomLevel; 
      clearMapItems();
      map.centerLatLon = result.latlon;
      addCenterMarker(map.centerLatLon);                
      searchAndShow(map.centerLatLon);
     
    } 
As you can see, there is a set of Geocoding classes you can play with, including Address, GeocoderEvent, GeocoderResult, etc. The usage of them is straight forward. As usual, the remote connection is designed as asynchronous, which is consistent with Flex's communication model. The success geocoding event call-back function handleGeocodeSuccess is defined to receive the geocoding result.

Next, let me show you how reverse geocoding works:

   geocoder = new Geocoder();
   geocoder.addEventListener(
                  GeocoderEvent.GEOCODER_SUCCESS, 
                  handleReverseGeocoding);
   geocoder.reverseGeocode(centerMarker.latlon);

   ...

   private function handleReverseGeocoding(event:GeocoderEvent):void {
       var resultSet:GeocoderResultSet = event.data as GeocoderResultSet;
       var firstResult:GeocoderResult = resultSet.firstResult;
                 
       mapBox.status = firstResult.getLineAddress();
       address.text  = firstResult.getLineAddress();
    }
The reverse geocoding process is very similar to the address geocoding. A Geocoder class is used to do the job and the communication is asynchronous as well. In the above code, the address obtained from the reverse geocoding is shown at both address input text filed and the map panel title status area. Just you know Yahoo recently released a new startup called FireEagle. The whole business model of Fire Eagle is built around a high performance geocoding technology Yahoo acquired from a buy out. Geocoding is one of the fundamental building blocks for GeoWeb. It's nice we can do it so easily as I showed you in above code.

Local Search

I bet most of the time you come to the web is to search for something. We can't build a GeoWeb applications without location based search either. In my case, I'd like to search something around a location within certain miles. That's exactly what Yahoo Local service can do and Yahoo Map for AS3 contains the API does just that. Here is the code does the search:

  var localSearch:LocalSearch = new LocalSearch();
  localSearch.addEventListener(LocalSearchEvent.SEARCH_SUCCESS, 
                               handleSearchSuccess);
  localSearch.searchLocal(findSomthing.text, 
                          map.zoomLevel, 
                          loc, 
                          Number(withinMiles.text), 1, 25 );
As you might have noticed, the way calling Yahoo services is very consistent. This search result handling function is:

private function handleSearchSuccess(event:LocalSearchEvent):void {
     var searchResults:LocalSearchResults = 
                       event.data as LocalSearchResults;
     var results:Array = searchResults.results;
     var len:int = results.length;
     
     searchMarkers = new Array();
     
     for(var i:int=0; i<len; i++) {
          var item:LocalSearchItem = results[i];
          var marker:SearchMarker = new SearchMarker(item);
          
          map.markerManager.addMarker(marker);
          searchMarkers[i] = marker;    
      }
}  
I do like the SearchMarker class provided by Yahoo. It simplifies a lot on search result processing. In the above code, all I need to do is to add the SearchMarker to the map one by one.

Drawing a Circle on Map

You must be wondering what's the big deal of drawing a circle on a map. Well, the big deal is, just in case you forgot, the Earth is not flat. Simple x = r*cos(a), y = r*sin(a) equation to find out and draw points to form a circle won't work. Here is the code to come up with the points for a circle on the map so that you have a taste on what geo spatial service or GIS deals with:

   var latRadius:Number = miles/69;
   var lonRadius:Number = miles/(Math.cos(point.lon*Math.PI/180)*111.315);
   var circlePoints:Array = new Array();

   for (var i:int=0; i<=360; i++){
        var cPoint:LatLon = new LatLon(
          point.lat + latRadius*Math.sin(i*Math.PI/180), 
          point.lon + lonRadius*Math.cos(i*Math.PI/180));
 
        circlePoints[i] = cPoint;                    
        lonRadius = miles /(Math.cos(cPoint.lon*Math.PI/180)*111.315);
    }
Eventually, the circlePoints array contains all the points to be drawn. The reason behind it is that each latitude degree represents almost identical distance. However, the distance of one degree longtitute changes depends on where the location is. Have I done it right? Close enough. But scientifically speaking, there are more need to be considered such as the projection system used for this map, the data set standard used, etc. A geo spatial service or GIS will handle all that. So it's OK you have no idea what I'm talking about here, because me neither.

Driving Time Polygon
If that circle I've drawn represents the perfect world, then the driving time polygon is the reality. Within certain minute, how far you can reach in all directions is not a circle. It's a irregular polygon that its shape depends on the streets, connections, highways, etc. But how do you come up with that polygon?

Well, it needs to analyze the street (or route) as a network, where all the turns, intersections, segments of streets, one way or two ways, directions, types of streets, etc are data. Can you imagine now how intensive computing involved? Can you imagine the level of math applied here? Don't be scared, the geo spatial service has gotten all those covered. All we need to do here is to call couple of simple JavaScript API functions.

In this application, the communication between the Flex SWF and JavaScript code in HTML makes the driving time polygon drawing happens. When click the Find the button, eventually, the Flex code calls a external JavaScript function getDriveTimePoly and passes the center point lat/lon and driving minutes. Calling external JavaScript function is very simple:

   import flash.external.ExternalInterface;
   var m:String = ExternalInterface.call(
                   "getDriveTimePoly", 
                   map.centerLatLon.lat.toString(), 
                   map.centerLatLon.lon.toString(), 
                   this.driveTime.text);
After the JavaScript function did its work, it calls back a Flex method to pass in the result polygon points array. To allow a external call back, the only thing needs to do is register that method after application initialized as this:

ExternalInterface.addCallback("createDriveTimePoly",createDriveTimePoly);
In my case, the JavaScript function will call the Flex method createDriveTimePoly. Now, let's take look at what the JavaScript part looks like.

Since the ESRI JavaScript API for ArcGIS 9.3 is still in beta, I won't get into too much details. Rather, here is the code. First, initialize the geo spatial task on HTML page load:

      function init() {
          point = new esri.geometry.Point();
          point.spatialReference = new esri.SpatialReference();
          point.spatialReference.wkid = 4326;
          task = new esri.tasks.Geoprocessor("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Network/ESRI_DriveTime_US/GPServer/CreateDriveTimePolygons");
       }
The URL shown here is the REST end point represents the CreateDriveTImePolgons GeoProcess, which is running a ArcGIS server environment. All the hard work is done there. Then to execute the task:

      function getDriveTimePoly(lat, lon, mins) {  
         window.document.title= lat + ":" + lon + ":" + mins;
         
         point.x = parseFloat(lon);
         point.y = parseFloat(lat);
         
         var pointSymbol = new esri.symbol.SimpleMarkerSymbol();
         graphic = new esri.Graphic(point,pointSymbol);
         var features= [];
         features.push(graphic);  
       
         featureSet = new esri.tasks.FeatureSet();
         featureSet.features = features;
                 
         var params = { "Input_Location":featureSet, "Drive_Times":mins };
        task.execute(params, showResult);
       }
You can see most of the code is just to prepare the parameter. The last line simply calls the task. It's a asynchronous AJAX call so that a call back showResult function has to be specified. By the way, the ESRI JavaScript API is built around JavaScript Dojo Tookit.

The showResult function is the one calls back the Flex method to start drawing the driving time polygon inside my Flex Map:

      function showResult(success, messages, data) {  
         resultData = data;
           resultFeatures = resultData[0].value.features;    
           
           for (var i=0; i<resultFeatures.length; i++) {
                var geo = resultFeatures[i].geometry.rings[0];
                var done = GeoYahooMap.createDriveTimePoly(geo, i); 
            
            } 
           
           window.document.title = window.document.title + "=" + done; 
           window.clearTimeout(tout);    
       }  
In the code, GeoYahooMap is the name of the SWF file that used to identify the Flex application.

With the driving time polygon drawn, we've done the job. Not too hard, isn't it?

Before you moving on, there are couple of my discoveries to share so that you won't run into them with wasted efforts.

First, the Yahoo Map for AS3 does have bugs. For example, you can't just simply call the method map.markerManager.removeAllMarkers() to remove all markers as it promised, nor does map.overlayManager.removeAllOverlay(). It will partially remove items and then complains about null value. That's why I ended up storing all the markers and overlay into global variables and looping them through to remove them, in the clearMapItems method.

Another note, to allow JavaScrip function in HTML page to call Flex method, be careful about HTML definition at the first couple of lines. In my case, something like this:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
will stop the calling from JavaScript to Flex. Flex calls external function still works though. So, to make it easier, my HTML starts with: <html lang="en">

Also, as best practices, for a real Flex application, I would put all those ActionScript code outside of the MXML file. Also, I would use CSS to manage the layout so that the MXML will be much cleaner.

Again, go to here to run the application, right click on Flex to view the Flex source code and right click the none Flex to view the HTML/JavaScript source.

Read more from Moxie Zhang. Moxie Zhang's Atom feed flexria on Twitter

Comments

7 Comments

Brett Walker said:

Great work man. It's still too bad that uMap's Google support got shut down due to Goog's over-restrictive TOS, but this is probably the next best thing.

What would be nice to see (and what uMap has) is dynamic map scaling as you zoom, which made its Google Maps implementation actually better than Google's own experience.

I second that. This is a great tutorial for n00bs like me who wants to dive into geocoding and doesn't know where to start. I appreciate your effort on this. Thanks a lot man.

[...] I have no idea about how can we dive into the web map but i have seen many of the sites they are keeping web map in their site to tell the exact area of the company. now it is taking place in most of the sites......

freaking cool, i did something similar with googlemaps and php a while ago. to see the same idea but on flex is niiice!

i'll try to play a little bit more con user interaction on the map

thanx for your time and share!

Hey,
Here is a tutorial to show how to geo-locate a visitor with his IP. I explain how to install and use the MaxMind Database with PHP scripts examples. And it also shows how to display it on a map (Yahoo! Map) (french):
http://www.flex-tutorial.fr/2009/02/01/flex-yahoo-maps-api-geo-localisation-par-ip-dun-visiteur-exemple/

pedro said:

hi,
this may be a dumb question, but i assume this only works for users that are online? we have some customers that are not allowed an internet connection due to HIPAA contracts.

i am looking for a geo-mapping solution that can work on it's own. i'm sure i'll have to go private, just wanted to ask...

pedro said:

hi,
this may be a dumb question, but i assume this only works for users that are online? we have some customers that are not allowed an internet connection due to HIPAA contracts.

i am looking for a geo-mapping solution that can work on it's own. i'm sure i'll have to go private, just wanted to ask...

Leave a comment


Type the characters you see in the picture above.

Tag Cloud

Poll: Sci-Fi Movies

What's Your Favorite Sci-Fi Movie of All Time?

Vote | View Poll Results | Read Related Blog Entry

Latest Features

  •     Welcome back to the series. This time we are goings to build a really exciting component that will be used to simply display information about the user. Well, you might say why to we need such a component, is there... Continue Reading
  •    Welcome back to our exciting Facebook ActionScript series. In this article we will discuss one of most important (and most exciting) features of the FB platform, it's the publishing of news. We all know when we log in to facebook,... Continue Reading
  • This article provides 10 tips and best practices (in no particular order) for maximizing the benefits that Dojo can bring to your next project. For a more thorough introduction to Dojo, see the article Dojo: The JavaScript Toolkit with... Continue Reading
  •     The notifications are one of the most interesting (and important) parts of the facebook area. In order to completely understand the Flash side of it, we need to understand the basics of the facebook notification, what it is and how... Continue Reading

Development Series

Get an overview of the tools and technologies that work together to allow developers to build Rich Internet Applications (RIAs) quickly and easily.

facebook icon Facebook Application Development

Anatomy of an Enterprise Flex RIA

Recommended for You

@InsideRIA on Twitter

Archives

  • Or, visit our complete archive.  

About This Site

Welcome to the premiere community site for all things RIA sponsored by O'Reilly Media and Adobe Systems Incorporated.