Skip to content
jimilucio edited this page Nov 26, 2014 · 1 revision

Obiettivo del lab: lavorare con le informazioni sulla geolocalizzazione.

In questa esercitazione utilizzeremo le Geolocation API e vedremo come utilizzare queste informazioni implementando anche una mappa con i servizi di google. Alcuni browser possono bloccare l'accesso a queste informazioni se effettuiamo l'accesso diretto da file system, quindi avremo bisogno di un server http.

Step 1. Predisposizione

Per avere una situazione stabile e funzionante puoi aggiornare il tuo sorgente direttamente da questo comando:

# !bash
# git checkout geolocation-dev

checkout-geolocation-dev

Se tutto è andato bene, il messaggio restituito sarà il seguente: Switched to branch 'responsive-dev'

Altrimenti, visto che git tiene traccia di tutte le modifiche fatte in locale, per cambiare ramo dobbiamo prima annullare tutte le modifiche fatte sui file che abbiamo modificato. con il comando:

# git checkout *

Se vuoi mantenere le modifiche fatte, fai commit oppure clona il progetto in una nuova cartella! se invece hai creato nuovi file, devi prima cancellarli.

Se non vuoi utilizzare git puoi scaricare l'archivio zip da qui: https://github.com/marcocasario/codemotion2014/tree/geolocation-dev

Step 2. Analizziamo il server

Di seguito è possibile dare uno sguardo al server che utilizzeremo durante le esercitazioni:

/* variabili utilizzate dal server */
var http = require("http"),
    
    //modulo per la gestione delle URL
    url = require("url"),
    
    //modulo per la gestione dei percorsi 
    path = require("path"),
    
    //modulo per filesystem
    fs = require("fs"),
    
    //modulo websocket
    ws = require("nodejs-websocket"),
    
    //se la porta viene specificata come argomento la utilizza altrimenti imposta la porta di default 8888
    port = process.argv[2] || 8888,

    //impostiamo il file di default in caso di file non trovato
    file404 = '404.html';
 
/* webserver */
http.createServer(function(request, response) {
  var uri = url.parse(request.url).pathname
    , filename = path.join(process.cwd(), uri);
  
  /* Restituisce il content type in base all'estensione del file richiesta */
  function getContentType( filename ){
    //JS
    if (filename.indexOf('.js') != -1){return {'Content-Type': 'text/javascript'}
    //CSS
    }else if ( filename.indexOf('.css') != -1 ){return {'Content-Type': 'text/css'};
    //HTML
    }else if (filename.indexOf('.html') != -1 ){return {'Content-Type': 'text/html'};
    //JPG
    }else if (filename.indexOf('.jpg') != -1){return {'Content-type':'image/jpg'};
    //PNG
    }else if (filename.indexOf('.png') != -1){return {'Content-type':'image/png'};
    //GENERICO
    }else{return {'Content-Type': 'text/plain'};}
  }

  /* controlla se il path/file richiesto esiste e lo restituisce all'interno della response.
  * altrimenti restituisce il file 404
  */
  path.exists(filename, function(exists) {
    var nowTime = new Date(),
    contentType = '';
    //
    if(!exists) {filename = path.join(process.cwd(), file404);}
    //se non e' stato richiesto un file specifico restituisce il file index.html
    if (fs.statSync(filename).isDirectory()) {filename += '/index.html';}
    //legge il file ed inizializza l aresponse con il relativo content-type
    fs.readFile(filename, "binary", function(err, file) {
      //in caso di errore generico la response scrive il suo errore
      if(err) {
        response.writeHead(500, {"Content-Type": "text/plain"});
        response.write(err + "\n");
        response.end();
        return;
      }
      //scrive il log
      console.log(nowTime + "# Serve file:" + filename);
      //recupera il content-type
      contentType = getContentType( filename );
      //scrive la response con il content-type
      response.writeHead(200, contentType);
      //aggiunge il contenuto del file all'interno della response
      response.write(file, "binary");
      //chiude la response
      response.end();
    });
  });
}).listen(parseInt(port, 10));
console.log("Static file server running at\n  => http://localhost:" + port + "/\nCTRL + C to shutdown");

Step 3. Facciamo partire il server!

prima di far partire il server, commenta la riga 19, ci servira' nei prossimi moduli.

//modulo websocket
//ws = require("nodejs-websocket"),

Spostiamoci nella cartella principale del progetto, da qui lanciamo l'istanza del server http realizzato con node js con il seguente comando:

# node server.js

schermata 2014-04-07 alle 16 23 14

Step 4. Lavoriamo con le HTML5 Geolocation API

Apriamo il file js/company.js, ed aggiungiamo una nuova funzione per la nostra pagina web.

/* @company.js */
/* Comincia la nostra applicazione */
function loadDemo() {

}

All'interno della funzione loadDemo() aggiungiamo il controllo per verificare che il browser supporti le Geolocation API:

/* @company.js */
if(navigator.geolocation) {
...
...
...
}

Inseriamo all'interno dell'if il codice per caricare le informazioni sulla geolocalizzazione dell'utente che sta visitando la pagina utilizzando la funzione:

/* @company.js */

navigator.geolocation.getCurrentPosition(
   function(position) {
      //inserire il codice per aggiornare gli oggetti della pagina
   },
   function(error){
      alert('error reported' + error);
   }, {
      enableHighAccuracy: true,
      timeout : 30000
   }
);

Step 5. Modifichiamo il DOM

A questo punto possiamo cambiare il dom del nostro file company.html per ospitare le informazioni che ci arrivano dall'oggetto geolocation.

All'interno della

aggiungiamo dei div specificando una classe/id per ognuno di questi attributi:
  • accuracy
  • altitude
  • altitudeAccuracy
  • heading
  • latitude
  • longitude
  • speed
<!-- @company.html -->
...
<!-- inserisci tui il codice html -->
<div class="left">Accuracy: </div><div class="accuracy right">0</div><br>
<div class="left">Altitude: </div><div class="altitude right">0</div><br>
<div class="left">Altitude Accuracy: </div><div class="altitudeAccuracy right">0</div><br>
<div class="left">Heading: </div><div class="heading right">0</div><br>
<div class="left">Latitude: </div><div class="latitude right">0</div><br>
<div class="left">Longitude: </div><div class="longitude right">0</div><br>
<div class="left">Speed: </div><div class="speed right">0</div>
...

A questo punto all'interno della funzione javascript possiamo utilizzare jquery per popolare la nostra pagina web con le informazioni che ci arrivano dall'oggetto position.

/* @company.js */
...
//inserire il codice per aggiornare gli elementi della pagina
$('.accuracy').html( position.coords.accuracy );
$('.altitude').html( position.coords.altitude );
$('.altitudeAccuracy').html( position.coords.altitudeAccuracy );
$('.heading').html( position.coords.heading );
$('.latitude').html( position.coords.latitude );
$('.longitude').html( position.coords.longitude );
...

Quando sei pronto per fare il primo test, ricorda di aggiungere in fondo al tuo company.js il comando per inizializzare la funzione appena creata.

/* @company.js */

/* Comincia la nostra applicazione */
function loadDemo() {  
     ...
     ...
}

/* Inizializzazione del codice */
loadDemo();

Salva ed aggiorna la pagina http://localhost:8888 il risultato dovrebbe essere il seguente: browser_question

Cliccando su consenti, daremo tutte le informazioni sulla nostra posizione alla pagina. Il risultato sarà il seguente: infodiv

Se non dovesse comparire nulla potete impostare a mano questo settaggio: Gestire le impostazioni di Location nei Settings di Chrome


Integriamo le Google API

Step 1. Includiamo le librerie

Includiamo la libreria nel file company.html

<!-- Google Maps: change key to be your site's ID. -->
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=AIzaSyC3nvub6YdbJZLIKdNjcVDfh2vPbI60vus&sensor=false"></script>

Per funzionare, le api di google hanno bisogno di una APIKey, in questo caso è stata generata una generica che trovi già all'interno del codice.

Per maggiori informazioni sull'utilizzo delle google maps puoi visitare la pagina: https://developers.google.com/maps/documentation/javascript/tutorial

Step 2. Predisposizione dell'area per far ospitare la mappa

Dobbiamo predisporre la nostra pagina HTML ad ospitare la mappa da visualizzare all'interno della pagina. Sostituiamo la

con il nuovo codice:
<section id="map-canvas" class="map_section"></section>

Aggiungiamo una nuova regola all'interno del nostro css:

.map_section { width: 880px; background: #fff url('../img/loader.gif') center center no-repeat; border-bottom: 1px solid #ccc; padding: 0 40px; height: 440px;}

Step 3. Utilizzo delle librerie

Aggiungiamo una nuova funzione "loadMap" all'interno del nostro file company.js, questa funzione avrà lo scopo di richiedere le informazioni direttamente al servizio google maps e di restituirci la cartina con la nostra posizione direttamente all'interno del div "banner_section".

/* @company.js */
function loadMap(lon,lat){
  //definiamo le variabili utilizzate dalla funzione
  var myLatlng = new google.maps.LatLng(lat,lon),
  bound = new google.maps.LatLngBounds(),
  mapOptions = {},
  map = {};

  //creiamo il nuovo oggeto, che google utilizza per centrare la mappa.
  bound.extend( myLatlng ),

  //definiamo le opzioni per la creazione della mappa
  mapOptions = {
      center: bound.getCenter(),
      zoom: 12,
  };

  //Istanziamo il nuovo oggetto google.maps.Map();
  map = new google.maps.Map(document.getElementById("map-canvas"),
    mapOptions);

}

Richiamiamo la nostra funzione con le relative proprietà.

$('.longitude').html( position.coords.longitude );
//richiamiamo la funzione che richiede ed include la mappa passando la posizione attuale.
loadMap(position.coords.longitude, position.coords.latitude);

Aggiorniamo la nostra pagina web e visualizziamo il risultato ottenuto. schermata 2014-04-07 alle 17 04 32

Aggiungere il marker che indica all'interno della mappa dove ci troviamo! Aggiungendo queste poche righe dopo aver istanziato l'oggetto map (new google.maps.Map).

Tutte le informazioni su come aggiungere un marker all'interno di una mappa le puoi trovare qui: https://developers.google.com/maps/documentation/javascript/markers

/* @compan.js => loadMap() */

new google.maps.Marker({
      position: myLatlng,
      map: map,
      title:"Sono qui!",
      animation: 'bounce'
    });

Salva ed aggiorna la pagina http://localhost:8888

Il risultato dovrebbe essere molto simile a questo: mapsonpage

Step 4. Aggiungiamo il percorso per raggiungere la sede

Aggiungiamo delle nuove variabili all'interno della funzione loadMap. Impostiamo nei primi due latitudine e longitudine del punto di arrivo. La terza è il nostro oggetto google con il punto sulla mappa. directionsDisplay e directionsService richiamano i servizi google, istanziano gli oggetti necessari per richiedere la direzione e per effettuare il render sulla mappa.

var locationLatitude = 41.901556, locationLongitude = 12.502005, //Stazione di Roma Termini
  locationLatlng = new google.maps.LatLng(locationLatitude,locationLongitude),
  directionsDisplay = new google.maps.DirectionsRenderer(),
  directionsService = new google.maps.DirectionsService();

Successivamente scriviamo una nuova funzione all'interno della loadMap() che chiama le api di google e chiede il percorso da fare partendo dai due punti.

inserire la funzione dopo la dichiarazione delle variabili

function calcolaPercorso() {
    var request = {
      origin:myLatlng,
      destination:locationLatlng,
      travelMode: google.maps.TravelMode.DRIVING
    };
    directionsService.route(request, function(result, status) {
      if (status == google.maps.DirectionsStatus.OK) {
        directionsDisplay.setDirections(result);
      }
    });
  }

Come ultimo passaggio, rimuoviamo la definizione del nostro primo marker, aggiungendo invece la chiamata alla funzione appena definita per il render sulla nostra mappa:

//richiede le informazioni sul percorso
calcolaPercorso();
  
//imposta la mappa con l'oggetto directionsDisplay
directionsDisplay.setMap(map);

Salva ed aggiorna la pagina http://localhost:8888

Il risultato dovrebbe essere molto simile a questo: mapwithstreet