Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Mappe personalizzate con le API di Google Maps e Flash Builder

Realizzare controlli Flash con mappe personalizzate utilizzando le API di Google Maps
Realizzare controlli Flash con mappe personalizzate utilizzando le API di Google Maps
Link copiato negli appunti

Google Maps deve il suo successo a tantissimi fattori, non ultima la possibilità offerta agli sviluppatori di integrare servizi geolocalizzati nelle applicazioni Web, grazie alle API. Le API (Application Programming Interface) sono librerie che fanno da "ponte" tra la nostra applicazione e le funzionalità offerte dal sistema Google Maps.

In questo articolo prendiamo confidenza con i concetti basilari delle API e l'implementazione di base sui progetti Flex. Ci occuperemo di come integrare le API Google Maps e il relativo oggetto all'interno dei nostri progetti Flex.

Le API per Flex e Flash richiedono come minimo la versione 9 di Flash o la versione 3 di Flex Builder, oppure l'utilizzo dell'SDK di Flex. Quest'ultimo è open source e quindi completamente gratuito, a differenza degli altri due che sono prodotti commerciali. La versione di prova di Flex Builder 3 è liberamente scaricabile da qui.

Per potere utilizzare le API di Google all'interno del nostro progetto occorre seguire i seguenti passi:

  • Richiedere la "Google Maps API Key"
  • Scaricare l'SDK (Software Development Kit)
  • Creare un nuovo progetto facendo riferimento alle librerie dell'SDK
  • Sviluppare l'interfaccia

In questo articolo ci occuperemo di tutto questo in modo molto dettagliato.

Perché le API di Google Maps funzionino è necessario che l'applicazione abbia un accesso ad internet. Le mappe e anche le componenti stesse delle API, sono scaricate dal sito di Google.

Richiedere la Google Maps Key

Per utilizzare le API di Google, come in genere accade per i servizi Web, dobbiamo identificarci con un codice, detto chiave. Prima di effettuare la richiesta è molto importante ricordare che la chiave è strettamente collegata al dominio che ospiterragrave; l'applicazione.

È possibile richiedere la propria chiave, una volta letti e accettati i termini e delle condizioni di utilizzo.

Figura 1. La richiesta della chiave
La richiesta della chiave

Il processo di generazione della chiave è immediato. La chiave visualizzata dovrà essere copiata e conservata: essa sarà poi utilizzata all'interno del nostro progetto.

Figura 2. Esempio chiave
Esempio chiave

Scaricare l'SDK

Il secondo passo consiste nello scaricare l'SDK di Google Maps. Una volta ottenuto l'SDK, estraiamo l'archivio in una cartella locale. Andrà benissimo la cartella dove flex pone il suo workspace, che per default è:

Path del workspace per Mac

Users/[nome utente]/Documenti/Flex Builder 3/

Path del workspace per Windows

C:Documents and Settings[nome utente]My DocumentsFlex Builder 3

L'SDK contiene due cartelle: lib, che contiene le librerie per Flex e per Flash e docs, in cui è presente la documentazione delle API.

Le librerie, in realtà, sono delle interfacce ai metodi delle API e quindi non contengono il codice dei metodi che invece rimane online sul sito di Google Maps. Questo per noi è un vantaggio perché significa che tutte le variazioni o correzioni fatte ai metodi delle API da parte di Google, saranno per noi completamente trasparenti: questi metodi verranno sempre scaricati dal sito all'avvio della nostra applicazione. Ovviamente ciò vale solo per i metodi delle API il cui riferimento è presente nella libreria.

Qualora Google rendesse disponibili dei nuovi metodi, non inclusi nella libreria, per poterli utilizzare dovremo scaricare nuovamente l'SDK, aggiornare i riferimenti nel nostro progetto, modificare i sorgenti dove intendiamo utilizzare i nuovi metodi, ricompilare il tutto e quindi ripubblicare il nostro componente sul sito.

Creazione del progetto

Avviamo il Flex e selezioniamo la voce di menu File > New > Flex Project. Dalla finestra che appare inseriamo "GoogleMapTest" nel campo Project Name e selezioniamo Web Application come tipo di applicazione. Infine clicchiamo su Next.

Figura 3. Creazione di un nuovo progetto Flex
Creazione di un nuovo progetto Flex

Indichiamo la cartella per le applicazioni compilate (lasciamo pure quella predefinita).

Figura 4. Cartella per i file compilati
Cartella per i file compilati

Ora possiamo importare le librerie di Google nel nostro progetto Flex. Scegliamo anzitutto la tab Library Path, poi clicchiamo su Add SWC....

Figura 5. Importare la libreria
Importare la libreria

Cerchiamo tra le cartelle quella in cui abbiamo salvato i file dell'SDK e infine selezioniamo la libreria per Flex map_flex_x_x.swc(x_x cambia a seconda della versione scaricata).

Figura 6. Selezionare il file dell'API
Selezionare il file dell'API

Sviluppo dell'Interfaccia

Una volta creato il progetto, aggiungiamo un nuovo componente di tipo Canvas (da menu File > New > MXML Component), lo chiamiamo MapHosts e impostiamo le dimensioni a 600 px in larghezza e 400 px in altezza.

Figura 7. Creare un componente MXML
Creare un componente MXML

Scegliamo di lavorare in modalit?esing utilizzando la tab in alto a sinistra:

Figura 8. Modalità Design
Design mode

Dal pannello Components (solitamente situato in basso a sinistra dell'ambiente di sviluppo), trasciniamo sullo stage un oggetto Map, lo troviamo nella cartella Custom. Appare un messaggio che ci segnala che non abbiamo ancora impostato la chiave di Google, non c'è da preoccuparsi: la inseriremo dopo.

Figura 9. L'oggetto Map nal pannello componenti
Inserire un oggetto Map

Sul pannello Flex Properties, solitamente in basso a destra dell'ambiente di sviluppo, indichiamo le proprietà del componente: inseriamo map nel campo id e impostiamo la modalità ridimensionamento automatico.

Figura 10. Pannello delle propriet?p>
Pannello delle propriet?style=

Una volta dimensionato il componente passiamo alla modalità Source e, finalmente inseriamo la chiave Google Maps nella proprietà key dell'oggetto Map.

<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="640" height="400" xmlns:ns1="com.google.maps.*">
  
  <ns1:Map left="0" right="0" top="0" bottom="0" 
           id="map" key="[la nostra key]"/>
	
</mx:Canvas>

Abbiamo praticamente finito, non ci rimane che importare il componente nel resto del progetto. Apriamo la pagina principale in modalità Design e trasciniamo dal pannello componenti il componente MapHost, che abbiamo creato.

Figura 11. Importare il componente nell'applicazione
Importare il componente nell'applicazione

Mandiamo in esecuzione il progetto. Se non abbiamo commesso errori possiamo già utilizzare la mappa: pur non avendo inserito nessun codice né impostato nessuna proprietà sull'oggetto, la nostra applicazione risponde già agli eventi del mouse. In particolare facendo doppio click sulla finestra, si aumenterà lo zoom corrente e, trascinando il mouse tenendo premuto il pulsante sinistro, possiamo scorrere la mappa.

L'oggetto Map

In questa parte dell'articolo ci occupiamo dell'oggetto principale delle API di Google Maps: Map. In particolare vedremo:

  • il codice per creare l'oggetto Maps e personalizzarlo
  • come navigare la mappa attraverso i controlli predefiniti

Creazione e personalizzazione della mappa

L'oggetto Map eredita da flash.display.Sprite e quindi è direttamente inseribile nello stage o in un qualsiasi oggetto contenitore, proprio come un qualunque controllo Flex.

Nella filosofia object oriented, quando si intende personalizzare un oggetto, in genere, si sceglie tra due comportamenti (pattern):

  1. creare l'oggetto ereditando dall'oggetto che si vuole personalizzare (subclass)
  2. inserire una istanza dell'oggetto da personalizzare in un nuovo oggetto (wrap)

Solitamente si preferisce il primo schema quando l'oggetto da personalizzare è stato creato da noi o quando si conosce molto bene, si sceglie l'altro quando viene meno una di queste condizioni o quando si vuole controllare le proprietà da esporre dell'oggetto incorporato.

Scegliamo il secondo pattern e creaimo una classe che estenda Canvas e incorpori una istanza di Map.

L'oggetto Map possiede un solo costruttore, quello di default (senza parametri). Quindi nessuna personalizzazione delle mappe potrà essere effettuata sul costruttore; invece vedremo come utilizzare il metodo setInitOptions. La chiamata a questo metodo, deve essere effettuata dopo che la mappa sia stata preinizializzata.

Come facciamo a sapere quando l'oggetto è stato preinizializzato? In Flex, tutti gli oggetti che richiedono un utilizzo intenso di risorse, siano esse locali o remote, agiscono in modalità asincrona. Un oggetto contenitore lancia l'azione di un oggetto figlio e non aspetta che essa venga conclusa. L'oggetto figlio procede con l'azione finché non l'ha terminata poi manda un segnale all'oggetto contenitore: un evento. Questo evento era stato associato ad un metodo detto "di callback", in cui viene stabilito il comportamento del contenitore al termine dell'azione del figlio.

In questa lezione useremo due funzioni di callback associate a due azioni dell'oggetto Map: useremo la prima, per sapere quando l'oggetto è stato preinizializzato, la seconda per sapere quando l'inizializzazione è terminata. Questi sono due tra i più importanti eventi dell' oggetto map da intercettare.

Il codice

Veniamo adesso al codice. Creiamo un un nuovo progetto Flex di tipo Web Application e importiamo le librerie Google Maps. Successivamente creiamo una nuova classe (MapHostScript) che estenda mx.containers.Canvas ed impostiamo it.html.googlemaps come nome di package.

Figura 12. Creare una nuova classe ActionScript
Nuova classe ActionScript

L'ambiente di sviluppo ci prepara il codice:

package it.html.googlemaps
{
  import mx.containers.Canvas;
  
  public class MapHostScript extends Canvas
  {
    public function MapHostScript()
    {
      super();
    }
  
  }
}

Ora aggiungiamo gli import necessari nell'header della classe, all'interno delle dichiarazioni del package.

package it.html.googlemaps
{
  // la classe base
  import mx.containers.Canvas; 
  
  // import delle classi di Google
  import com.google.maps.LatLng;
  import com.google.maps.Map;
  import com.google.maps.MapEvent;
  import com.google.maps.MapOptions;
  import com.google.maps.MapType;
  import com.google.maps.controls.ControlPosition;
  import com.google.maps.controls.MapTypeControl;
  import com.google.maps.controls.MapTypeControlOptions;
  import com.google.maps.controls.PositionControl;
  import com.google.maps.controls.ZoomControl;
  import com.google.maps.interfaces.IControl;

  // import della nozione di Punto
  import flash.geom.Point;

Ora aggiungiamo alla classe una variabile privata di istanza di tipo Map e la chiamiamo _map, che inizializziamo nel costruttore, subito dopo la chiamata al costruttore della classe base. Qui inseriamo nella proprietà key il valore della chiave ottenuta da Google.

  public class MapHostScript extends Canvas
  {
    // Variabile di istanza di tipo Map
    private var _map:Map
    
    // Costruttore
    public function MapHostScript()
    {
      super();
      
      // istanziamo _map
      _map = new Map();
      
      // impostiamo la chiave ottenuta da Google
      _map.key="ABQIAAAALKrOMe- etc"
    

È importante impostare da subito la chiave per ottenere la corretta inizializzazione dell'oggetto ed evitare errori come quello in figura:

Figura 13. Errore chiave non impostata
Il metodo setCenter

Sempre nel costruttore, aggiungiamo la mappa come "child" della nostra classe. Questo passaggio è fondamentale, se ce ne dimenticassimo non avremmo nessuna mappa da visualizzare.

      // aggiungiamo la mappa al contenitore
      this.addChild(_map);

Subito dopo impostiamo il listener dell'evento MAP_PREINITIALIZE della mappa e stabiliamo che sarà gestito da una funzione di callback, chiamata mappaPreInizializzata.

      // aggiungiamo il gestore dell'evento MAP_PREINITIALIZE
      _map.addEventListener(MapEvent.MAP_PREINITIALIZE,mappaPreIinizializzata);

Per convenienza, eliminiamo anche la politica di visualizzazione delle eventuali barre di scorrimento orizzontali e verticali dell'oggetto Canvas. Infine, impostiamo la dimensione della nostra mappa con il metodo setSize a 600x600 pixel, per questo ci serviamo della nozione Point che abbiamo importato all'inizio.

      // disabilitiamo gli scroll orizzontale e verticale del Canvas
      this.horizontalScrollPolicy = "off";
      this.verticalScrollPolicy = "off";
      
      // impostiamo la dimensione della mappa
      _map.setSize(new Point(600,600));
    }

Finalmente chiudiamo il costruttore e scriviamo il gestore dell'evento di pre inizializzazione. Definiamo mappaPreInizializzata come metodo privato che accetti come parametro un evento di tipo MapEvent e non ritorni valori (void).

Il callback viene lanciato dopo che Google ha verificato la nostra chiave e ci ha permesso di utilizzare le mappe. È in questo momento possiamo utilizzare il metodo setInitOptions, per inizializzare i parametri della mappa.

Infatti setInitOptions accetta come parametro un oggetto del tipo MapOptions, in cui specificare caratteristiche come la posizione iniziale, lo zoom o l'utilizzo di tastiera e mouse per la navigazione della mappa. L'elenco di tutte le proprietà lo troviamo nella documentazione dell'SDK.

Nel nostro esempio utilizziamo le caratteristiche che ci sembrano fondamentali per usare una mappa:

  • center, di tipo LatLng;
  • zoom, di tipo numerico;
  • mapTypes, di tipo Array;
  • mapType, che è un valore della enumerazione MapType.

La proprietà center serve per impostare la coordinate iniziali della mappa. Il suo costruttore accetta tre parametri: i primi due sono rispettivamente la latitudine e la longitudine del punto; il terzo parametro, facoltativo, è di tipo booleano (true per default) ed indica se deve essere controllata l'esattezza dei due parametri precedenti.

I valori corretti per la latitudine sono compresi tra -90 e 90 gradi , mentre per la longitudione i valori devono essere compresi tra -180 e 180 gradi.

Attraverso la proprietà mapTypes, possiamo impostare i tipi di mappa con cui l'utente potrà interagire (Satellite, Fisica, Ibrida, Normale); gli elementi dell'array devono contenere, ognuno, uno dei valori della enumerazione MapType desiderati.

Utilizzeremo i valori di questa proprietà nell'oggetto MapTypeControl, che permettera di scegliere il tipo di mappa da visualizzare.

La proprieta mapType indica il tipo di mappa inizialmente visualizzata.

Ecco il nostro metodo per l'inizializzazione della mappa:

    // Callaback di preinizializzazione
    private function mappaPreInizializzata(event:MapEvent):void
    {
      // creiamo l'oggetto che conterrà le nostre impostazioni
      var options:MapOptions = new MapOptions();
      
      // la posizione iniziale della mappa
      var posizioneIniziale:LatLng = new LatLng(37.3, 14.3);
      
      // lo zoom
      var zoom:Number = 7;
      
      // i tipi di mappe possibili del nostro oggetto
      var mapTypes:Array = new Array();

      mapTypes[0] = MapType.PHYSICAL_MAP_TYPE;
      mapTypes[1] = MapType.SATELLITE_MAP_TYPE;
      mapTypes[2] = MapType.HYBRID_MAP_TYPE;
      mapTypes[3] = MapType.NORMAL_MAP_TYPE;
      
      // impostiamo le proprietà dell'oggetto
      options.center   = posizioneIniziale;
      options.zoom     = zoom;
      options.mapTypes = mapTypes;
      
      // tipo di mappa iniziale
      options.mapType = MapType.SATELLITE_MAP_TYPE;
      
      // ecco la chiamata al metodo di inizializzazione
      _map.setInitOptions(options);
    }

Incorporare gli oggetti di controllo predefiniti

Vediamo adesso come rendere navigabile la mappa (zoom, scorrimento etc.) attraverso l'uso degli oggetti predefiniti del tutto simili a quelle riscontrati GoogleEarth. Verificando sulla documentazione dell'SDK, l'oggetto Map può contenere oggetti che ereditano da ControlBase ed implementano l'interfaccia IControl.

Figura 14. Il metodo addControl
Il metodo addControl

I controlli inseribili sono quelli appartenenti al package com.google.maps.controls e che, ovviamente, implementano l'interfaccia IControl. Questi oggetti sono:

  • MapTypeControl
  • NavigationControl
  • OverviewMapControl
  • PositionControl
  • ScaleControl
  • ZoomControl

Ognuno di questi controlli, può essere inserito, dopo averne creato una istanza, come child dell'oggetto Map utilizzando il metodo addControl.

L'inserimento potrà avvenire in uno dei seguenti modi :

  1. nel costruttore dell'oggetto MapHostScript
  2. in una funzione di callback richiamata allo scatenarsi dell'evento MAP_READY
  3. a runtime

Come e quando inserire questi controlli è chiaramente una scelta progettuale. Volendo, si potrebbero creare a priori, nasconderli con il metodo setVisible e visualizzarli a richiesta con una CheckBox o un bottone.

Il costruttore di ognuno di questi oggetti, accetta come parametro l'oggetto inizializzatore corrispondente (null per default). Con questo parametro possiamo variare il punto di ancoraggio (in basso a destra piuttosto che in alto a sinistra), lo stile, la dimensione dei bottoni che lo compongono etc.

Vediamo come inserire i controlli alla nostra mappa. Dobbiamo farlo quando rileviamo l'evento MAP_READY, perciò torniamo al costruttore del nostro oggetto e aggiungiamo un listener per questo evento e un metodo di callback che chiamiamo mappaInizializzata.

      // aggiungiamo il listener per sapere quando la
      // mappa è stata completamente inizializzata
      _map.addEventListener(MapEvent.MAP_READY, mappaInizializzata);

Infine scriviamo il metodo mappaInizializzata.

    // Callback dell'evento MapReady
    private function mappaInizializzata(event:MapEvent):void
    {
      // dimostriamo la personalizzazione per l'oggetto MapTypeControl
      var optionMapType:MapTypeControlOptions = new MapTypeControlOptions();
      
      optionMapType.position = new ControlPosition(ControlPosition.ANCHOR_TOP_RIGHT);
      optionMapType.buttonSize= new Point(60,15);
      optionMapType.buttonSpacing = new Point(1,1);
      optionMapType.buttonAlignment = MapTypeControlOptions.ALIGN_VERTICALLY;
      
      // creiamo l'oggetto passando i parametri di personalizzazione nel costruttore
      var mapTypeControl:MapTypeControl=new MapTypeControl(optionMapType);
      
      // aggiungiamo il controllo alla lista dei controlli dell mappa
      _map.addControl(mapTypeControl);
      
      // inseriamo gli altri oggetti inizializandoli con il costruttore di default
      // zoom Control
      var mapZoomControl:ZoomControl=new ZoomControl();
      _map.addControl(mapZoomControl);
      
      // Position Control
      var mapPositionControl:PositionControl=new PositionControl();
      _map.addControl(mapPositionControl);
    }

Abbiamo finito: possiamo testare il nostro componente. Selezioniamo il file principale della nostra applicazione e impostiamo la modalità Design. Dal pannello componenti, dovremmo vedere il nostro componente MapHostScript (se così non fosse, effettuare un build del progetto e riprovare), selezioniamolo e trasciniamolo sulla pagina.

Figura 15. Il componente MapHostScript nella finestra Componenti
Il componente nella finestra componenti

Posizioniamo il controllo a piacimento oppure impostiamo le proprietà x e y sul pannello proprietà.

All'avvio del progetto, se non ci sono errori, dovremmo vedere le mappa di tipo Satellite con al centro la Sicilia.

Figura 16. Mappa visualizzata
Il nostro progetto in esecuzione

Conclusioni

Google ha fatto le cose in grande: infatti sono disponibili, oltre al controllo Map, una serie di controlli accessori che possono "arricchire" la nostra mappa (d'altra parte questi controlli sono già disponibili nella versione Ajax delle API Google Maps). L'utilizzo dettagliato di questi controlli sar?ggetto di ulteriori approfondimenti.

In questo articolo introduttivo abbiamo preferito un approccio semplicistico alle API per ragioni didattiche. Un progetto "serio" prevedrebbe la creazione di classi che incapsulino l'oggetto Map di Google o derivate direttamente da esso, esponendo le proprietà più importanti dell'oggetto come proprietà pubbliche, possibilmente compatibili con il binding di Flex, e con il dispatch di eventi custom.

Ti consigliamo anche