Abbiamo già visto in un articolo precedente come interagire con Google Maps. In questo articolo ripercorriamo alcuni passi e vediamo come sfruttare l'interazione con la nostra applicazione aggingendo dei marker personalizzati.
Per utilizzare le Google Maps Api è necessaria una API Key ottenibile solo dai possessori di un account Google: l'api key è completamente gratuita e serve come identificativo per interfacciarsi con il sistema di mappe.
In fase di richiesta della chiave bisogna specificare l'indirizzo di un sito web: nel caso in cui stiamo sviluppando una web application dobbiamo specificare l'indirizzo del sito dove pubblicheremo l'applicazione; se stiamo sviluppando un'applicazione desktop (con Adobe AIR) dobbiamo specificare l'indirizzo del sito da cui sarà possibile scaricare l'applicazione.
Introdurre le mappe nell'applicazione
Per aggiungere una mappa alla nostra applicazione, per prima cosa dobbiamo scaricare l'SDK con le librerie per ActionScript e Flex dalla sezione del sito alle api per Flash.
Una volta scaricato il file sdk.zip, lo estraiamo e aggiungiamo al build path del nostro progetto la libreria map_flex_1_18.swc presente nella cartella lib/.
Possiamo aggiungere la libreria al build path sia tramite la finestra di gestione delle proprietà del progetto (come mostrato in figura), sia copiando il file SWC all'interno della cartella libs/ del nostro progetto.
Iniziamo a sviluppare, quindi, una semplice applicazione che permette di ricercare un indirizzo e di centrare la mappa sulla relativa posizione. Il component che conterrà la mappa è un semplice contenitore di tipo UIComponent:
<mx:UIComponent id="mapContainer"
width="100%" height="100%"
resize="mapContainerResize(event);" y="75" />
Il component di Google per gestire la mappa ha necessità di essere inizializzato: è necessario specificare l'Api Key, aggiungere i controlli per lo zoom o per selezionare la tipologia di mappa (stradale, satellite, ibrida) e bisogna registrare l'event listener sull'evento MapEvent.MAP_READY
Di seguito è riportato il codice del metodo che si preoccupa di effettuale l'inizializzazione dell'oggetto Map e di aggiungere la mappa al contenitore mapContainer. Il metodo deve essere invocato quando l'applicazione termina il caricamento (si può sfruttare l'evento CreationComplete). Da notare anche l'aggiunta dei controlli per lo Zoom e il MapType.
Sull'oggetto Map
eventListener
MapEvent.MAP_READY
Infatti, quando il component ha terminato il caricamento dobbiamo instanziare un oggetto di tipo ClientGeocoder che è fornito dalla libreria che stiamo utilizzando e che serve ad effettuare la traduzione di un dato geografico (come ad esempio il nome di una strada) in coordinate geografiche (latitudine e longitudine).
Per inizializzare l'oggetto che si deve preoccupare di effettuare il geocoding è necessario dichiarare due event listener, uno per gestire i risultati positivi delle richieste e uno per gestirne gli errori.
private function onGMapReady(evt:MapEvent) : void {
geocoder = new ClientGeocoder();
geocoder.addEventListener(GeocodingEvent.GEOCODING_SUCCESS, geocoderResult);
geocoder.addEventListener(GeocodingEvent.GEOCODING_FAILURE, geocoderFault);
}
Quindi scriviamo i due event listener: per l'evento che gestisce i risultati del geocoding dobbiamo centrare la mappa nel punto che otteniamo come risultato della richiesta, mentre per l'evento che gestisce gli errori facciamo visualizzare un popup con un messaggio di errore.
private function geocoderResult(evt:GeocodingEvent):void {
var result:Placemark = GeocodingResponse(evt.response).placemarks[0];
googleMap.setCenter(result.point, 16);
}
private function geocoderFault(evt:GeocodingEvent):void {
Alert.show("Si è verificato un errore durante la ricerca: " + evt.name);
}
A questo punto, possiamo gestire la ricerca di una città o di un indirizzo: siccome abbiamo già dichiarato gli event listener per gestire i risultati di una richiesta di geocoding dobbiamo solo implementare il metodo che effettua la richiesta.
Effettuare un richiesta di geocoding è molto semplice: bisogna soltanto invocare il metodo geocode()
ClientGeocoder
private function onBtnGoToClick(evt:MouseEvent) : void {
geocoder.geocode(tiAddress.text);
}
Di seguito è riportato il codice completo dell'esempio. Tra i tag <fx:Declarations>
fx:String
apikey.txt
APIKEY
Map()
<?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/mx"
creationComplete="init();">
<fx:Declarations>
<fx:String id="APIKEY" source="apikey.txt" />
</fx:Declarations>
<fx:Script>
<![CDATA[
import com.google.maps.LatLng;
import com.google.maps.Map;
import com.google.maps.MapEvent;
import com.google.maps.controls.MapTypeControl;
import com.google.maps.controls.PositionControl;
import com.google.maps.controls.ZoomControl;
import com.google.maps.services.ClientGeocoder;
import com.google.maps.services.GeocodingEvent;
import com.google.maps.services.GeocodingResponse;
import com.google.maps.services.Placemark;
import mx.controls.Alert;
import mx.events.ResizeEvent;
private var googleMap:Map;
private var geocoder:ClientGeocoder;
private function init() : void {
googleMap = new Map();
googleMap.key = APIKEY;
googleMap.addEventListener(MapEvent.MAP_READY, onGMapReady);
googleMap.setSize(new Point(mapContainer.width, mapContainer.height));
googleMap.addControl(new ZoomControl());
googleMap.addControl(new MapTypeControl());
mapContainer.addChild(googleMap);
}
private function onGMapReady(evt:MapEvent) : void {
geocoder = new ClientGeocoder();
geocoder.addEventListener(GeocodingEvent.GEOCODING_SUCCESS, geocoderResult);
geocoder.addEventListener(GeocodingEvent.GEOCODING_FAILURE, geocoderFault);
}
private function geocoderResult(evt:GeocodingEvent):void {
var result:Placemark = GeocodingResponse(evt.response).placemarks[0];
googleMap.setCenter(result.point, 16);
}
private function geocoderFault(evt:GeocodingEvent):void {
Alert.show("Si è verificato un errore durante la ricerca: " + evt.name);
}
private function onBtnGoToClick(evt:MouseEvent) : void {
geocoder.geocode(tiAddress.text);
}
private function mapContainerResize(evt:ResizeEvent):void {
if (googleMap) {
googleMap.setSize(new Point(mapContainer.width, mapContainer.height));
}
}
]]>
</fx:Script>
<mx:ApplicationControlBar dock="true" width="100%" x="0" y="0">
<mx:Form styleName="plain">
<mx:FormItem label="Address:" direction="horizontal">
<mx:TextInput id="tiAddress" text="" />
<mx:Button id="btnGoTo" label="Vai a" click="onBtnGoToClick(event);" />
</mx:FormItem>
</mx:Form>
</mx:ApplicationControlBar>
<mx:UIComponent id="mapContainer" width="100%" height="100%"
resize="mapContainerResize(event);" y="73"/>
</s:Application>
Nell'esempio completo possiamo notare, oltre alle dichiarazioni degli oggetti di tipo Map
ClientGeocoder
mapContainerResize
ApplicationControlBar
Posizionare i marker sulla mappa
Dopo aver realizzato la prima modalità di interazione con le Google Maps, ci focalizziamo sulla possibilità di posizionare dei marker sulle mappe. Partendo dall'esempio che abbiamo appena terminato di sviluppare, vogliamo posizionare il marker nel punto esatto che riceviamo come risultato della richiesta di geocoding.
Modifichiamo il metodo geocoderResult aggiungendo il codice necessario al posizionamento del marker. Di seguito è riportato il codice modificato.
Quando riceviamo il risultato della richiesta di geocoding, dopo aver posizionato il centro della mappa, creiamo un marker
Marker
LatLng
Successivamente dichiariamo l'event listener sul click del marker
InfoWindow
Alla fine dobbiamo aggiungere il marker alla mappa
addOverlay(marker)
googleMap