Google Maps JavaScript API v3 (assignatura WEC)

De wikijoan
Salta a la navegació Salta a la cerca

Introducció

Discover what you can do with the Google Maps APIs

  • Build location-based apps: Use Google tools and services to build innovative location-based apps.
  • Build maps for mobile apps: Build high performance apps that work on multiple mobile devices.
  • Visualize Geospatial Data: Create 3D images with the Earth API, heat maps, and more.
  • Customize your maps: Create customized maps that highlight your data, imagery, and brand


API Documentation

  • JavaScript API v3: Embed an interactive Google Map in your webpage using JavaScript.
  • Maps for Business: Google Maps API for Business provides Enterprise-ready application support for your mapping needs.
  • Google Maps SDK for iOS: Add Google Maps to your iOS apps, with rotation, tilt & 3D buildings. Launch the Google Maps app using a URL scheme.
  • Maps Android API: Add interactive, vector-based maps to your Android application.
  • Web Services: Use URL requests to access geocoding, directions, elevation, place and time zone information.
  • Places API: Access information about establishments, geographic locations, or prominent points of interest.
  • Maps Image APIs: Embed a Google Maps image or Street View panorama in your web page without requiring JavaScript. Static Maps - Street View.
  • Google Earth API: Take your visitors anywhere on the Earth without leaving your web page.

Referències

Exemples

Geocoding Service

Es tracta de resoldre un problema real. A partir d'una llista de direccions reals (per exemple, les direccions dels alumnes), es tracta de visualitzar aquestes dades en un mapa. Opcionalment, podem pensar quina és la millor ruta (la ruta òptima) per recórrer tots els punts.

NOTA: en aquest codi no es necessita una key de Google Maps.

Primer de tot ficarem a la base de dades una llista de direccions:

CREATE DATABASE direccions DEFAULT CHARACTER SET utf8;
#USE direccions;

#CREATE USER alumne IDENTIFIED BY 'keiL2lai';
#GRANT ALL ON direccions.* TO alumne@localhost identified by "keiL2lai";
#flush privileges;

drop table direccions;

CREATE TABLE direccions(
direccio varchar(200) not null,
year integer
);

insert into direccions values ('Roger de Flor 254 pral 2 08025 Barcelona (Barcelona) (España)', 2015);
insert into direccions values ('Rossello 484 08025 Barcelona (Barcelona) (España)', 2015);
insert into direccions values ('Sicilia 372 08025 Barcelona (Barcelona) (España)', 2015);
insert into direccions values ('Corcega 546 08025 Barcelona (Barcelona) (España)', 2015);
insert into direccions values ('Pi i Margall 22 08025 Barcelona (Barcelona) (España)', 2015);
insert into direccions values ('Corcega 596 08025 Barcelona (Barcelona) (España)', 2015);
insert into direccions values ('Sardenya 355 08025 Barcelona (Barcelona) (España)', 2015);
insert into direccions values ('Sardenya 476 08025 Barcelona (Barcelona) (España)', 2015);
insert into direccions values ('Rossello 423 08025 Barcelona (Barcelona) (España)', 2015);
insert into direccions values ('Rossello 431 08025 Barcelona (Barcelona) (España)', 2015);

insert into direccions values ('C/Nàpols 327 08025 Barcelona (Barcelona) (España)', 2016);
insert into direccions values ('C/Almeria 30 08014 Barcelona (Barcelona) (España)', 2016);
insert into direccions values ('C/Torrent de''n Vidalet 5 08012 (Barcelona) (España)', 2016);
insert into direccions values ('C/Provença 419 08025 Barcelona (Barcelona) (España)', 2016);
insert into direccions values ('C/Navas de Tolosa 348 08027 Barcelona (Barcelona) (España)', 2016);
insert into direccions values ('C/Plaça de la Concòrdia, 2 08120 (Barcelona) (España)', 2016);
insert into direccions values ('C/Granvia 419 08015 Barcelona (Barcelona) (España)', 2016);

insert into direccions values ('C/Mas Eastornell 08389 Palfolls (Barcelona) (España)', 2016);

Farem una llista de direccions dels alumnes. Els alumnes donaran la seva adreça/direcció postal en el format:

Roger de Flor n.254 pral 2ª 08025 Barcelona (Barcelona) (España)

Els fitxers necessaris de l'aplicatiu són:

open_db_adreces_alumnes.php

<?php
$conn = mysqli_connect("localhost", "alumne", "keiL2lai");

if (!$conn) {
    $log->error('Could not connect: ' . mysql_error());
    die('Could not connect: ' . mysql_error());
}

mysqli_select_db($conn, "direccions") or die('Could not select jbalmes database.');
mysqli_set_charset('utf8',$conn);
?>

close_db_adreces_alumnes.php

<?php
mysqli_close($conn);
?>

cercar_adreces_alumnes.php:

<?php
include("open_db_adreces_alumnes.php");

$sql = "select direccio from direccions";

$result=mysqli_query($conn,$sql);

if (!$result) {
    $message  = 'Invalid query: ' . mysqli_error() . "\n";
    die($message);
}

while($row = mysqli_fetch_assoc($result)) {	
	echo utf8_encode($row['direccio']).'<br />';
}

include("close_db_adreces_alumnes.php");
?>

geocoding_service_adreces_alumnes.htm:

<!DOCTYPE html>
<html>
	<head>
	<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
	<meta charset="utf-8">
	<title>Google Maps JavaScript API v3 Example: Geocoding Simple</title>
	<link href="https://google-developers.appspot.com/maps/documentation/javascript/examples/default.css" rel="stylesheet">

	<script>
		var geocoder;
		var map;
		var adreca = [];
		var adreca_arreglada = [];
		var adreces_diferents = [];;

		function initialize() {
			geocoder = new google.maps.Geocoder();
			var latlng = new google.maps.LatLng(41.404159, 2.159929);
			var mapOptions = {
				zoom: 13,
				center: latlng,
				mapTypeId: google.maps.MapTypeId.ROADMAP
			}
			map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
		}

		function codeAddress_1() {

			var length = adreca_arreglada.length;
			for (var i = 0; i < length; i++) {
				codeAddress_2(adreca_arreglada[i]);
			}
		}

		function codeAddress_2(vaddress) {
			var address = vaddress;
			geocoder.geocode( { 'address': address}, function(results, status) {
			if (status == google.maps.GeocoderStatus.OK) {
				map.setCenter(results[0].geometry.location);

				if (!array_contains(adreces_diferents, results[0].geometry.location)) {
					//és necessari el toString() per tal de què el que es guarda en l'array sigui realment un string i no un objecte de Google Maps!
					adreces_diferents.push(results[0].geometry.location.toString()); 
					//alert(adreces_diferents.length);
					//només afegim el marker si la direcció que ha trobat el servei de geocoding és nova. El problema és que les direccions que no es resolen bé es resolen amb una direcció que es va repetint...
					var marker = new google.maps.Marker({
						map: map,
						position: results[0].geometry.location
					});
				}

			//http://stackoverflow.com/questions/9805529/geocoding-api-over-query-limit
	        } else if (status === google.maps.GeocoderStatus.OVER_QUERY_LIMIT) {    
	            setTimeout(function() {
	                codeAddress_2(vaddress);
	            }, 200);
	        } else {
	            alert("Geocode was not successful for the following reason:" + status + ' ' + vaddress);
	        }

			});
		}

		function cercar_adreces()
		{
			var xmlhttp;
			var txt,x,xx,i;
			if (window.XMLHttpRequest)
			{// code for IE7+, Firefox, Chrome, Opera, Safari
			  xmlhttp=new XMLHttpRequest();
			}
			else
			{// code for IE6, IE5
				xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
			}

			xmlhttp.onreadystatechange=function()
			{
				if (xmlhttp.readyState==4 && xmlhttp.status==200)
				{
					txt=xmlhttp.responseText;
					//alert(txt);
					adreca=txt.split("<br />");
					adreca_arreglada = arreglar_adreces(adreca);
					codeAddress_1();
				}
			}
			xmlhttp.open("GET","cercar_adreces_alumnes.php");
			xmlhttp.send();

		}

		function array_contains(myarray,element) {
			for (var i = 0; i < myarray.length; i++) {
				if (myarray[i] == element) {
					//alert('si');
					return true;
				}
			}
		}

		function arreglar_adreces(adreces) {
			//el problema està en què s'han d'arreglar les adreces que tinc de la bd. 
			//Roger de Flor n.254 pral 2ª 08025 Barcelona (Barcelona) (España)
			//es resol incorrectament. S'ha de convertir a:
			//Roger de Flor 254 08025 Barcelona (Barcelona) (España) 
			var adreces2 = [];
			for (var i = 0; i < adreces.length; i++) {
				adreces2[i] = arreglar_adreca(adreces[i]);
			}
			return adreces2;
		}

		function arreglar_adreca(adreca) {
			var adreca2 = adreca;
			//hem de cercar on està el cp
			var poscp=adreca.indexOf("08"); //suposo que totes les adreces són de la província de Barcelona
			var adreca_temp = adreca.substr(0,poscp-1); 
			var adreca_temp2 = adreca.substr(poscp,adreca.length-1);
			var trobat_numeros = false;
			var trobat_caracter_especial = false;
			var pos_trobat_numeros = 0;
			var pos_trobat_caracter_especial;

			//el criteri per al cas particular de 'Roger de Flor n.254 pral 2ª' i similars és eliminar el 'n.' i, començant pel principi, 
			//buscar on comencen els números (en aquest cas '254') fins a trobar un caràcter especial (de moment: espai blanc, -).
			//aquesta funció és la que s'haurà de retocar en funció del format de les adreces que tingui.
			adreca_temp = adreca_temp.replace('n.','');
			//alert(adreca_temp);
			for (var i = 0; i < adreca_temp.length; i++) {
				//48: 0; ...; 57: 9; 32: espai en bland; 45: -
				if (trobat_numeros==false && (adreca_temp.charCodeAt(i)>=48 && adreca_temp.charCodeAt(i)<=57)) {
					pos_trobat_numeros = i; //trobem números
					trobat_numeros = true;
				}
				if (trobat_numeros == true && trobat_caracter_especial == false && (adreca_temp.charCodeAt(i)==32 || adreca_temp.charCodeAt(i)==45)) {
					pos_trobat_caracter_especial = i;
					trobat_caracter_especial = true;
				}

			}
			adreca_temp = adreca_temp.substr(0,pos_trobat_caracter_especial);
			adreca2 = adreca_temp.concat(" ");
			adreca2 = adreca2.concat(adreca_temp2);
			return adreca2;

		}

		function setCharAt(str,index,chr) {
			 if(index > str.length-1) return str;
			 return str.substr(0,index) + chr + str.substr(index+1);
		}

	</script>
	</head>
	<body>

	<div>
	<input type="button" value="Geocode"  onclick="cercar_adreces()" />
	</div>
	<div id="map-canvas" style="height:90%;top:30px"></div>
    <script async defer
    src="https://maps.googleapis.com/maps/api/js?key=*********&callback=initialize">
    </script>
	</body>
</html>

Dades GPS a Google Maps

Rutes gps.jpg

Avui en dia, amb els smartphones, tothom té a l'abast crear rutes GPS. Per exemple, el professor fa servir l'app Oruxmaps en un telèfon Android. Aquest aplicatiu pot generar fitxers de rutes GPS, que normalment tenen format XML. Un dels formats preferits és el format GPX, que no deixa de ser un fitxer XML.

D'altra banda tenim webs com ara wikiloc.com, http://ca.wikiloc.com/wikiloc/home.do, on podem descarregar i pujar rutes GPS (en format GPX entre d'altres).

Aquest aplicatiu que aquí presentem fa el següent:

  • en la carpeta rutes_gps/ hem ficat tots els nostres arxius gpx (nota: en tot cas els hem hagut de reanomenar amb extensió xml en un ordinador, en un altre ordinador no ha fet falta...)
  • l'aplicatiu web llegeix i carrega tots els fitxers de rutes que hi ha en aquesta carpeta (crida AJAX).
  • quan seleccionem una ruta es fa una crida AJAX per descarregar el fitxer XML i es pinta gràcies a la API de Google Maps. És necessari calcular el punt mig de la ruta per tal de que quedi centrar, i també és necessari ajustar el zoom per tal de que tota la ruta quedi dins el mapa.

No és un projecte especialment difícil, se't facilita el codi per tal de què el provis.

rutes_gps.php (llegeix el contingut de la carpeta rutes_gps/):

<?php

if ($handle = opendir('rutes_gps/')) {

    /* This is the correct way to loop over the directory. */
    while (false !== ($entry = readdir($handle))) {
	//if (strstr($entry, '.gpx')) {
	if (strstr($entry, '.xml')) {
			echo "<p>";
        	//echo "<a href='rutes_gps/$entry'>$entry</a><br />";
			echo "<a href=\"#\" onclick=\"pintar_ruta('rutes_gps/$entry')\">$entry</a><br />";
		//SimpleXML functions are part of the PHP core
		$xml = simplexml_load_file('rutes_gps/'.$entry)
			or die("Error: Cannot create object");
		

		foreach($xml->children() as $child)
			{
				if (!strstr($child->getName(),'trk')) {
				echo $child->getName() . ": " . $child . "<br>";
				}
			}
		echo "</p>";

	}
    }
    closedir($handle);
}
?>

Pots descarregar-te una carpeta amb rutes GPS:

rutes_gps.htm: és la pàgina principal i el punt d'entrada: http://localhost/rutes_gps.htm

<!DOCTYPE html>
<html>
	<head>
	<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
	<meta charset="utf-8">
	<title>Rutes GPS</title>
	<link rel="stylesheet" href="rutes_gps.css" type="text/css" />		


	<script>
	function carregar_rutes() {
		var xmlhttp;
		var txt,x,xx,i;
                xmlhttp=new XMLHttpRequest();

		xmlhttp.onreadystatechange=function() {
			if (xmlhttp.readyState==4 && xmlhttp.status==200) {
				txt=xmlhttp.responseText;
				document.getElementById('rutes').innerHTML=txt;
			}
		}
		xmlhttp.open("GET","rutes_gps.php",true);
		xmlhttp.send();
	}

	function pintar_ruta(url) {
		var xmlhttp;
		var txt,x,xx,i;
		if (window.XMLHttpRequest)
		  {// code for IE7+, Firefox, Chrome, Opera, Safari
		  xmlhttp=new XMLHttpRequest();
		  }
		else
		  {// code for IE6, IE5
		  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
		  }

			xmlhttp.onreadystatechange=function()
			  {
			  if (xmlhttp.readyState==4 && xmlhttp.status==200)
				 {
				 x=xmlhttp.responseXML.documentElement.getElementsByTagName("trkpt");
			  	var coordenades = new Array(x.length);
				var coordenadeslat_min=1000, coordenadeslat_max=0, coordenadeslat_total, coordenadeslat_mig;
				var coordenadeslong_min=1000, coordenadeslong_max=0, coordenadeslong_total, coordenadeslong_mig;

				for (var i = 0; i < x.length; i++) {
					coordenades[i] = new Array(2);
				}
				 for (i=0;i<x.length;i++) {
					//omplim una matriu
					coordenades[i][0] = x[i].attributes[0].value;
					coordenades[i][1] = x[i].attributes[1].value;

					if (coordenadeslat_min > coordenades[i][0]) coordenadeslat_min = coordenades[i][0];
					if (coordenadeslat_max < coordenades[i][0]) coordenadeslat_max = coordenades[i][0];
					if (coordenadeslong_min > coordenades[i][1]) coordenadeslong_min = coordenades[i][1];
					if (coordenadeslong_max < coordenades[i][1]) coordenadeslong_max = coordenades[i][1];
				}

				var bounds = new google.maps.LatLngBounds();
				var latlng = new google.maps.LatLng(coordenadeslat_min, coordenadeslong_min);
				bounds.extend(latlng);
				var latlng = new google.maps.LatLng(coordenadeslat_max, coordenadeslong_max);
				bounds.extend(latlng);

				var myLatLng_puntmig = bounds.getCenter();

				var mapOptions = {
					center: myLatLng_puntmig,
					mapTypeId: google.maps.MapTypeId.HYBRID
				};
				
				var map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
				map.fitBounds(bounds); //ajustem el mapa al contorn de les 4 cantonades, i podem conèixer el zoom.
				//alert(map.getZoom());

				var lineCoordinates = new Array(x.length);
				for (var i = 0; i < x.length; i++) {
					lineCoordinates[i] = new google.maps.LatLng(coordenades[i][0],coordenades[i][1]);
				}

				var line = new google.maps.Polyline({
					path: lineCoordinates,
					map: map
				});

			}
		}

		xmlhttp.open("GET",url,true);
		xmlhttp.send();
	}
	</script>

	</head>
	<body>
	<h1>Rutes GPS</h1>
	<div id="rutes">
	</div>
	<div id="map_canvas">
	Selecciona una ruta
	</div>
    <script async defer
    src="https://maps.googleapis.com/maps/api/js?key=*******&callback=carregar_rutes">
    </script>
	</body>
</html>

rutes_gps.css: un full d'estils adequat (adapta les mides de les capes a la resolució de la teva pantalla)

html, body {
	margin:0;
	padding:0;
}
body{
	color: #fff;
	font-family: "Trebuchet MS", "Lucida Grande", Arial, Helvetica, sans-serif;
	background: #222;
	margin: 0 40px;
	padding: 0;
	font-size: 0.8em;
	position: relative;
	text-align: left;

}

div#rutes
{
	position: absolute;
	top: 60px;
	left: 20px;
	width: 200px;
	padding: 10px;
	margin: 10px;
	font-size: 1em;
	background-color: #333;
}

div#map_canvas
{
	position: absolute;
	top: 60px;
	left: 260px;
	width: 1000px;
	height: 800px;
	padding: 10px;
	margin: 10px;
	background-color: #444;
}

a{
	color: #ff9000;
	text-decoration: none;
}

creat per Joan Quintana Compte, abril 2018