Tutorial para hacer un mapa interactivo la API de Google Maps

Este en mi tercer tutorial en Google Maps API v3. Vamos a mostrar como usar algunos características de google maps construyendo un mapa interactivo.

Creando un Mapa de viajes interáctivo usando el API de Google Maps.

Incluso tendrán la posibilidad de agregar nuevas ubicaciones en el mapa y ver las ubicaciones agregadas por otros. Se hará uso de MySQL. La base de datos almacena los valores de las diferentes ubicaciones que nos permitirá comenzar.

¿Qué características de google maps aprenderás?

  1. Agregar un mapa a tu sitio WEB.
  2. Agregar controles para el papa y  establecer las opciones para los controles.
  3. Responder a eventos.
  4. Agregar marcadores, estableciendo opcioes para los mismos, y establecer cambios dinámicamente.
  5. Geocodificación de ubicaciones.
  6. Crear informes

Prerequisitos.

La aplicación esta construida en HTML, PHP y JavaScript, también guarda las ubicaciones en una base de datos en MySQL. Tienes que tener conocimientos básicos de estas tecnologías para que te sea mas fácil la compresión de este turorial.

¿Que es lo que construiremos?

Se construirá un mapa interactivo, donde cualquiera puede ver las ubicaciones en el mapa y también agregar nuevas, fácilmente. La información que guardemos será la ubicación (Coordenadas, direcciones, una descripción, fotos y datos acerca de la persona que agrego la información). Los usuarios pueden agregar ubicaciones haciendo clic en el mapa y buscar información de las coordenadas y direcciones, filtradas del resto de la información. El usuario también puede ver la informacion de todas las ubicaciones de la base de datos. Para ver la información fácilmente, agregamos una lista que el usuario puede navegar y resaltar una ubicación en el mapa, cuando el usuario va con el muose sobre una ubicación.

Puedes ver la aplicación aqui (http://www.aniri.ro/tutorial-travelmap/) y también descargar el archivo desde aquí (http://www.aniri.ro/tutorial-travelmap/travel-map-source-code.zip).

Creando tablas para la base de datos.

Primero tenemos que crear una tabla en nuestra base de datos que guarde los datos acerca de las ubicaciones del mapa. Nosotros guardaremos la siguiente información por cada ubicación.

  1. Un nombre
  2. Una descripción
  3. Una foto
  4. Coordenadas: Latidud y logitud.
  5. Direcciones
  6. Info acerca del usuario que agregó la ubicacion, nombre y ubicación

El código creado para la tabla es el siguiente.

CREATE TABLE IF NOT EXISTS `locations` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` text NOT NULL,
`description` text NOT NULL,
`photo` text NOT NULL,
`latitude` double NOT NULL,
`longitude` double NOT NULL,
`address` text NOT NULL,
`user_name` text NOT NULL,
`user_location` text NOT NULL,
PRIMARY KEY (`id`));

Creando un layout para nuestra app.

Haremos uso de una Capa (Layout) simple. Mostraremos un título y alguna información de nuestra app en la parte superior de la página. Debajo de eso vamos a agregar tres columnas,  una para agregar ubicaciones (con un formulario para  agregar nuevas ubicaciones), una para el mapa (un  div llamado “map_canvas’) y otro para la lista de ubicaciones.

Conectando a la base de datos y obteniendo la info de las ubicaciones.

$server = "WRITE_SERVER_NAME_HERE";
$username = "WRITE_USERNAME_HERE";
$password = "WRITE_PASSWORD_HERE";
$database = "WRITE_DATABASE_NAME_HERE";
$connId = mysql_connect($server, $username, $password) or die("Cannot connect to server");
$selectDb = mysql_select_db($database, $connId) or die("Cannot connect to database");

No se olvide establecer sus datos.

Incluiremos este script en nuestro archivo principal y la conexion a la base de datos esta hecha. Añadiremos las siguiente lineas en nuestro archivo principal

<?php
include( 'connect.php' );
?>

Ahora necesitamos conocer el número de ubicaciones y la información de todas las ubicaciones en la base de datos.

Aqui esta como:

$locations = mysql_query("select * from locations");
$nr_locations = mysql_num_rows($locations);

En este pequeño segmento de código, tenemos hecho una simple consulta a la base de datos y recuperamos la información de la ubicaciones en la variable $locations. Tenemos también guardado en número de ubicaciones. Podemos imprimir esta información en un texto dispuesto en la parte superior de nuesta página.

También tenemos impresa la lista de ubicaciones, así.

<?php
// find locations from db
// save data for locations
$lats = "";          // string with latitude values
$lngs = "";          // string with longitude values
$addresses = "";     // string with address values
$names = "";         // string with names
$descrs = "";        // string with descriptions
$photos = "";        // string with photo names
$user_names = "";    // string with user names
$user_locs = "";     // string with user locations
$i=0;
// take the locations from the db one by one
while ($locat = mysql_fetch_array($locations))
{
  // add location data to info strings
  $lats .= $locat['latitude'].";;";
  $lngs .= $locat['longitude'].";;";
  $addresses .= $locat['address'].";;";
  $names .= $locat['name'].";;";
  $descrs .= $locat['description'].";;";
  $photos .= $locat['photo'].";;";
  $user_names .= $locat['user_name'].";;";
  $user_locs .= $locat['user_location'].";;";
  // show the location name in the right of the map with link that calls the highlightMarker function
?>
<a onmouseover="highlightMarker(<?php echo $i;?>)"><?php echo $locat['name'];?></a> <br/>
<?php
  $i++;
}
// hidden inputs for saving the info for all the locations in the db
?>
<input type="hidden" value="<?php echo $lats;?>" id="lats" name="lats"/>
<input type="hidden" value="<?php echo $lngs;?>" id="lngs" name="lngs"/>
<input type="hidden" value="<?php echo $addresses;?>" id="addresses" name="addresses"/>
<input type="hidden" value="<?php echo $names;?>" id="names" name="names"/>
<input type="hidden" value="<?php echo $descrs;?>" id="descrs" name="descrs"/>
<input type="hidden" value="<?php echo $photos;?>" id="photos" name="photos"/>
<input type="hidden" value="<?php echo $user_names;?>" id="user_names" name="user_names"/>
<input type="hidden" value="<?php echo $user_locs;?>" id="user_locs" name="user_locs"/>

Mostramos los nombres de las ubicaciones como link. Cuando el usuario va con el mouse sobre el link, la función highlightMarker de JavaScript es llamada. Revisaremos esto más tarde.

También tenemos información guardada acerca de las ubicaciones en campos ocultos (Hidden input). Usaremos esta información de los campos ocultos para mostrar las ubicaciones en el mapa.

Mostrando el mapa.

Para agregar el mapa primero debemos tener includida el Google Mapa API, De esta manera.

<script src="http://maps.google.com/maps/api/js?sensor=true"></script>

Ahora, definiremos las funciones de Javascript llamada ‘initialize’ para mostrar en el mapa los div creados para el mapa. Nosotros llamaremos esta función despues de que la página a sido cargada.

Aqui esta como llamaremos a la fnnción cuando la pagina esta cargada.

<body onload="initialize();">

Y aqui esta el código de la función:

<script>
var geocoder;
var map;
// initializing the map
function initialize()
{
  // define map center
  var latlng = new google.maps.LatLng(57.279043,29.355469);
  // define map options
  var myOptions =
  {
    zoom: 3,
    center: latlng,
    mapTypeId: google.maps.MapTypeId.HYBRID,
    scaleControl: true,
    navigationControl: true,
    navigationControlOptions: {
      style: google.maps.NavigationControlStyle.SMALL
    },
    mapTypeControl: true,
    mapTypeControlOptions: {
      style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
    }
  };
  // initialize map
  map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
  // add event listener for when a user clicks on the map
  google.maps.event.addListener(map, 'click', function(event) {
    findAddress(event.latLng);
  });
}
</script>

Para crear un mapa, primero tenemos que definir la opcion de mostrar el mapa. Tenemos establecido el nivel de zoom, el centro del mapa. Despues, establecemos los controles para mostrar en el mapa: control de escala, navegación y tipo de mapa y tenemos diferentes opciones para ello. Eleginmos mostrar un control de navegación pequeño y muestra el control del tipo de mapa como un Drop Down menu. Ustedes pueden ver todas las opciones disponbles para controloes en el API refence. (http://code.google.com/apis/maps/documentation/javascript/reference.html#MapTypeControlOptions)

Entonces, inicializamos el objeto mapa, y agregamos eventos para cuando el usuario cliclea en el mapa. Cuando este evento es activado, la función findAddress es invocada. La función toma como argumentos las coordenadas donde el usuario a hecho clic en el mapa.

// finds the address for the given location
function findAddress(loc)
{
  geocoder = new google.maps.Geocoder();
  if (geocoder)
  {
  geocoder.geocode({'latLng': loc}, function(results, status)
  {
    if (status == google.maps.GeocoderStatus.OK)
    {
      if (results[0])
      {
        address = results[0].formatted_address;
        // fill in the results in the form
        document.getElementById('lat').value = loc.lat();
        document.getElementById('long').value = loc.lng();
        document.getElementById('address').value = address;
      }
  }
  else
  {
    alert("Geocoder failed due to: " + status);
  }
  });
  }
}

La función usa el servicio de Geocodificación de Google Map para encontrar las direcciones correspondientes a las coodernadas dnode el usuario clickeo en el mapa. Cuando la función obtiene los datos de Google, estos son mostrados en el formulario.

// fill in the results in the form
document.getElementById('lat').value = loc.lat();
document.getElementById('long').value = loc.lng();
document.getElementById('address').value = address;

El usuario tiene que llenar el resto de los datos y se agrega una nueva a ubicación. No incluimos aqui el código de PHP para agregar una ubicación en la base de datos, Usted puede verlo en las fuentes descargadas.

Mostrando los markers (marcadores)

También tenemos que mostrar las ubicaciones en el mapa cuando se carga. Para ello llamaremos a más de una función cuando se carga la página.

<body onload="initialize(); addMarkers()">

Examinemos la función.

// initialize the array of markers
var markers = new Array();
// the function that adds the markers to the map
function addMarkers()
{
  // get the values for the markers from the hidden elements in the form
  var lats = document.getElementById('lats').value;
  var lngs = document.getElementById('lngs').value;
  var addresses = document.getElementById('addresses').value;

var names = document.getElementById(‘names’).value;
var descrs = document.getElementById(‘descrs’).value;
var photos = document.getElementById(‘photos’).value;
var user_names = document.getElementById(‘user_names’).value;
var user_locs = document.getElementById(‘user_locs’).value;
var las = lats.split(«;;»)
var lgs = lngs.split(«;;»)
var ads = addresses.split(«;;»)
var nms = names.split(«;;»)
var dss = descrs.split(«;;»)
var phs = photos.split(«;;»)
var usrn = user_names.split(«;;»)
var usrl = user_locs.split(«;;»)
// for every location, create a new marker and infowindow for it
for (i=0; i<las.length; i++)
{
if (las[i] != «»)
{
// add marker
var loc = new google.maps.LatLng(las[i],lgs[i]);
var marker = new google.maps.Marker({
position: loc,
map: window.map,
title: nms[i]
});
markers[i] = marker;
var contentString = [
‘<div>’,
‘<ul>’,
‘<li><a href=»#tab-1″><span>photo</span></a></li>’,
‘<li><a href=»#tab-2″><span>description</span></a></li>’,
‘<li><a href=»#tab-3″><span>location</span></a></li>’,
‘</ul>’,
‘<div>’,
‘<p><h1>’+nms[i]+'</h1></p>’,
‘<p><img src=»./photos/’+phs[i]+'»/></p>’+
‘</div>’,
‘<div>’,
‘<p><h1>’+nms[i]+'</h1></p>’,
‘<p>Added by: ‘+usrn[i]+’ from ‘+usrl[i]+'</p>’+
‘<p>’+dss[i]+'</p>’+
‘</div>’,
‘<div>’,
‘<p><h1>’+nms[i]+'</h1></p>’,
‘<p>Address: ‘+ads[i]+'</p>’+
‘<p>Location: ‘+loc+'</p>’+
‘</div>’,
‘</div>’
].join(»);
var infowindow = new google.maps.InfoWindow;
bindInfoWindow(marker, window.map, infowindow, contentString);
}
}
}
// make conection between infowindow and marker (the infowindow shows up when the user goes with the mouse over the marker)
function bindInfoWindow(marker, map, infoWindow, contentString)
{
google.maps.event.addListener(marker, ‘mouseover’, function() {
map.setCenter(marker.getPosition());
infoWindow.setContent(contentString);
infoWindow.open(map, marker);
$(«#tabs»).tabs();
});
}

Guardamos los marcadores en un arreglo.

Tomaremos la información acerca de las ubicaciones de los campos ocultos creados anteriormente. Creando nuevos marcadores para las nuevas ubicaciones. El título de cada marcador viene a ser el nombre de la ubicación. También crearemos la información a mostrar cuando el usuario pone el cursor del mouse sobre los marcadores.

La información mostrada acerca de los marcadores en el infowindow, se ha decidido usar codigo que se encontro en esta dirección (http://code.google.com/p/gmaps-samples-v3/source/browse/trunk/infowindow/tabs.html?r=78). Usando JQuiery y Jqueryui, mostramos también la inclusion de esos script en el trabajo.

<script src="jquery-1.4.2.min.js"></script>
<script src="jquery-ui-1.8rc3.custom.min.js"></script>
<link href="jquery-ui-1.8rc3.custom.css" rel="stylesheet" />

Y con esto terminamos.

Todo lo que resta hacer ahora es la funcion highlightMarker, es invocada cuando el usuario posiciona el mouse sobre el nombre de una ubicacion en la lista, Mostramos el contenido de la función.

// highlighting a marker
// make the marker show on top of the others
// change the selected markers icon
function highlightMarker(index)
{
  // change zindex and icon
  for (i=0; i<markers.length; i++)
  {
    if (i == index)

{
markers[i].setZIndex(10);
markers[i].setIcon(‘http://www.google.com/mapfiles/arrow.png’);
}
else
{
markers[i].setZIndex(2);
markers[i].setIcon(‘http://www.google.com/mapfiles/marker.png’);
}
}
}

La función toma como argumentos los index del arreglo de marcadores que se ha creado. La función highlightMarker hace que la selección de los marcadores se muestre en la parte superior de todos los marcadores y cambia los iconos. Hacer que los marcadores se muestren superiores a los otros, se logra cambiando el zindex.  El marcador con el valor mas grande es mostrado en la parte superior. Nosotros tenemos una conjunto de marcadores seleccionados de valores entre 10 y el resto de ellos a 2 (usando la función setZIndex). Para realizar los cambios a los iconos hacemos uso de la función SetIcon.

Puedes haber notado que también hemos agregado una pequeña función en Javascript para verificar si el usuario lleno los datos de la información del formulario de agregar. La función es llamada cuando el formulario es enviado. Verifica si los valores de los campos de los formularios han sido definidos, si no los encuentra asi, muestra un mensaje de error y previene que el formulario sea enviado.
y eso es todo. Tenemos ahora un mapa interactivo de viajes.