1. Code
  2. JavaScript

Indicaciones paso a paso con la API de Google Maps

Scroll to top
16 min read

Spanish (Español) translation by Kelly Gianella (you can also view the original English article)

En este tutorial, pasaremos por el proceso de creación de un pequeño widget que permite a los usuarios recuperar indicaciones paso a paso a una ubicación especificada. Usaremos la API de Google Maps, a través de JavaScript, para proporcionar esta funcionalidad bastante avanzada.

Final ProductFinal ProductFinal Product

Obtención de una clave de API

La única advertencia con el uso de Google Maps es que debemos solicitar una clave de API, pero este es un proceso bastante trivial si ya tiene una cuenta de Google / GMail. Desafortunadamente debido a los requerimientos de Google debemos desarrollar sobre el dominio que proporcionamos a Google, es decir, no podemos desarrollar en un servidor local. Afortunadamente para nosotros el proceso será rápido y no pasaremos mucho tiempo en el servidor en vivo. Además, asegúrese de almacenar la clave de API en un lugar seguro porque no pude encontrar una manera de recuperarlos una vez generados, aunque supongo que podría recrear uno.

La situación

Antes de sumergirnos en el código, permítanme discutir la razón detrás de esta idea. Como la mayoría de los desarrolladores, paso mucho tiempo en la web. Un subconjunto particular de sitios web que visito son empresas locales que ciertamente no tienen grandes recursos para dedicar al diseño web, pero espero que las personas que están desarrollando esos sitios vean artículos como este y se den cuenta de lo fácil que es incluir un mapa con todas las funciones en cualquier página web. Casi cualquier sitio web que representa a una pequeña empresa tiene una página dedicada a decirle a los usuarios cómo localizar su ubicación física. Muchas veces obtienes un mapa con su ubicación anclada en él, lo que no ayuda a los usuarios que no conocen el área. En este tutorial vamos a cambiar eso y permitir que los usuarios ingresen su dirección y obtengan indicaciones paso a paso a cualquier dirección que queramos.

Incluyendo la biblioteca Javascript de Google Maps

Ahora que la caja de jabón está fuera de camino vamos a buscar en el código. Lo primero que tenemos que hacer es incluir la biblioteca Javascript que contiene todos los métodos de Google Maps. Google probablemente generó este código cuando creó su clave de API, pero eso podría haber apuntado a la API de la versión 3 que todavía está en pruebas beta. Aquí está el enlace a la versión 2 de la API, asegúrese de insertar su clave de API. También vamos a incluir un archivo, aplicación.js que sostendrá nuestras funciones personalizadas, almacené la mía en un directorio a nivel raíz llamado js. El código siguiente va dentro de la sección head de la página.

1
<script src="https://maps.google.com/?file=api&v=2&key=INSERT_API_KEY_HERE" type="text/javascript"></script>
2
<script src="./js/application.js" type="text/javascript"></script>

El código HTML

En la sección de cuerpo de nuestra página necesitamos un marcado limitado. Repasaré brevemente los bits requeridos, y puedes mirar el código fuente para ver la pelusa que incluí en mi demo. El primer elemento es un div vacío con un ID de map_canvas, este es el marcador de posición al que apuntamos las llamadas de Google Maps y generará todo el marcado del mapa dentro de ese elemento.

1
<div id="map_canvas"></div>

A continuación, creé un div para contener la dirección de la organización y el formulario para que el usuario ingrese su dirección. Puede mirar sobre este código, pero es bastante simple y no es muy difícil discernir que se está reuniendo. Asegúrese de mirar mi CSS para ver cómo se estilizar en mi demostración.

1
<div id="addresses">
2
    <div class="address-panel">
3
        <h2>Our Address</h2>
4
        <address>
5
          1450 Jayhawk Blvd #223<br />
6
          Lawrence, KS<br />
7
          66045
8
        </address>
9
    </div>
10
11
    <div class="address-panel">
12
        <h2>Your Address</h2>
13
14
        <form action="./index.php" onsubmit="overlayDirections();return false;" method="post">
15
            <div>
16
              <label for="street">Street Address</label>
17
              <input id="street" name="street_address" type="text" />
18
            </div>
19
            <div>
20
              <div class="address-form-column">
21
                <label for="city">City</label>
22
                <input id="city" name="city" type="text" />
23
              </div>
24
25
              <div class="address-form-column">
26
                <label for="state">State</label>
27
                <select id="state" name="state">
28
                  <option value="AL">Alabama</option>
29
                  <option value="AK">Alaska</option>
30
                  <option value="AZ">Arizona</option>
31
                  <option value="AR">Arkansas</option>
32
                  <option value="CA">California</option>
33
                  <option value="CO">Colorado</option>
34
                  ...
35
                </select>
36
              </div>
37
38
              <div class="address-form-column">
39
                <label for="zip">Zip Code</label>
40
                <input id="zip" name="zip_code" type="text" maxlength="5" size="5" />
41
              </div>
42
            </div>
43
44
            <div class="button">
45
              <input name="submit" type="submit" value="Get Directions" />
46
            </div>
47
        </form>
48
    </div>
49
</div>

Tenga en cuenta que estamos enviando esta página a sí mismo esto es para que podamos procesar la página usando PHP si el usuario tiene JS deshabilitado. Si tienen JS habilitado queremos ejecutar una función, overlayDirections() que echaremos un vistazo un poco más adelante. La mayor parte de este código va al cuadro de selección que permite al usuario elegir su estado, lo he condensado por el bien de los que imprimen este artículo, pero puede tomar el código completo de la descarga. Otras notas interesantes es que establecemos el tamaño y la longitud máxima del campo de texto del código postal en 5. Lo último a tener en cuenta es que hemos asignado identificadores y nombres a todos los elementos de formulario.

Arranque y declaración de variables

Bien, ahora podemos pasar a la carne de este tutorial, el código JavaScript. Casi todas las llamadas que vamos a hacer provienen de la API de Google Maps a la que hicimos referencia anteriormente. Google proporciona una excelente documentación y código de ejemplo en su sitio web, así que asegúrese de revisarlo. Intentaré enlazar a páginas relevantes a medida que las uso.

Lo primero es que mientras tenemos nuestra página HTML abierta permite arrancar la función initialize estableciendo el atributo onload. Nota: esto se puede hacer en jQuery usando la función $(document).ready().

1
<body onload="initialize()">

Ahora vamos a pasar al archivo js/appication.js. Lo primero que tenemos que hacer es establecer algunas variables. Algún evangelista de código probablemente me perseguirá por declarar variables globales, pero creo que en este caso deberíamos estar bien. Te daré el código y luego explicaré cómo usaremos cada uno.

1
var gdir, fromAddress, toAddress;
  • gdir: contiene el objeto GDirections utilizado para obtener resultados de indicaciones de conducción y mostrarlos en un mapa y/o un panel de texto.
  • fromAddress: una cadena que contiene la dirección completa del usuario.
  • toAddress: una cadena que contiene la dirección de la empresa o organización

La función initialize()

La función initialize() que llamamos anteriormente se utilizará para crear el mapa en la página y colocar un marcador personalizado de nuestra ubicación.

1
/*
2
**
3
* Bootstrap function to setup map and apply
4
* custom company marker
5
*/
6
function initialize() {
7
  if (GBrowserIsCompatible()) {
8
    //settings
9
    var companyMarkerImage= "./images/jayhawk.gif";
10
    var companyLatLng     = new GLatLng(38.957101, -95.251469);
11
    var companyMarkerSize = new GSize(55, 52); //width, height
12
    
13
    toAddress = "1450 Jayhawk Blvd #223 Lawrence, KS 66045";
14
15
    var defaultZoomLevel  = 13;
16
    //end settings
17
18
    //setup elements
19
    map   = new GMap2(document.getElementById("map_canvas"));
20
    gdir  = new GDirections(map, document.getElementById("directions"));
21
22
    //error handler
23
    GEvent.addListener(gdir, "error", handleErrors);
24
25
    //set company marker
26
    var companyMarker = createMarker(companyLatLng, companyMarkerImage, companyMarkerSize);
27
28
    //set map center
29
    map.setCenter(companyLatLng, defaultZoomLevel);
30
    map.addOverlay(companyMarker);
31
  }
32
}

Lo primero que tenemos que hacer es comprobar si el navegador es compatible con Google Maps, y para ello Google proporciona el GBrowserIsCompatible() en su API. En esencia devuelve true si el navegador es compatible y nos permite pasar al resto de nuestra función. Decidí abstraer algunos de los valores a variables en la parte superior de la función para que esto pudiera ser fácilmente portado a muchas aplicaciones.

1
  //settings
2
  var companyMarkerImage= "./images/jayhawk.gif";
3
  var companyLatLng     = new GLatLng(38.957101, -95.251469);
4
  var companyMarkerSize = new GSize(55, 52); //width, height
5
  
6
  toAddress = "1450 Jayhawk Blvd #223 Lawrence, KS 66045";
7
8
  var defaultZoomLevel  = 13;
9
  //end settings

El companyMarkerImage es una cadena de la ubicación de una pequeña imagen que colocaremos en nuestra ubicación en el mapa. Esto es algo que creo que es un buen toque para tener un icono personalizado para representar su negocio que personalizará la vista genérica de Google Map. A continuación, companyLatLng contiene un objeto GLatLng correspondiente a un punto de latitud y longitud del mundo. No te quedes sin nada y compres un dispositivo GPS para obtener estos números que podemos usar maps.google.com. En el cuadro de búsqueda, escriba su dirección y cuando encuentre la ubicación, haga clic en el botón Vincular en la parte superior derecha del mapa. Desplácese por el primer cuadro de texto de la ventana modal y busque &sll=....

Puede copiar y pegar esas coordenadas en los parámetros de nuestro constructor GLatLng. Este es el punto del mapa donde colocaremos nuestra imagen personalizada. La siguiente variable, companyMarkerSize, contiene un objeto GSize que representa el ancho y el alto de la imagen de marcador personalizada. A continuación, establecemos toAddress, que es la dirección de la empresa. La variable final, defaultZoomLevel, simplemente indica al mapa lo que desea que el nivel de zoom predeterminado sea de 1 a 18.

1
  //setup elements
2
  map   = new GMap2(document.getElementById("map_canvas"));
3
  gdir  = new GDirections(map, document.getElementById("directions"));

La siguiente línea de código crea un objeto GMap2. Google describe esto como "la clase central en la API". Esto carga los datos del mapa y nos permite manipular lo que se muestra en el área del mapa. Toma un argumento un objeto DOM que apunta al elemento que contiene el mapa, #map_canvas. A continuación, establecemos gdir para contener el objeto GDirections. Esta es la interfaz que utilizamos para consultar Google Maps para obtener indicaciones. El constructor toma dos argumentos, un objeto de mapa y un objeto DOM donde queremos poner las indicaciones giro a giro. Elijo crear un div vacío debajo de #addresses llamado #directions.

1
  //error handler
2
  GEvent.addListener(gdir, "error", handleErrors);

Cuando usamos servicios web, siempre corremos el riesgo de que se devuelva un error. Podemos hacer que esto sea lo más libre de dolor posible usando la clase GEvent. En este fragmento de código estamos diciendo que si tenemos un error al obtener las instrucciones para ejecutar una función de devolución de llamada personalizada, handleErrors en nuestro caso. Llamamos directamente a la función addListener() que registra una devolución de llamada. Toma 3 argumentos un objeto de origen, una cadena que hace referencia al tipo de evento en el que queremos ejecutar la devolución de llamada y un controlador que apunta a una función que queremos que se ejecute. La función, handleErrors, es algo que veremos más adelante.

1
  //set company marker
2
  var companyMarker = createMarker(companyLatLng, companyMarkerImage, companyMarkerSize);
3
  
4
  //set map center
5
  map.setCenter(companyLatLng, defaultZoomLevel);
6
  map.addOverlay(companyMarker);

Las últimas líneas en initialize() se utilizan para crear nuestro marcador personalizado, elegí un Jayhawk que se encuentra en la página de inicio de KU. createMarker es una función contenedora que escribí para abstraer el código necesario para crear un marcador personalizado. Toma tres argumentos: una referencia a un objeto GLatLng donde queremos colocar la imagen en el, una cadena que representa la ruta de acceso a una imagen y una referencia a un objeto GSize que representa el tamaño de la imagen. A continuación usamos el método setCenter() de la clase GMap2 que toma dos argumentos, un objeto GLatLng de las coordenadas en las que centrar y un entero para el nivel de zoom. Observe que estamos pasando las variables que establecemos en el bloque de configuración en la parte superior de la función initialize(). La última línea de código utiliza el método addOverlay(). Esto es lo que realmente agrega la imagen personalizada al mapa.

La función initialize() hace mucho trabajo pesado, pero ciertamente puede mostrarlo. Después de escribir la función createMarker() a continuación, podrá cargar la aplicación y ver algún progreso. Pero primero vamos a recapitular la función initialize().

La función createMarker()

A continuación, crearemos una función contenedora que elimina todo el dolor de crear un marcador con una imagen personalizada. La razón por la que elijo abstraer esto es porque es un proceso involucrado y saturaría aún más nuestra función initialize(). Otro beneficio adicional es que podemos agregar varios marcadores muy rápidamente sin repetir una gran cantidad de código.

1
/*
2
**
3
* Wrapper function to create/return a marker object
4
* with custom image
5
*/
6
function createMarker(latlng, imageURL, imageSize)
7
{
8
9
    var marker      = new GIcon(G_DEFAULT_ICON, imageURL);
10
    marker.iconSize = imageSize;
11
12
    return new GMarker(latlng, { icon: marker });
13
14
}

Considerablemente más pequeño que nuestra primera función, pero igual de importante. Primero declaramos una nueva variable, marcador y almacenamos un objeto GIcon. Puede tomar dos argumentos copy que es un objeto GIcon del que copiará las propiedades, e image, que es una cadena que representa una ruta de acceso a una imagen personalizada. G_DEFAULT_ICON es una constante que representa un marcador predeterminado, y imageURL proviene del bloque de configuración en initialize(). Solo tenemos que establecer una propiedad más, iconSize que es de tipo GSize, esto representa el tamaño de nuestra imagen personalizada y también proviene del bloque de configuración. La última línea de código devuelve un objeto GMarker que toma dos argumentos latlng e icon. El primero, latlng es una referencia al objeto GLatLng que declaramos en el bloque de configuración. El siguiente argumento es para el objeto GIcon que acabamos de crear. Eso es todo lo que tenemos que hacer para que la parte del mapa de nuestra aplicación funcione. Ahora puede cargar la página y ver lo fácil que es obtener un buen mapa en nuestro sitio web.

Agregar direcciones

Esta es, con mucho, mi parte favorita de este tutorial, que permite a los usuarios ingresar una dirección y recibir de vuelta un mapa con la ruta resaltada y las indicaciones paso a paso. A través del uso de esta API podemos condensar algo que requeriría miles de líneas de código y una increíble cantidad de recursos de procesamiento en solo un puñado de código.

1
/*
2
**
3
* Looks up the directions, overlays route on map,
4
* and prints turn-by-turn to #directions.
5
*/
6
7
function overlayDirections()
8
{
9
    fromAddress =
10
      document.getElementById("street").value
11
      + " " + document.getElementById("city").value
12
      + " " + document.getElementById("state").options[document.getElementById("state").selectedIndex].value
13
      + " " + document.getElementById("zip").value;
14
15
    gdir.load("from: " + fromAddress + " to: " + toAddress);
16
}

La primera línea en realidad la he ampliado en cinco líneas para mayor claridad. En esencia, esto agarra todos los valores de la forma y pone un espacio entre cada parte. Pensé que esto era mejor que pedirle al usuario que ingresara la dirección completa en un solo cuadro de texto porque eso puede llegar a ser confuso.

La segunda línea hace uso del gdir que establecemos en initialize(). Llamamos al método load() y pasamos un solo argumento de cadena, que es esencialmente lo que pasaríamos maps.google.com a través del cuadro de búsqueda. Las palabras clave from: y to: ayudan a decirle a Google qué dirección debe ser el punto de partida y cuál debe ser el punto final. Eso es todo lo que tenemos que hacer para las direcciones, sí, ¡también me sorprendió! Si vuelves a visitar tu página puedes ver esto en acción.

Control de errores

A continuación vamos a declarar la función handleErrors(). Agarré esto del código de muestra de Google en su sitio web de API. No voy a entrar en detalles porque es bastante sencillo.

1
  function handleErrors(){
2
     if (gdir.getStatus().code == G_GEO_UNKNOWN_ADDRESS)
3
       alert("No corresponding geographic location could be found for one of the specified addresses. This may be due to the fact that the address is relatively new, or it may be incorrect.\nError code: " + gdir.getStatus().code);
4
     else if (gdir.getStatus().code == G_GEO_SERVER_ERROR)
5
       alert("A geocoding or directions request could not be successfully processed, yet the exact reason for the failure is not known.\n Error code: " + gdir.getStatus().code);
6
     else if (gdir.getStatus().code == G_GEO_MISSING_QUERY)
7
       alert("The HTTP q parameter was either missing or had no value. For geocoder requests, this means that an empty address was specified as input. For directions requests, this means that no query was specified in the input.\n Error code: " + gdir.getStatus().code);
8
     else if (gdir.getStatus().code == G_GEO_BAD_KEY)
9
       alert("The given key is either invalid or does not match the domain for which it was given. \n Error code: " + gdir.getStatus().code);
10
     else if (gdir.getStatus().code == G_GEO_BAD_REQUEST)
11
       alert("A directions request could not be successfully parsed.\n Error code: " + gdir.getStatus().code);
12
     else alert("An unknown error occurred.");
13
  }

Tiene un largo si... elseif... else que comprueba muchos tipos de error y alerta al usuario si se produce alguno. Puede modificar esto si desea que la alerta sea menos técnica.

degradable

Como buenos desarrolladores web, debemos asegurarnos de que nuestro sitio web funcione para tantos usuarios como sea posible, incluidos aquellos con JavaScript deshabilitado. En esta situación elegí redirigir aquellos con JS deshabilitado a Google Maps con la búsqueda realizada para que todavía obtengan direcciones. Esto se hace usando PHP para evaluar el formulario y redirigir a Google Maps. En la parte superior de la página HTML, inserte este código:

1
<?php
2
  //settings

3
4
    $TO    = "1450 Jayhawk Blvd #223 Lawrence, KS 66045"; //company address

5
6
  //end settings

7
8
  //they seem to have JS disabled, let's redirect them to

9
  //Google Maps and prefill the query

10
  if($_POST['submit']) {
11
    $FROM  = $_POST['street'] . " " . $_POST['city'] . ", " . $_POST['state'] . " " . $_POST['zip'];
12
    $LOC   = $_POST['language'];
13
14
    $url   = "http://maps.google.com/maps?hl=".urlencode($LOC)."&q=from:".urlencode($FROM)."+to:".urlencode($TO)."&ie=UTF8";
15
16
    header("Location: " . $url);
17
  }
18
?>
19
...

Primero tenemos un bloque de configuración de nuevo que solo tiene una variable para establecer, $TO. Esto es similar a lo que hicimos en JavaScript para toAddress, pero también necesitamos la misma cadena en PHP. A continuación, tenemos una declaración if para verificar los datos de POSTed, lo que significa que nuestro formulario se envió. Ahora tomamos los valores del formulario y los colocamos en una cadena con espacios y los almacenamos en una variable, $FROM. Luego almacenamos el valor de idioma para $LOC, más sobre esto más adelante. La variable $url mantendrá la cadena que representa la URL de consulta a Google. Tenga en cuenta que codificamos nuestros valores para que viajen de forma segura en la redirección. La última línea de código utiliza encabezados PHP para redirigir al usuario a Google.

Opcional: Agregar compatibilidad multilingüe

Como empresa, desea llegar a tantas personas como sea posible y parte de ese proceso es admitir varios idiomas. En Google Maps, admitir otros idiomas no tiene ningún costo adicional para nosotros.

Primero abra su página HTML e inserte el siguiente código entre las etiquetas de formulario.

1
...
2
<select id="language" name="language">
3
  <option value="en" selected>English</option>
4
  <option value="fr">French</option>                  
5
  <option value="de">German</option>
6
  <option value="ja">Japanese</option>
7
  <option value="es">Spanish</option>
8
</select>
9
...

Por supuesto, si desea eliminar cualquier idioma, simplemente elimine la etiqueta de opción para él, también puede cambiar el valor predeterminado moviendo el atributo seleccionado.

Pasando a js/application.js, necesitamos hacer solo dos cambios. Comenzando en la función overlayDirections() después de crear la cadena fromAddress, agregue esto para tomar el valor seleccionado del cuadro de selección de idioma y guárdelo en nuestra variable de idioma.

1
...
2
var language  = document.getElementById("language").options[document.getElementById("language").selectedIndex].value;
3
...

A continuación, agregue un argumento a la función gdir.load(), esto toma un conjunto de opciones. En nuestro caso, solo necesitamos declarar la configuración regional para que conozca el idioma y las unidades adecuadas para las indicaciones giro a giro.

1
...
2
gdir.load("from: " + fromAddress + " to: " + toAddress, { "locale": language });
3
...

Nota: Ya incluimos esto en la redirección de PHP y si desea deshabilitar esto, simplemente establezca estáticamente $LOC.

1
...
2
$LOC = 'en'
3
...

conclusión

Eso es todo lo que necesitamos para esta increíble función, y espero que hayas aprendido un poco sobre Google Maps en el camino. Los reto a ustedes, como desarrolladores, a que sigan encontrando formas interesantes de integrar mapas en sus aplicaciones. Cada vez que un modelo es consciente de la ubicación, debe preguntarse si su proyecto tiene un uso para la representación visual en un mapa. Gracias por leer; como siempre, estoy aquí para ayudar en los comentarios o en Twitter (@noahhendrix).

  • Síganos en Twitter o suscríbase a la fuente RSS de NETTUTS para obtener más tuts y artículos de desarrollo web diarios.