This tutorial shows you how to display Last.FM events on a Google map with Adobe Flex.
The sequence of events that we will follow is this:
- Create and display the Google map
- Request local events from the Last.FM service
- Place markers for those events onto the Google map
- Focus the map onto the last event that was placed
This tutorial will assume that you have read the previous two tutorials, and so we will brush over the actual implementation of the Google Maps and Last.FM service.
Import the following packages.
import mx.controls.Alert;
import com.google.maps.*;
import com.google.maps.overlays.*;
import com.google.maps.services.*;
import com.google.maps.controls.*;
import com.google.maps.*;
import com.google.maps.geom.*;
Define the following variables.
private static const LASTFM_API_KEY:String = "YourLastFMAPIKey";
private static const REQUEST_URL:String = "http://ws.audioscrobbler.com/2.0/?method=geo.getevents&api_key=" + LASTFM_API_KEY;
Add a Google map object to the Application element.
<maps:Map3D
xmlns:maps="com.google.maps.*"
mapevent_mappreinitialize="onMapPreinitialize(event)"
mapevent_mapready="onMapReady(event)"
id="map"
width="100%"
height="100%"
key="YourGoogleAPIKey"/>
Add the onMapPreinitialize and onMapReady functions to initialise the Google Map object.
private function onMapPreinitialize(event:MapEvent):void
{
var myMapOptions:MapOptions = new MapOptions();
myMapOptions.zoom = 12;
myMapOptions.center = new LatLng(40.756054, -73.986951);
myMapOptions.mapType = MapType.NORMAL_MAP_TYPE;
myMapOptions.viewMode = View.VIEWMODE_ORTHOGONAL;
map.setInitOptions(myMapOptions);
}
private function onMapReady(event:MapEvent):void
{
map.addControl(new ZoomControl());
map.addControl(new PositionControl());
map.addControl(new MapTypeControl());
loadLastFMGigs();
}
Once onMapReady has been called the Google Map object is ready to use. From the function we call the loadLastFMGigs function.
private function loadLastFMGigs():void
{
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, loaderComplete);
loader.addEventListener(IOErrorEvent.IO_ERROR,
function(error:IOErrorEvent):void
{
Alert.show("IO Error");
}
);
var request:URLRequest = new URLRequest(REQUEST_URL);
loader.load(request);
}
The loadLastFMGigs function queries the Last.FM servers for local events. The Last.FM servers will map the IP of the client to a location if no location is supplied.
The loaderComplete function is set to be called when the Last.FM servers return the events data.
private function loaderComplete(event:Event):void
{
var response:URLLoader = URLLoader(event.target);
var responseData:XML = new XML(response.data);
var point:LatLng = null;
for each (var node:Object in responseData.events.event)
{
point = createMarker(node);
}
if (point != null)
map.flyTo(point, 12, new Attitude(0,0,0), 3);
}
Here we simply loop through the event XML elements, and pass them to the createMarker function. Note that the createMarker function returns the geographical point of the event, the last one of which is saved and used to reposition the map by calling flyTo.
private function createMarker(node:Object):LatLng
{
var geo:Namespace = new Namespace("http://www.w3.org/2003/01/geo/wgs84_pos#");
var description:String = node.title + "\n" + node.startDate + "\n" + node.venue.name;
var lat:String = node.venue.location.geo::point.geo::lat;
var long:String = node.venue.location.geo::point.geo::long;
var latNumber:Number = parseFloat(lat);
var longNumber:Number = parseFloat(long);
if (isNaN(latNumber)) latNumber = 0;
if (isNaN(longNumber)) longNumber = 0;
var point:LatLng = new LatLng(latNumber, longNumber);
var info:InfoWindowOptions = new InfoWindowOptions({content: description});
var marker:Marker = new Marker(point);
marker.addEventListener(MapMouseEvent.CLICK, function (event:MapMouseEvent):void
{
marker.openInfoWindow(info);
});
map.addOverlay(marker);
return point;
}
The createMarker function takes the event XML element and extracts the latitude and longitude, converts that into a LatLng object which is then used to create and position a new Marker.
You may have noticed that we had to use a Namespace object to reference the events location. The XML returned by Last.FM looks like this (unnecessary elements have been left out for brevity).
<event>
...
<venue>
...
<geo:point>
<geo:lat>-33.893739</geo:lat>
<geo:long>151.262502</geo:long>
</geo:point>
...
</venue>
</event>
The latitude and longitude data are housed in XML elements named geo:lat and geo:long. You can not use the dot notation to reference these elements, instead you have to define a Namespace object and use double colons (::) to reference these elements from ActionScript.