Geocode: Buscar direcciones con GMaps API v3 Geocode: Buscar direcciones con GMaps API v3

Posted by on Jun 26, 2011 in Código, Featured Articles | 28 comments


Si no tienes mucha experiencia o tienes dudas con respecto a algo que usemos en este post, puedes consultar los demás ejemplos que se han realizado anteriormente aquí.

Ya hemos visto el cómo obtener geolocalización para ubicar el lugar donde nos encontramos, pero, ¿qué pasa cuando buscamos una dirección diferente a donde nos encontramos?, sería necesario escribir y buscar la dirección deseada, bien pues el proceso es relativamente sencillo. (Para esto requeriremos que agregues los scripts de GMaps y de jQuery, consulta los anteriores post si tienes duda de esto).

Lo que haremos se resume en: escribir una dirección, verificar si existe, si existe, colocar un marcador, centrar y dar zoom en el mapa en la región de la dirección obtenida, si no existe la dirección arrojar un error diciendo que no existe.

Ver Demo Geocoding

La parte importante del código es generar un objeto que nos permita comunicarnos con la API  de Google Maps y nos convierta la dirección en latitud y longitud de manera que podamos maniobrarlas a placer.

var geocoder = new google.maps.Geocoder();

Cuando se genera una petición de Geocoding, pueden enviarse varios parámetros para obtener resultados más específicos, un objeto de solicitud completa comprendería:

  • address (obligatorio *): es la dirección que deseas codificar de forma geográfica.
  • latLng (obligatorio *): la latitud y la longitud (LatLng ) para las que deseas obtener la dirección interpretable por humanos más cercana.
  • bounds (opcional): los límites de latitud y de longitud (LatLngBounds) dentro de los que quieres predeterminar los resultados de codificación geográfica con mayor importancia. Para obtener más información, consulta la sección Especificación de la ventana gráfica que encontrarás a continuación.
  • language (opcional): es el idioma en el que se devuelven los resultados.
  • region (opcional): el código de región, especificado como una subetiqueta region del lenguaje IANA. En la mayoría de los casos, estas etiquetas se asignan directamente a valores de dos caracteres ccTLD (“dominio de nivel superior”) ya conocidos. Para obtener más información, consulta la sección Especificación del código de región que encontrarás a continuación.

* Nota: la búsqueda funciona incluyendo solamente el campo address, aunque siempre es requisito incluir un campo address o un campo latLng obligatoriamente, si se coloca un campo latLng, el geocoder realizará el proceso conocido como codificación geográfica inversa, o sea, convertir coordenadas en direcciones, pero, eso lo veremos en otro post.

La solicitud se hace de la siguiente manera:

// Obtenemos la dirección y la asignamos a una variable
var address = $('#address').val();
// Creamos el Objeto Geocoder
var geocoder = new google.maps.Geocoder();
// Hacemos la petición indicando la dirección e invocamos la función
// geocodeResult enviando todo el resultado obtenido
geocoder.geocode({ 'address': address}, geocodeResult);

El objeto que se obtiene de respuesta es un JSON, donde lo manejaríamos como regularmente se hace en javascript, el resultado es algo como esto:

{
  "status": "OK",
  "results": [ {
    "types": [ "street_address" ],
    "formatted_address": "1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA",
    "address_components": [ {
      "long_name": "1600",
      "short_name": "1600",
      "types": [ "street_number" ]
    }, {
      "long_name": "Amphitheatre Pkwy",
      "short_name": "Amphitheatre Pkwy",
      "types": [ "route" ]
    }, {
      "long_name": "Mountain View",
      "short_name": "Mountain View",
      "types": [ "locality", "political" ]
    }, {
      "long_name": "California",
      "short_name": "CA",
      "types": [ "administrative_area_level_1", "political" ]
    }, {
      "long_name": "United States",
      "short_name": "US",
      "types": [ "country", "political" ]
    }, {
      "long_name": "94043",
      "short_name": "94043",
      "types": [ "postal_code" ]
    } ],
    "geometry": {
      "location": {
        "lat": 37.4219720,
        "lng": -122.0841430
      },
      "location_type": "ROOFTOP",
      "viewport": {
        "southwest": {
          "lat": 37.4188244,
          "lng": -122.0872906
        },
        "northeast": {
          "lat": 37.4251196,
          "lng": -122.0809954
        }
      }
    }
  } ]
}

Lo único que nos faltaría es el código para validar, interpretar y dibujar. Para esto, hay 3 cosas importantes que debemos tomar en cuenta del JSON que tenemos de respuesta:

  • status: contiene la respuesta del estado de la petición, si fue satisfactoria o si hubo algún error y que tipo de error.
  • geometry.location: la ubicación de la dirección solicitada
  • geometry.viewport: los límites recomendados para ajustar el zoom del mapa, haciendo un cuadrante con las esquinas Noreste (superior derecha) y Suroeste (inferior izquierda).

Con esto en presente, la función siguiente nos mostrará solamente el primer resultado obtenido, quedando así :

function geocodeResult(results, status) {
    // Verificamos el estatus
    if (status == 'OK') {
        // Si hay resultados encontrados, centramos y repintamos el mapa
        // esto para eliminar cualquier pin antes puesto
        var mapOptions = {
            center: results[0].geometry.location,
            mapTypeId: google.maps.MapTypeId.ROADMAP
        };
        map = new google.maps.Map($("#map_canvas").get(0), mapOptions);
        // fitBounds acercará el mapa con el zoom adecuado de acuerdo a lo buscado
        map.fitBounds(results[0].geometry.viewport);
        // Dibujamos un marcador con la ubicación del primer resultado obtenido
        var markerOptions = { position: results[0].geometry.location }
        var marker = new google.maps.Marker(markerOptions);
        marker.setMap(map);
    } else {
        // En caso de no haber resultados o que haya ocurrido un error
        // lanzamos un mensaje con el error
        alert("Geocoding no tuvo éxito debido a: " + status);
    }
}

Y listo con esto tenemos terminado nuestro ejercicio, puedes verificarlo en funcionamiento en la página de demos:

Ver Demo Geocoding

El código completo quedaría así:

$(document).ready(function() {
    load_map();
});

var map;

function load_map() {
    var myLatlng = new google.maps.LatLng(20.68009, -101.35403);
    var myOptions = {
        zoom: 4,
        center: myLatlng,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    map = new google.maps.Map($("#map_canvas").get(0), myOptions);
}

$('#search').live('click', function() {
    // Obtenemos la dirección y la asignamos a una variable
    var address = $('#address').val();
    // Creamos el Objeto Geocoder
    var geocoder = new google.maps.Geocoder();
    // Hacemos la petición indicando la dirección e invocamos la función
    // geocodeResult enviando todo el resultado obtenido
    geocoder.geocode({ 'address': address}, geocodeResult);
});

function geocodeResult(results, status) {
    // Verificamos el estatus
    if (status == 'OK') {
        // Si hay resultados encontrados, centramos y repintamos el mapa
        // esto para eliminar cualquier pin antes puesto
        var mapOptions = {
            center: results[0].geometry.location,
            mapTypeId: google.maps.MapTypeId.ROADMAP
        };
        map = new google.maps.Map($("#map_canvas").get(0), mapOptions);
        // fitBounds acercará el mapa con el zoom adecuado de acuerdo a lo buscado
        map.fitBounds(results[0].geometry.viewport);
        // Dibujamos un marcador con la ubicación del primer resultado obtenido
        var markerOptions = { position: results[0].geometry.location }
        var marker = new google.maps.Marker(markerOptions);
        marker.setMap(map);
    } else {
        // En caso de no haber resultados o que haya ocurrido un error
        // lanzamos un mensaje con el error
        alert("Geocoding no tuvo éxito debido a: " + status);
    }
}

Y en el Body solamente esto:

<div><input type="text" maxlength="100" id="address" placeholder="Dirección" /> <input type="button" id="search" value="Buscar" /></div><br/>
<div id='map_canvas' style="width:600px; height:400px;"></div>

Espero les sirva y cualquier cosa, ya saben cómo contactarme…

Enjoy this Life!

Quizá también te interese...


28 Responses to “Geocode: Buscar direcciones con GMaps API v3”

  1. hola como hago para agrgarle el recuadro de fotos y de wikipeia como aparecee n la pgina google maps

    • @juan es HTML simple, al momento de que mandas abrir un infowindow, en el contenido tienes que linkear la foto que quieres que aparezca, para wikipedia, es necesario usar el API de Wikipedia vaya, eso es sencillo pero requiere de tiempo y algo más de código para adentrarse a esa API

  2. lo que pasa es que yo estoy en mi tesis y en ella estoy utilizando sig y he tomado el gogle maps para ello
    y me gustaria poder lograr realizar obtener ytodo el tipo de informaacion que cuando yo le de una direccion el me pueda arrojar el mapa y ademas todas las fotos que se encuentren en panoramica de ese sitio o pais, ciudad y utilizar la informacion de wikipedia te agradesco me ayudes

    • @juan lo que buscas es algo como esto http://jafrancov.com/projects/mtwsoa/ pero para eso necesitas consultar tantas APIs como datos quieras mostrar, lo que ves en google maps o google earth es una consulta a todas las APIs que selecciones y muestren datos del lugar que marques.

      • si algo asi ,pero quiero agregarle un boton de fotos que al dar click hay me muestre las imagenes como aparece en la pagina oficial de google maps que utilizan panaromico q aparecen todas las fotos que estan publicadas hay y el boton de wikipedia

      • necesito q me puedas ayudar o un ejemplo para guiarme

  3. samuel says:

    Hola te agradezco mucho el que compartas tus conocimientos y estoy aqui de nuevo molestandote con una duda, probe este ejemplo y resulto genial, despues queria que la lat y la lng se mostraran en 2 cuadros de texto de un form, crei que solo usando sus propiedades era suficiente pero no se que es toy haciendo mal, no me marca error pero tampoco me da el resultado deseado, me podrias ayudar por favor??

    if (status == ‘OK’ && results.length > 0)
    {
    // Si hay resultados encontrados, centramos y repintamos el mapa
    // esto para eliminar cualquier pin antes puesto
    var mapOptions = {
    zoom: 14,
    center: results[0].geometry.location,
    mapTypeId: google.maps.MapTypeId.ROADMAP

    };
    map = new google.maps.Map($(“#map_canvas”).get(0), mapOptions);
    // fitBounds acercará el mapa con el zoom adecuado de acuerdo a lo buscado
    map.fitBounds(results[0].geometry.viewport);
    // Dibujamos un marcador con la ubicación del primer resultado obtenido
    var markerOptions = { position: results[0].geometry.location,draggable: true}
    var marker = new google.maps.Marker(markerOptions);
    //Obtener Lactitud y Longitud, mostrandolos en cuadros de texto y mostrar un infowindow
    var markerLatLng = marker.getPosition();
    $(‘#x’).val()=markerLatLng.markerLatLng.lat();
    $(‘#y’).val()=markerLatLng.markerLatLng.lng();
    marker.setMap(map);
    }

    • @Samuel yo creo que necesitas leer un poco de jQuery =P la asignación es lo erróneo, el
      $(‘#x’).val() = ‘algo’
      debería ser:
      $(‘#x’).val(‘algo’)

      Así lo resuelves :)

      • samuel says:

        Ok, muchas gracias, si de jqry no se nada :( tendre que estudiarlo, muchas gracias

  4. samuel says:

    Veo tambien que al agregar estas lineas de codigo:
    //Obtener Lactitud y Longitud, mostrandolos en cuadros de texto y mostrar un infowindow
    var markerLatLng = marker.getPosition();
    $(‘#x’).val()=markerLatLng.lat();
    $(‘#y’).val()=markerLatLng.lng();
    o cualquier otra, como por ejemplo para poner un window info, el marcador que estaba lo desaparece, seguro que algo esta mal, me podrias apoyar?? por favor, de antemano te agradezco mucho y disculpa las molestias

    • @Samuel La asignación es lo erróneo en jQuery para este caso debe ser:

      $(‘#x’).val(markerLatLng.lat());
      $(‘#y’).val(markerLatLng.lng());
      
  5. Hola, estoy intentando pasar toda mi pagina al API3 pero me encuentro con el siguiente problema. Como cambiar esta instruccion de API 2 a API 3, concretamente me da problemas “point.toURLValue()”, si lo pongo no sale nada en el sidebar, me refiero siempre si migro esta instrucción al API3

     function createMarker(point,name,html,category) {
       html += '<a href="http://maps.google.com/maps?' +
          'saddr=&daddr=' + point.toUrlValue() +
          'rel="nofollow">Pulsa para llegar hasta aqui';
       var marker = new GMarker(point,gicons[category]);
       marker.mycategory = category;
       marker.myname = name;
       GEvent.addListener(marker, "click", function() {
          marker.openInfoWindowHtml(html); });
       gmarkers.push(marker);
       return marker;}
    

    Un saludo

    • @Joaquin Hola, buscando encontré que la función .toString() devuelve las coordenadas con decimales completos del lugar, y en paréntesis, algo como:
      (60.174391639841424, 24.939823150634766)

      Otra opción que puedes tomar, es por separado extraer el Lat/Lng, algo como:

      myLatlng.lat().toFixed(6) + ',' + myLatlng.lng().toFixed(6) 

      Espero eso ayude, saludos!!!

  6. Joaquin says:

    Hola Alex, ante todo gracias por estar ahí ayudando a los demás. Una pregunta rápida: Estoy intentando hacer un ejemplo de mapa con KML, solo copiar y pegar algunos de los ejemplos que hay, y no consigo que funcione ninguno, sale el mapa pero como si no encontrara los datos del klm (con el api2 funciona perfectamente) pero con el api3 no consigo que funcione. Hay algun problema.

    Un abrazo

    • @Joaquín pues no se supone que haya problemas, aunque si estás mezclando APIs no va a funcionar, necesitaría ver el código para poder ver si hay algo fuera de lo ordinario que te esté causando conflictos, porque los KML si los muestra en la API v2 es que están bien hechos, entonces no debería haber problema en la v3

  7. Joaquin says:

    Hola Alex, no mezclo nada, tomo como ejemplo la galeria de demostraciones de google maps para api3, el ejemplo 41 que funciona perfectamente, si lo copias todo, html, kml y js y tratas de verlo tu, solo sale el mapa.

    http://gmaps-samples-v3.googlecode.com/svn/trunk/xmlparsing/

  8. eduardo says:

    ES ORRIBLE

  9. Daniel says:

    Hola, gracias a tu blog he solucionado un par de cosas de una página que estoy haciendo, asi que gracias :D pero hay algo que no encuentro en ningún lado, quiero obtener la dirección (formatted address) de varios marcadores, a traves de las coordenadas, me resulta como para los primeros 5 pero despues sale OVER_QUERY_LIMIT y no sé que hacer. Ayuda porfa :c
    Saludos

    • @Daniel deja me hago un post para hacer geocode inverso, no sé cómo es que lo estés haciendo pero por lo que te arroja, tienes una sobrecarga, mejor, en un comentario quedaría corto, así que deja me pongo a escribir un poco, saludos!

      • Daniel says:

        Si, creo que tengo una sobrecarga por que lo debo hacer para muchos marcadores y lo puse dentro de un for.. bueno, espero tu post y gracias!

      • Daniel says:

        Hola, lo solucione ! :D poniendo el geocode dentro del addListener en vez de en el for, así hace una consulta a la vez y no se sobrecarga. Igual espero el post, saludos!

  10. Lemay says:

    Muy buen post, tengo una duda, en vez de hacer la busqueda por dirección la debo hacer por código postal, perteneciente a un país determinado, cómo sería en este caso ???

    Sds y gracias

    • @Lemay El Geocode hace la búsqueda al igual por Código Postal, el detalle es que probablemente necesites concatenar un “, México” para que lo busque en el país correcto, ya que por experiencia, algunos o se repiten o hay lugares que específicamente se llaman por números y elige el más cercano al meridiano 0, sencillo, ¿no? ;)

      Saludos!

      • Lemay says:

        entonces sería algo como esto:

        geocoder.geocode({ ‘address’: pcode+’, España’,'region’:'es’}, geocodeResult);

        ??

        Saludos !

      • Lemay says:

        Ok, ya solo especificando la region, funciona con código postal.

        Muchas gracias

      • @Lemay Exactamente, puedes concatenar el país o indicar la región, con cualquiera de los 2 funciona suerte!

      • Al parecer es un poco tarde mi respuesta, pero de todas maneras la dejaré por acá.. con la api de foursquare se puede hacer una especie de Geocode Inverso al utilizar la “https://api.foursquare.com/v2/venues/trending”
        puedes utilizar el parametro “ll” para buscar por latitud/longitud o el parametro “near” para buscar por ubicación, te devuelve un json con la ciudad, region y pais, ademas de las coordenadas poligonales en latitud, longitud del ará de la ubicación.

        Muy bueno tu blog, lo visito frecuentemente pero de manera pasiva.. saludos!

      • @DanielRubilar es correcto, pero el punto es hacer el geocoding inverso con la API de Maps directamente, gracias por la visita ;)

Leave a Reply