¡Hola! Me parece que andas usando un bloqueador de anuncios =( ¿Nos desbloqueas? ¿Por qué?
F13

Funcion 13

Ocultando y mostrando múltiples marcadores en Google Maps

No hace mucho, en el último artículo que escribí sobre la serie de Google Maps, recibí una consulta que me pareció realmente interesante el cubrirla en un artículo.

El problema

El problema que se presenta es bastante común. Cuando cargamos varios puntos de interés en un mapa, a veces puede ser molesto tanta cantidad de marcadores o bien porque solo queramos mostrar alguna clase de ellos.

Manos a la obra

Para la ocasión, he obtenido datos de la página todo-poi sobre estaciones de autobuses y aeropuertos. Con un poco de magia convirtiendo el XML a JSON y algunos ajustes por aquí y otros por allá, he creado dos archivos json que contienen gran cantidad de elementos. Contienen objetos con la siguiente estructura:

[
  {
    "name":"Aeropuerto Reina Sofia -Tenerife Sur-",
    "type":"Aeropuerto",
    "coords":{
      "lng":-16.57776,
      "lat":28.04887
    }
  },
  {
    "name":"Estación de autobuses Fuengirola, Avda.Ramón y Caja l",
    "type":"Estacion de autobus",
    "coords":{
      "lng":-4.62295,
      "lat":36.54154
    }
  }
]

La función con la que la inserto, de manera temporal, es la siguiente:

var insertar_marcador = function(data) {  
  $.each(data, function(i, obj) {
    var marcador = new google.maps.Marker({
      position: new google.maps.LatLng(obj.coords.lat, obj.coords.lng),
      map: map
    });
    marcadores.push(marcador);
  });
};
$.getJSON('aeropuertos.json', insertar_marcador);
$.getJSON('estaciones.json', insertar_marcador);

Por ahora nada nuevo hasta ahora a lo que ya hemos visto. Guardamos los marcadores en una matriz porque los necesitaremos más tarde.

Veamos qué ocurre cuando metemos todos los marcadores en el mapa…

Vamos a hacer un pequeño ajuste a nuestra función para cambiar los marcadores en función del tipo, y también almacenaremos esta información dentro del propio marcador. Una vez más, haremos uso de los fantásticos iconos de Nicolas Mollet.

El ajuste es el siguiente:

var insertar_marcador = function(data) {  
  $.each(data, function(i, obj) {
    var marcador = new google.maps.Marker({
      title: obj.name,
      position: new google.maps.LatLng(obj.coords.lat, obj.coords.lng),
      map: map,
      tipo: obj.type,
      icon: obj.type === 'Aeropuerto' ? 'airport.png' : 'busstop.png'
    });
    marcadores.push(marcador);
  });
};

Nada demasiado complejo hasta ahora. Almacenamos el tipo y, en función de este decidimos el icono que vamos a usar. Nuestro resultado es ahora un poco menos complejo:

Un poco mejor… pero sigue siendo demasiado confuso. Lo que vamos a hacer es añadir unos checkbox que nos permitan decidir qué tipo de marcadores son los que queremos ver.

El marcado es muy simple:

<div id="controles">  
  <label>
    <input type="checkbox" name="aeropuertos" value="Aeropuerto" class="control" checked="checked" /> Aeropuertos</label>
  <br />
  <label>
    <input type="checkbox" name="estaciones" value="Estacion de autobus" class="control" checked="checked" /> Estaciones de autobus</label>
  <br /> 
</div>  

Los dejamos checked porque, por defecto, queremos verlos todos. La clase nos servirá para seleccionarlos de forma cómoda con jQuery.

Vamos a necesitar también una matriz que nos diga los elementos que están visibles en todo momento. Algo así:

var visibles = ['Aeropuerto','Estacion de autobus'];  

Ahora veamos la función que se activará cuando marquemos/desmarquemos uno de los checkbox que acabamos de crear.

$('input.control').on('change', function(e) {
  var $this = $(this),
    valor = $this.val();
  if ($this.is(':checked')) {
    // Si está marcado tendremos que añadirla a nuestra lista de visibles 
    visibles.push(valor);
  } else {
    // Nos tocará borrarlo 
    visibles.splice(visibles.indexOf(valor), 1);
  }
});

La función es muy sencilla. Obtenemos el valor del checkbox. Después, con la ayuda de jQuery, comprobamos si un checkbox está marcado o no. En función de si está marcado o no, lo añadiremos o quitaremos de la lista de visibles. Lo siguiente que haremos es llamar a otra función que, usando esa lista de visibles, recorra nuestra lista de marcadores y oculte o no el marcador, si el tipo del marcador está en la lista de elementos visibles:

var ocultar_marcadores = function() {  
  for (var i = 0, length = marcadores.length; i < length; i++) {
    marcadores[i].setVisible(visibles.indexOf(marcadores[i].tipo) !== -1);
  }
};

Si indexOf nos devuelve -1, significa que elemento no está en la lista de elementos visibles y por tanto tendremos que ocultarlo. La función setVisible del marcador, nos permite establecer si el marcador es visible o no.

Ahora, cuando marquemos y desmarquemos un checkbox, los marcadores se ocultarán de manera automática tal y como queríamos. Fácil, ¿verdad?

Puedes ver todo el código al completo en la demo que he preparado con este ejemplo. ¡Espero que te sea útil!

Si el artículo te pareció interesante, útil o incluso equivocado, por favor considera el dejar un comentario. ¡Lo apreciaré mucho!

Edición

En esta última semana he recibido varios correos de personas preguntando por los archivos .json que uso en la aplicación ya que no os funciona. Es buena idea revisar la validez del archivo JSON para evitar que no se os haya quedado algo mal formado.

No obstante, aquí tenéis ambos archivos:

Programador Front-end en First + Third y Potato. Trabajando con JavaScript y HTML5 desde el corazón de Sevilla.

Comentarios ¡Únete a la conversación!