mar 14 2011

Dibujando rutas en Google Maps

Dibujando rutas

Puedes consultar las partes anteriores del manual de Google Maps Api 3:
Primera parte del manual

Segunda parte del manual

Tercera parte del manual

Este servicio es interesante, a demás podemos usar coordenadas o direcciones directamente, ya que el servicio las traducirá por sí solo.
Las clases principales son: google.maps.DirectionsService que es la que ejecuta la peticion del servicio al servidor y nos devuelve los datos, y google.maps.DirectionsRenderer que es la encargada de mostrar la ruta en nuestro mapa.
El ejempo básico de inicialización es el siguiente:

directionsService = new google.maps.DirectionsService();
directionsDisplay = new google.maps.DirectionsRenderer();

directionsDisplay.setMap(map);

La llamada a route tiene el formato “directionsService.route(request, function(result, status)”. Hay que generar un objeto request primero(DirectionRequest) que solo es necesario rellenar los campos que no sinteresan. Despues la funcion de callback es la que a partir del status tratamos los reultados.

var request = {
  origin:start,
  destination:end,
  travelMode: google.maps.DirectionsTravelMode.DRIVING
};

La llamada y el tratamiento del objeto result. Comprobamos que el status es OK, si no no hay nada que hacer, salvo mostrar el tipo de error.

directionsService.route(request, function(result, status) {
  if (status == google.maps.DirectionsStatus.OK) {
    directionsDisplay.setMap(map);
    var mystr="";
    for(var i in result.routes){
      var mylegs=result.routes[i].legs
      for(var j in mylegs){
        mystr += mylegs[j].distance.text;
        mystr += " " + mylegs[j].duration.text+ " <br/>";
      }
      mystr+="<br/>";
      $(“#infoRecorrido).html(mystr);
    }
    directionsDisplay.setDirections(result);
  }
});

Lo que realmente dibuja el mapa es ‘directionsDisplay.setDirections(result)’ ¿y todo lo demas? pues bien, google nos envia un objeto con bastante información. Los margenes en que se visualizará el mapa, las coordenadas de los puntos de incio y fin, y otras cosas entre ellas la distancia y tiempo de recorrido.
La distancia se encuentra en “result.routes[0..n-1].legs[0..n-1].duration”. Se puede visualizar en texto en tiempo ya tranformado en horas:minutos:segundos con ‘.text’ o directamente en el numero de segundos con ‘.value’.
La respuesta contiene bastante información y se le puede sacar mucho partido (ver: http://code.google.com/intl/es/apis/maps/documentation/directions/ )

bounds = new google.maps.LatLngBounds();
for(var l in markers){
  bounds.extend( markers[l].getPosition() );
}
map.fitBounds(bounds);

visto en: http://blog.shamess.info/2009/09/29/zoom-to-fit-all-markers-on-google-maps-api-v3/

Finalmente y por experiencia propia recomiendo re posicionar los margenes con cierto retardo con una función como esta:

function rebounds(){
  setTimeout(recReBounds,250,(6));
}

function recReBounds(veces)
  if(!veces){
    return false;
  }
  try{
    bounds = new google.maps.LatLngBounds();
    for(var l in markers){
    bounds.extend( markers[l].getPosition() );
  }
  map.fitBounds(bounds);
  }
  catch(e){
    setTimeout(recReBounds,250,(veces-1));
  }
}

rebounds();

A veces la velocidad del navegador que esté utilizando el cliente no carga las imágenes del mapa con mucha velocidad. Si ejecutamos el reajuste de margenes una vez recogidos los datos puede que se reajusten los margenes antes de pintar el mapa, con lo cual el reajuste no tiene efecto. Con un retardo de un cuarto de segundo el usuario siente interacción de la web y el reajuste tiene efecto.


mar 11 2011

Dibujar marcas en un mapa

Trabajando con los markers

Puedes consultar las partes anteriores del manual de Google Maps Api 3

primera parte del manual

segunda parte del manual

Para empezar vamos a trabajar con un vector de marcas que va a ser una variable global markers. Tan sencillo como:

var markers={};

setMarker hace algo más que posicionar un marker en el mapa. Seleciona el campo donde tenemos la localidad (o direccion), esto lo hace con la funcion dollar de jquery. Esta direccion la traduce a coordenadas LatLng con el servicio geocoder.
Despues invoca al método marker que es el que realmente inserta el marcador en el punto correcto del mapa.

function setMarker(id,addid){
  var dir = $("#"+id).val();
  geocoder.geocode( { 'address': dir}, function(results, status) {
    if (status == google.maps.GeocoderStatus.OK) {
      marker(id, results[0].geometry.location);
    } else {
      marker(id,null);
    }
  });
}

Marker en realidad es una funcion muy sencilla. Si existe el marcador añade una nueva posición, si no existe lo crea indicandole el mapa y la posicion donde irá.
La unica complejidad en cuanto a configuracion del maker es indicarle que no sea arrastrable (draggable) ni que se pueda pinchar (clickable).

function marker(id, location){
  if(markers[id]){
    markers[id].setPosition(location);
  }
  else{
    markers[id] = new google.maps.Marker({
      map: map
      ,position: location
      ,markerOptions:{
        draggable:false
        ,clickable:false
      }
    });
  }

  map.setZoom(10);
}

Otras opciones posibles son hacer zoom y centrar el mapa en el marcador (en este caso está comentado) pero son opciones del mapa, no del marcador.

Borrar un marker

Para borrar un marker es tan sencillo como añadirle una posicion nula. Como en nuestro caso tenemos un objeto global donde están todos nuestros markers nos podemos hacer las funciones hideMarker y hideAllMarkers:

function hideAllMarkers(){
  for(var m in markers){
    markers[m].setPosition(null);
  }
}

function hideMarker(id){
  if(id && id != "" && markers[id]){
    markers[id].setPosition(null);
    return true;
  }
  return false;
}

*Cuidado si se usan otras propiedades de los markers como el texto que despliegan al clickarlos. Si volvemos a ponerle una posicion al marker esas propiedaden persisten. Suponemos que en esta aplicacion no añadimos informacion extra y que los markers no son clickables. En otro caso para más seguridad hay que hacer un new cada vez para chafar las propiedades anteriores, o cambiarlas una por una.


mar 9 2011

Google Maps Geocoder

De dirección a coordenada

Puedes consultar la primera parte del manual de Google Maps Api 3

El objeto Geocoder se usa para traducir coordenadas a direcciones y viceversa. Si nos fijamos en las indicaciones de uso de google nos encontramos que si usameos el servico Geocoder tenemos que incluir obligatoriamente un mapa de google en nuestra web.
Bueno en realidad es lo logico al traducir direcciones a coordenadas, pero si estabas pensando dar un servicio de otro tipo que no sea visualizado, siento decirte que te caparán el servicio

Este ejemplo traduce una dirección (de un input text) a unas coordenadas y centra el mapa en esas coordenadas y crea un marker.

<script type="text/javascript">
var geocoder;
var map;
function initialize() {
  geocoder = new google.maps.Geocoder();
  var latlng = new google.maps.LatLng(-34.397, 150.644);
  var myOptions = {
    zoom: 8,
    center: latlng,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  }
  map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
}

function codeAddress() {
  var address = document.getElementById("address").value;
  geocoder.geocode( { 'address': address}, function(results, status) {
    if (status == google.maps.GeocoderStatus.OK) {
      map.setCenter(results[0].geometry.location);
      var marker = new google.maps.Marker({
        map: map,
        position: results[0].geometry.location
      });
    } else {
      alert("Geocode was not successful for the following reason: " + status);
    }
  });
}
</script>

más info: http://code.google.com/intl/es/apis/maps/documentation/javascript/services.html#Geocoding

una consulta correcta devuelve un json tal que así:

{
"status": "OK",
"results": [ {
  "types": [ "locality", "political" ],
  "formatted_address": "Winnetka, IL, USA",
  "address_components": [ {
  "long_name": "Winnetka",
  "short_name": "Winnetka",
  "types": [ "locality", "political" ]
  }, {
  "long_name": "Illinois",
  "short_name": "IL",
  "types": [ "administrative_area_level_1", "political" ]
  }, {
  "long_name": "United States",
  "short_name": "US",
  "types": [ "country", "political" ]
  } ],
"geometry": {
  "location": {
    "lat": 42.1083080,
    "lng": -87.7417070
  },
"location_type": "APPROXIMATE",
  "viewport": {
    "southwest": {
      "lat": 42.0917501,
      "lng": -87.7737218
    },
    "northeast": {
      "lat": 42.1248616,
      "lng": -87.7096922
    }
  },
  "bounds": {
    "southwest": {
      "lat": 42.0885320,
      "lng": -87.7715480
    },
    "northeast": {
      "lat": 42.1284090,
      "lng": -87.7110160
    }
  }
}
} ]
}

Accediendo al objeto results[0].geometry.location obtenemos un objeto lonLat, objeto propio de google.maps, que contiene la coordenada. ya podemos hacer lo que queramos con ella.


mar 5 2011

Introducción a Google Maps Api 3

Google Maps api3 con ejemplos

Esta es la primera parte de un manual sobre el Api 3 de google maps. Simplemente es una primera guia para cómo, a partir de pocas lineas de código, poder implementar una aplicación interesante en tu web.

Aportar información geolocalizada está hoy a la orden del día, yo voy a basarme en los ejemplos que proporciona google añadiendo variaciones que amplian su funcionamiento. Para hacerlo de forma más comoda voy a utilizar jQuery 1.4.2 en algunos casos.

Ejemplo ligeramente modificado con jquery:
-muestra un mapa. se puede insertar longitud y latitud numerica y actualizar el mapa. Despues una lista de las propiedades de google.maps

<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript" src="./jquery.1.4.2.js"></script>
<script type="text/javascript">
var myOptions, latlng, map;

function initialize() {
  latlng = new google.maps.LatLng(-34.397, 150.644);
  myOptions = {
    zoom: 8,
    center: latlng,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  };
  map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
}

$(document).ready(function(){
  $("#buttonver").click(function(){
    var latVar,lonVar;
    latVar = $("#lat").val();
    lonVar = $("#lon").val();
    latlng = new google.maps.LatLng(latVar, lonVar);
    myOptions.center=latlng;
    map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
  });
});
</script>
</head>
<body onload="initialize()">
<div id="map_canvas" style="width:400px; height:400px"></div>
<label for="lat">latitud</label><input type="text" id="lat" name="lat" value="38.5"/>
<label for="lon">longitud</label><input type="text" id="lon" name="lon" value="-0.5"/>
<input type="button" id="buttonver" value="ver" />
</body>
</html>

Añadimos evento cuando haga click para que muestre la longitud y latitud:
*MEJORA: no hacemos un new Map cuando cambiamos las coordenadas. Usamos el método map.setCenter(latlng)

<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript" src="./jquery.1.4.2.js"></script>
<script type="text/javascript">
var myOptions, latlng, map;

function initialize() {
  latlng = new google.maps.LatLng(-34.397, 150.644);
  myOptions = {
    zoom: 8,
    center: latlng,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  };
  map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
  google.maps.event.addListener(map, 'click', function(event) {
    alert(event.latLng);
  });
}

$(document).ready(function(){
  $("#buttonver").click(function(){
    var latVar,lonVar;
    latVar = $("#lat").val();
    lonVar = $("#lon").val();
    latlng = new google.maps.LatLng(latVar, lonVar);
    myOptions.center=latlng;
    map.setCenter(latlng);
  });
});
</script>
</head>
<body onload="initialize()">
<div id="map_canvas" style="width:400px; height:400px"></div>
<label for="lat">latitud</label><input type="text" id="lat" name="lat" value="38.5"/>
<label for="lon">longitud</label><input type="text" id="lon" name="lon" value="-0.5"/>
<input type="button" id="buttonver" value="ver" />
</body>
</html>

Reseña sobre los eventos posibles:

- ‘click’
- ‘dblclick’
- ‘mouseup’ -> no me va
- ‘mousedown’ -> no me va
- ‘mouseover’
- ’mouseout’

En estos eventos se les pasa un event a la funcion calback que contiene una variable latLng.

- ‘zoom_change’ -> el callback no recibe parámetros
- ‘bounds_changed’
- ‘center_changed’

Enlaces de referencia:

-Tutorial:
http://code.google.com/intl/es/apis/maps/documentation/javascript/tutorial.html

-Referencia:
http://code.google.com/intl/es/apis/maps/documentation/javascript/reference.html

-Ejemplos:
http://code.google.com/intl/es/apis/maps/documentation/javascript/examples/