In merito al progetto iDem ho lavorato con le API v.3 di Google Maps ed il sistema di localizzazione del visitatore. Sfruttando alcune funzionalità dei browser moderni, inclusi molti di quelli installati nei nostri dispositivi mobili (soprattutto Android), è possibile identificare con discreta precisione da quale zona arriva il nostro visitatore, presentando le risorse a lui più vicine.
Utilizzando poi chiamate asincrone (Ajax) è possibile aggiornare una Maps (…e non solo…) in maniera dinamica.
Passiamo subito alla parte del codice, in PHP e Javascript. E’ necessario definire un DIV con id=”map” dove visualizzare la mappa:
<div id='map' style='width:520px; height: 300px; margin-top: 10px;'> Loading Google Maps... </div>
e poi incorporiamo il necessario codice Javascript nella nostra pagina:
<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\"> <html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'> <head> <meta http-equiv='content-type' content='text-html; charset=UTF-8'></meta> <link rel='stylesheet' type='text/css' href='http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.1/themes/base/jquery-ui.css'> <script type='text/javascript' src='http://maps.google.com/maps/api/js?sensor=true'></script> <script type='text/javascript' src='https://ajax.googleapis.com/ajax/libs/jquery/1.6.0/jquery.min.js'></script> <script src='http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/jquery-ui.min.js'></script> <link href='http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/themes/base/jquery-ui.css' rel='stylesheet' type='text/css'/> <script type='text/javascript' src='http://code.google.com/apis/gears/gears_init.js'></script> ...
P.S. Google Gears è consigliato nel caso non sia possibile utilizzare i metodi nativi W3C nella localizzazione dell’utente.
Nelle pagine dove vogliamo utilizzare il sistema descritto è poi necessario inserire questo javascript:
<script type='text/javascript'> $(document).ready(function() { var initialLocation; var defaultLoc = new google.maps.LatLng(41.87194,12.56738); // Visualizza tutta l'Italia var browserSupportFlag = new Boolean(); var mapOptions = { zoom: 5, mapTypeId: google.maps.MapTypeId.ROADMAP, center: defaultLoc }; var map = new google.maps.Map(document.getElementById('map'),mapOptions); // Try W3C Geolocation (Preferred) if(navigator.geolocation) { browserSupportFlag = true; navigator.geolocation.getCurrentPosition(function(position) { initialLocation = new google.maps.LatLng(position.coords.latitude,position.coords.longitude); map.setCenter(initialLocation); map.setZoom(10); }, function() { map.setCenter(initialLocation); }); // Try Google Gears Geolocation } else if (google.gears) { browserSupportFlag = true; var geo = google.gears.factory.create('beta.geolocation'); geo.getCurrentPosition(function(position) { initialLocation = new google.maps.LatLng(position.latitude,position.longitude); map.setCenter(initialLocation); map.setZoom(10); }, function() { map.setCenter(initialLocation); }); // Browser doesn't support Geolocation } else { map.setCenter(initialLocation); } var geocoder = new google.maps.Geocoder(); google.maps.event.addListener(map, 'idle', showMarkers); function showMarkers() { // get viewport bounds var southWestLat = map.getBounds().getSouthWest().lat(); var southWestLng = map.getBounds().getSouthWest().lng(); var northEastLat = map.getBounds().getNorthEast().lat(); var northEastLng = map.getBounds().getNorthEast().lng(); $.ajax({ type: 'POST', url: 'ajaxCb.php', dataType: 'json', data: ({'action':'getGroupMarkers', 'southWestLat' : southWestLat , 'southWestLng' : southWestLng , 'northEastLat' : northEastLat , 'northEastLng' : northEastLng}), success: function(groups) { groupsMap = groups.data; var markers=new Array(); var infowindow = new google.maps.InfoWindow({ content: "Loading..." }); for (var group in groupsMap){ if(typeof(groupsMap[group]) == 'object') { var center = new google.maps.LatLng(groupsMap[group].lat, groupsMap[group].lng); var groupOptions = { strokeColor: '#FF0000', strokeOpacity: 0.6, strokeWeight: 2, fillColor: '#FF0000', fillOpacity: 0.25, map: map, center: center, radius: groupsMap[group].radius }; var groupCircle = new google.maps.Circle(groupOptions); markers[group] = new google.maps.Marker({ position: center, map: map, title: groupsMap[group].name, html: "<h3><img src='/avatar/"+groupsMap[group].avatar+"' class='icon'> <a href='/group/"+groupsMap[group].id+"'>"+groupsMap[group].name+"</a></h3><p>"+groupsMap[group].description+"</p>" }); google.maps.event.addListener(markers[group], 'click', function () { infowindow.setContent(this.html); infowindow.open(map, this); }); } } }); } }); });</script>
Come potete vedere, ogni qualvolta l’utente si muove nella mappa viene generato un evento che effettua una chiamata ajax ad ajaxCb.php con 5 parametri POST:
'action':'getGroupMarkers', 'southWestLat' : southWestLat, 'southWestLng' : southWestLng, 'northEastLat' : northEastLat, 'northEastLng' : northEastLng
Nel file ajaxCb.php ci prepariamo a soddisfare adeguatamente la richiesta:
$ajaxAction = $_POST["action"]; function isBetween($numToCheck, $high, $low) { if($numToCheck <= $low) return false; if($numToCheck >= $high) return false; return true; } if($ajaxAction == 'getGroupMarkers') { $SW_Lat = $_POST['southWestLat']; $SW_Lng = $_POST['southWestLng']; $NE_Lat = $_POST['northEastLat']; $NE_Lng = $_POST['northEastLng']; $data = array(); $result = DB_Query("SELECT ID,Name,Avatar,Description,Place FROM Groups AS t1 WHERE LENGTH(Place) > 0;"); if(mysql_num_rows($result) > 0) { while($row = mysql_fetch_array($result, MYSQL_ASSOC)) { $groupId = $row["ID"]; $groupName = stripslashes($row["Name"]); $groupAvatar = stripslashes($row["Avatar"]); $groupDescription = stripslashes($row["Description"]); $groupPlace = unserialize(stripslashes($row["Place"])); $groupPlaceLat = $groupPlace["Latitude"]; $groupPlaceLng = $groupPlace["Longitude"]; if(isBetween($groupPlaceLat, $NE_Lat, $SW_Lat) && isBetween($groupPlaceLng, $NE_Lng, $SW_Lng)) { array_push($data,array('id'=>$groupId, 'name'=>$groupName, 'avatar'=>$groupAvatar, 'description'=>$groupDescription, 'lat'=>$groupPlaceLat, 'lng'=>$groupPlaceLng, 'radius'=>500); } } } echo json_encode(array('status'=>'success', 'data'=>$data)); }
Provo a spiegare in poche parole come funziona il sistema. L’evento generato quando l’utente si muove nella mappa invia le coordinate Nord-Est e Sud-Ovest dell’area visualizzata.
Da queste due coordinate posso fare una ricerca di tutti gli elementi che sono in quella zona semplicemente verificando se la Latitudine e la Longitudine di X è tra NE e SW:
if(isBetween($groupPlaceLat, $NE_Lat, $SW_Lat) && isBetween($groupPlaceLng, $NE_Lng, $SW_Lng)) {
A questo punto, se l’oggetto è nella zona, aggiungo i valori che voglio riportare sulla mappa ad una struttura di array pronta per essere condificata in JSON ed inviata al browser per la visualizzazione. Nell’esempio creo un marker per ogni gruppo a cui assegno una infoWindow per visualizzare, al click dell’utente, alcune informazioni formattate in HTML.
Per far capire meglio il funzionamento, ecco il tracciato delle chiamate tra il browser utente ed il server:
UTENTE: muove la mappa
AJAX: POST 200 text/xml http://www.i-dem.eu/ajaxCb.php
action getGroupMarkers
southWestLat 43.25568276691273
southWestLng 10.757850646484371
northEastLat 43.5549949798281
northEastLng 11.471961974609371
SERVER LAMP: risposta in formato JSON
{“status”:”success”,”data”:[{“id”:”1″,”name”:”xxxx”,”avatar”:”xxxx.jpg”,”description”:”Gruppo xxxx”,”lat”:43.3186614,”lng”:11.3305135,”radius”:11500},{“id”:”30″,”name”:”yyyy”,”avatar”:”yyyyy.jpg”,”description”:”Gruppo yyyy”,”lat”:43.3186614,”lng”:11.3305135,”radius”:2500}]}
BROWSER: interpreta la stringa ed aggiorna la mappa
L’unico “neo”, se così vogliamo definirlo, è che ogni volta che l’utente visualizza la nostra pagina riceve un alert tipo:
che lo avverte della richiesta di conoscere la propria posizione. E’ comunque una garanzia da un punto di vista della privacy che non dobbiamo trascurare.
1 comment
Ciao Michele.
Sono uno studente di sistemi di informazione geografica (GIS) e per la mia tesi sto facendo una applicazione web con le APIs di google e le APIs di geolocalizzazione. Non sono uno sperto di programmazione ma sto imparando. Ti volevo chiedere, come posso chiamare APIs di geolocalizzazione in una mappa di google? ho provato a costruire tutta la pagina con i codici che hai pubblicato ma non mi funziona, nemmeno carica la mappa base. Se per caso hai il codice completo html per provare almeno con Google Latitude.
Ti ringrazio.