Un problema poco común, que se puede encontrar al usar la api de Google Maps para generar nuestros propios puntos geolocalizados en un mapa, es que estos puntos se encuentren la misma coordenada GPS. Si ocurre esto los puntos se montan uno encima de otro y no es posible “desagregarlos” por mucho zoom que hagamos sobre el mapa. Google Maps posee una seria de funciones que permiten hacer clustering en los mapas pero esto no nos sirve porque el clustering funciona cuando los puntos están en diferentes posiciones y dependiendo del nivel de zoom se aplica el clustering o se muestran los puntos. Puedes ver aquí como se implementa el clustering y tambien aquí donde se explica muy bien Como he comentado, en este caso nos hacia falta otra solución y por suerte encontramos una librería que permite realizar este trabajo. Esta librería se encuentra aquí Lo que quería conseguir era que el mapa mostrase iconos diferentes según el nivel de superposición de los puntos y también según el contenido de cada punto. Si había puntos superpuestos se debería mostrar un icono de agrupación y al clicar en el se desagregaba y se mostraba cada icono según su tipo de contenido. En el enlace anterior pone varios ejemplos, lo que queremos hacer en este caso es lo que aparece en el tercer ejemplo con algunas modificaciones que comentaré mas adelante. En mi caso tenia tres iconos diferentes y otro icono adicional que se iba a mostrar cuando existiesen puntos superpuestos. Lo que cambia con respecto al ejemplo comentado es que no genero los iconos en svg, sino que uso imágenes en formato png para los iconos y tampoco genero los puntos de forma aleatoria sino que tengo un json con 10 puntos, de los que 2 están situados en la misma coordenada (el punto 3 y el punto 10). Tampoco permito que se borren puntos, ni que se añadan ni que se muevan de sitio, como pasa en este ejemplo, digamos que me quedo con lo esencial. Vamos alla!! 1. Tenemos un json con los puntos que queremos dibujar. De manera habitual esta información se podría obtener de una base de datos y generar el json, aunque en nuestro caso y para poder usar un html sin programación de lado de servidor vamos a usarlo “a pelo” y tener un json como este. En este json existen 2 puntos que están en la misma coordenada: el punto 3 y el 10 2. Definimos los iconos que nos hacen falta: 4 iconos en formato png, que no indico aquí 3. Configuramos la función addMarkerWithData para mostrar lo que nos interesa. Lo mas importante es esta parte donde en función del estado del punto se le asigna un icono u otro. En el siguiente apartado explicaremos cada estado y como funcionan.

Explicación de como se cambian los iconos de cada punto

Si los puntos se juntan lo suficiente para que parezcan uno son SPIDERFIABLE, y por lo tanto mostramos el icono de agrupación. En el momento que se aumenta el zoom y estos puntos se separan los suficiente pasan a ser UNSPIDERFIABLE, excepto en el caso de que esten en las mismas coordenadas, en cuyo caso son siempre SPIDERFIABLE. Si 2 o mas puntos están en la misma posición siempre van a ser SPIDERFIABLE excepto cuando se clica sobre ellos que se desagregan y pasan a ser SPIDERFIED y por tanto hay que asignarles su icono por defecto. Una vez que clico en alguno de estos puntos vuelven a ser SPIDERFIABLE y por tanto se le pone el icono de agrupación. Lo mismo que si se clica en otro punto que no sean estos, la libraría considera esos puntos como SPIDERFIABLE y se pone igualmente el icono de grupo. El estado SPIDERFIABLE quiere decir que el punto esta “lo suficientemente cercano” a otro o incluso en el mismo punto como para que se agrupen y se muestre el icono de agrupación. Este “suficientemente cercano” lo determina la librería y se puede configurar con la propiedad nearbyDistance que por defecto tiene el valor de 20 pixels de radio. El estado SPIDERFIED significa que el punto formaba parte de una agrupación y al clicar encima se desagrega y hay que ponerle el icono que le pertenece hasta que vuelva a su estado SPIDERFIABLE. La librería calcula en todo momento la cercanía de los puntos y a partir de este calculo determina que puntos son SPIDERFIABLE, SPIDERFIED y UNSPIDERFIABLE y esto es lo que lanza el evento “spider_format” para cambiar el icono. Cada vez que el usuario interactua con el mapa, bien clicando en algún punto o bien aumentando o disminuyendo el zoom se llama a la función “spider_format” que se encarga de recalcular y mostrar el icono correspondiente y en caso de que sea necesario agrupar o desagrupar puntos le pinta el icono correspondiente. El código en si, una vez que entiende el funcionamiento de los diferentes estados no tiene mayor complicación. Lo único que hay que tener en cuenta son 2 cosas:
  1. En el json para cada punto indico que icono hay que cargar. Esta información como en el json va como una cadena, al asignarla en la generación del icono y al cambiar el icono hay que evaluarla con la función eval de javascript para que obtenga su verdadero valor
  2. Los datos de los iconos hay que meterlos dentro de la función addMarkerWithData para que funcione la clausura. Si se se sacan fuera ya no va a funcionar la asignación del icono correspondiente. Si no tienes claro como funcionan las clausuras te recomiendo visitar los siguientes links:

https://developer.mozilla.org/es/docs/Web/JavaScript/Closures http://www.jmocana.eu/javascript-clausuras/

Aquí teneis el código completo del ejemplo en html, lo único que faltaría es el json que teneis al principio con los puntos y que se carga como archivo externo «datos.json» (línea 16) y los iconos que estamos usando que los podeis sustitutir por los que querais. Como pódeis ver es casi idéntico al original con excepción de las pequeñas modificaciones comentadas