One of the most challenging parts of creating Home Locator was the integration with Yahoo! Maps since there was no Flex 2 version of their API (they have a Flex 1.5 version, which does not work in Flex 2).
A lot of people asked me at CFUnited and by email about how I did it. In response to that, I made this simple example that shows the details, although not all of the functions are implemented.
One of the most challenging parts of creating Home Locator was the integration with Yahoo! Maps since there was no Flex 2 version of their API (they have a Flex 1.5 version, which does not work in Flex 2).
A lot of people asked me at CFUnited and by email about how I did it. In response to that, I made this simple example that shows the details, although not all of the functions are implemented.
It is important to say before we start that I don't recommend using this technique unless you need it right away. It would be better to wait until Yahoo! releases the Flex 2 version of their API. If you can wait, it will be so much easier for you and you won't have to deal with the whole Local Connection stuff (I will explain this in a minute).
As I mentioned before, Yahoo! doesn't have a Flex 2.0 map API, so if we want to have a map, we need to use the Flash API. But having the map in Flash and the rest of the app in Flex it is not as simple as having everything written in Flex. This is because now the player has 2 virtual machines, one for Flex that runs ActionScript 3 and another for Flash that runs ActionScript 2. The problem is that the communication between both VM is not straightforward. It is not very clean and it's not as robust as I would like it to be. But we need to communicate in some way and that way is by using Local Connection. Peter Ent from Adobe made a great post explaining the details of how to communicate Flash and Flex via Local Connection so I highly recommend you to read it.
These are the steps to put the map in a Flex app:
// ActionScript file
import com.yahoo.maps.markers.CustomPOIMarker;
import com.yahoo.maps.tools.PanTool;
import com.yahoo.maps.widgets.NavigatorWidget;
// register as a listener to get notified when the map finishes the initialization state
myMap.addEventListener(com.yahoo.maps.api.flash.YahooMap.EVENT_INITIALIZE, onInitMap);
function onInitMap(eventData)
{
// create tools and widgets to control the map
myMap.addTool(new PanTool(), true);
myMap.addWidget(new NavigatorWidget("closed"));
// notify Flex that the map finished the initialization state
connectedMap.send("_flexClient","mapInitialized");
}
var connectedMap:LocalConnection = new LocalConnection();
connectedMap.addMarker = function (connectionData:Object):Void
{
//Add the marker to the map
myMap.addMarkerByAddress(CustomPOIMarker,connectionData.address, connectionData.marker);
myMap.setCenterByAddress(connectionData.address, 2500);
}
connectedMap.connect("_flashClient");
What I did in the Flash movie is to set a listener for the "initialize" event. This event gets fired when the map finishes its initialization. Inside this event, I added a "Tool" and a "widget" to be able to control, drag and zoom the map. I also call the Flex application to let it know that flash finished its initialization, and it's ready for use. This also helps me forcing the connection from Flash, because I found (in the beta, that is. I don't know if the bug is fixed now) that if you don't start the connection from Flash the connection sometimes doesn't work.
I also want to mention that I used an underscore in the beginning of the connection name because I found (also in the beta, but I think that is fixed now) that the connection does not work if you name it without it. For example I used "_flexClient" and "_flashClient" for my names.
I included the .fla in the source code. So you only need to open the file, include your ID following the steps described at Yahoo!, compile the swf , and you are ready to go.
Now let's look at the Flex side. There are two files. One is the mxml application (MapExample.mxml) where all the components are.
In this file, we have the SWFLoader tag that will be loading the map into our flex app. In this file we also have a tag
package
{
import flash.net.LocalConnection;
public class MapConnection extends LocalConnection
{
private var isInitialized:Boolean;
private var index:uint;
public function MapConnection(server:String = "_flexClient")
{
try {
connect(server);
}
catch (error:ArgumentError)
{
// server already created/connected
}
super();
}
public function mapInitialized():void
{
isInitialized = true;
trace("SearchConnection init")
}
public function addMarker(address:String):void
{
var marker:Object = {index:++index, title:"title", description:"description", markerColor:0x990099, strokeColor:0xFFFF00 };
if(isInitialized) send("_flashClient","addMarker", {address:address, marker:marker});
}
}
}
In this other file we have one constructor and two methods. One method is "mapInitialized()" that will be called by Flash when Flash finishes the initialization of the map. The other is "addMarker()" that is called by the button that sends the info on the text field as the "address" parameter. What the method does is take that info, create a marker object, and send that to the Flash client (the map) using the local connection method "send()" that we inherit from LocalConnection.
As you can see, this example is very straightforward. You enter an address or just a zip code (easy to type) and click search to see the address marked in the map.
View Example