DÍA 3 / 2014

Custom Google Maps markers: estilos y animaciones CSS3

Cómo personalizar los marcadores (marks) de Google Maps, utilizando las clases y métodos que nos ofrece su API.
Veremos cómo personalizar su aspecto, pero también cómo podemos hacer que sean "atacables" desde CSS para animarlos con CSS3.


Hace unos meses, tuvimos que personalizar los marcadores (markers) de un mapa de Google para un proyecto, y aunque la API Javascript de Google Maps realmente me pareció amplia y fácil de entender, me di cuenta que en lo que más tiempo perdimos, fue en tener claro cómo empezar (que como siempre era una chorrada) pero la primera vez lees y lees sin tener muy claro qué hacer. Otra parte que también nos hizo perder bastante tiempo fue dar con el marker exacto que necesitábamos.

En nuestro caso, los markers debían ser redondos, de colores, y debían tener una animación inicial…ya ves, simpático que estaba el diseñador cuando lo pensó.

Empezaré por el principio para que veáis lo fácil que es presentar el mapa y después pasamos a los markers.

Nota: Para entender bien este post hay que tener unos mínimos conocimientos de JS y de programación orientada a objetos.

1. El HTML

En nuestro HTML necesitamos un div que contendrá el mapa, le ponemos un id para que sea más fácil identificarlo.
Para este ejemplo vamos a hacer un mapa que ocupe el 100% del documento.
También tendremos que poner el link a la API de Maps:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Custom markers - Google Maps</title>
    <style>
    html, body, #myMap{
        margin:0;
        padding:0;
        width: 100%;
        height: 100%;
    }
    <style>
</head>
<body>
<div id="myMap"></div>
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
</body>
</html>

2. El Mapa

Ahora tenemos que crear el mapa, al constructor debemos pasarle dos parámetros: el elemento html que va a contener el mapa, y un objeto que agrupa las opciones de configuración del mismo.

var myMap = new google.maps.Map(document.getElementById("myMap"),mapOptions)

El objeto mapOptions debe tener la configuración mínima para mostrar nuestro mapa, lo normal es especificar; zoom inicial, punto central del mapa y tipo de mapa (MapTypeId), aunque tenemos un montón de parámetros opcionales para configurar, que podéis ver aquí.

Yo voy a añadir disableDefaultUI, para que no se muestren los controles del zoom, ni el resto de elementos de la UI por defecto.

El punto central lo obtenemos mediante google.maps.LatLng(latitud, longitud), y los tipos de mapa básicos son 4;
ROADMAP, SATELLITE, HYBRID y TERRAIN.
Nosotros usaremos el ROADMAP que es el más común. (Más información acerca de tipos de mapas aquí)

var mapOptions = {
      zoom: 8,
      center: new google.maps.LatLng(40.417181, -3.700823),
      mapTypeId: google.maps.MapTypeId.ROADMAP,
      disableDefaultUI: true
};

Y para dejar nuestro mapa hecho un primor y ser limpios y ordenados, vamos a meter todo en una función init, para que el mapa se cargue en el evento load.

Hasta aquí hemos creado el mapa con la configuración que queremos y centrado en las coordenadas deseadas:

function init() {
  var mapOptions = {
      zoom: 8,
      center: new google.maps.LatLng(40.417181, -3.700823),
      mapTypeId: google.maps.MapTypeId.ROADMAP,
      disableDefaultUI: true
  };
  var myMap = new google.maps.Map(document.getElementById('myMap'), mapOptions);
}
google.maps.event.addDomListener(window, 'load', init);

3. El Custom Marker Simple

Para dibujar un marker a nuestro gusto, en vez de el típico de Google Maps rojo con el punto negro, tenemos que asociar a nuestro mapa un nuevo objeto que lo defina, para ello utilizaremos la clase google.maps.Marker.

– Le decimos dónde queremos que se coloque el marcador, en nuestro caso, en el centro del mapa, y utilizamos el método .getCenter().
– Le decimos también cómo debe representarse mediante “icon”, que a su vez tiene varios parámetros, veamos:
path determina la forma, aquí podríamos meter notación SVG que queramos (ver ejemplo). En nuestro caso vamos a utilizar unas constantes que ya nos ofrece Google, porque queremos un círculo sin más.
– Definimos el tamaño, colores de borde y relleno y opacidad.
– Y por último, a qué mapa debe asociarse (myMap)

var marker = new google.maps.Marker({
position: myMap.getCenter(),
 icon: {
  path: google.maps.SymbolPath.CIRCLE,
  scale: 10, //tamaño
  strokeColor: '#f00', //color del borde
  strokeWeight: 5, //grosor del borde
  fillColor: '#00f', //color de relleno
  fillOpacity:1// opacidad del relleno
},
map: myMap
});

Con todo esto ya tenemos un mapa con un marker personalizado, que quedaría así:

marker_personalizado

4. Animar el Marker

Aquí empezó nuestra odisea de prueba/error porque la API tiene muchas maneras de personalizar los markers (cambiar formas y tamaños, poner una imagen propia…), pero una vez que conseguimos pintar lo que queríamos, no podíamos acceder a él para animarlo, los markers simples de maps, no tienen entidad dentro del DOM, de modo que no podemos atacarlos ni con CSS ni con js.

Existen dos animaciones predeterminadas para ellos (BOUNCE y DROP), pero que no nos servían. Por otro lado, también tenemos la opción de animarlos con el método setTimeout(), pero sinceramente me parece muchísimo más complicado que la solución que encontramos nosotros.

NUESTRO AMIGO EL MARKERWITHLABEL: (Te queremos MarkerWithLabel)

Descubrimos un tipo de marcadores que pueden llevar asociada una etiqueta, totalmente personalizable y…

redoble de tambores…

se puede asociar una clase CSS!!! Albricias!! Yujuuu!!!

El truco está en utilizar el “label” como “marker”, escondiendo el propio marker, y como podemos hacer con CSS “casi” lo que queramos, es mucho más versátil que los markers estándar.

Para ello, en vez de usar la clase google.maps.Marker, usaremos la clase MarkerWithLabel y tendremos que añadir una librería que nos permite utilizarla.

<script type="text/javascript" src="https://google-maps-utility-library-v3.googlecode.com/svn-history/r391/trunk/markerwithlabel/src/markerwithlabel.js"></script>

Vais a ver que la sintaxis es muy parecida a los markers que ya hemos visto, la diferencia esencial es el juego que vamos a darle después con CSS, os pongo el código js y seguimos.

var marker = new MarkerWithLabel({
       position: myMap.getCenter(),
        icon: {
          path: google.maps.SymbolPath.CIRCLE, //el path es obligatorio, pero da igual lo que pongamos porque no se va a ver.
          scale: 0 //tamaño del marker real, le pongo 0 y así no se ve.
        },
       map: myMap,
       labelAnchor: new google.maps.Point(10, 10), // Os lo explico después del CSS.
       labelClass: "label" // LA CLASE CSS, AQUÍ LLEGA LA MAGIA!!
     });

Por último, el CSS que hará la animación, como en este caso no hemos definido ni forma ni colores porque no queremos que se vea el marker real, tenemos que hacer que el “label” parezca un marker y darle los estilos que buscamos.

Vamos a pintar un círculo verde con un borde azul, y con una sombra y todo!!!, y que al cargar tenga una animación que lo hace crecer y decrecer 3 veces, el CSS no os lo explico porque si habéis llegado hasta aquí, doy por hecho que lo sabéis interpretar:

.label {
  box-sizing:border-box;
  background: #05F24C;
  box-shadow: 2px 2px 4px #333;
  border:5px solid #346FF7;
  height: 20px;
  width: 20px;
  border-radius: 10px;
  -webkit-animation: pulse 1s ease 1s 3;
  -moz-animation: pulse 1s ease 1s 3;
  animation: pulse 1s ease 1s 3;
}

/* ANIMATIONS */
@-webkit-keyframes pulse {
 50% {
    -webkit-transform: scale(2);
    -moz-transform: scale(2);
    transform: scale(2);
  }

  100% {
    -webkit-transform: scale(1);
    -moz-transform: scale(1);
    transform: scale(1);
  }
}
@-moz-keyframes pulse {
 50% {
    -webkit-transform: scale(2);
    -moz-transform: scale(2);
    transform: scale(2);
  }

  100% {
    -webkit-transform: scale(1);
    -moz-transform: scale(1);
    transform: scale(1);
  }
}
@keyframes pulse {
  50% {
    -webkit-transform: scale(2);
    -moz-transform: scale(2);
    transform: scale(2);
  }

  100% {
    -webkit-transform: scale(1);
    -moz-transform: scale(1);
    transform: scale(1);
  }
}

Como podéis ver, nuestro círculo es de 20x20px, y ahora os explico el parámetro “labelAnchor: new google.maps.Point(10, 10)”:
Este parámetro coloca el “label” respecto del centro del marker que tiene asociado, si no lo ponemos quedaría así:

marker_personalizado2

En la imagen vemos un punto negro, que sería el marker (lo he pintado para que se vea) y veis que el label (circulo verde y azul) no está centrado. Como mi label mide 20x20px, lo muevo 10 arriba y 10 a la izquierda.

Tenéis varios ejemplos de MarkerWithLabel aquí.

Pues ya está, podéis ver el mapa final con las animaciones en este Pen:

See the Pen Custom CSS styles and animations in Google Maps markers by Diana (@diana_aceves) on CodePen.8811

Espero que os sirva! Nos vemos!

Diana Aceves

Química de carrera, programadora Java de rebote y actual desarrolladora Front-end de vocación. Me encanta la interactividad y el dinamismo en las webs, soy una fan incondicional de Sublime Text y una obsesiva del responsive. Desarrollo principalmente con Javascript y jQuery, HTML5 y CSS3. De vez en cuando doy cursos de desarrollo responsive y alguna que otra conferencia. Mis últimos trabajos están siendo apasionantes, colaborando con grandes empresas en grandes proyectos como Vogue, Vanity Fair y GQ Francia, Banco Santander, Blackphone, Geeksphone…