Merida Design Blog

Publicado el | Tutoriales / , ,

Como crear un botón con ondas estilo Material Design

El Material Design es a mi gusto una de las mejores propuestas para diseño de interfaces y la evolución natural del diseño flat.

Con este estilo de diseño Google hace mayor énfasis en la retroalimentación visual a través de animaciones, y una de esas animaciones es el efecto de onda que podemos ver en sus botones. En éste artículo, veremos como recrear ese efecto con un poco de javascript y css.

Antes de continuar les dejo la muestra de lo que vamos a crear:

See the Pen Material Design button with ripple by Iván Villamil (@ivillamil) on CodePen.15465


El primer paso, es colocar el código html necesario para nuestro ejemplo.


<!DOCTYPE html>
<html>
  <head>
    ...
    <link rel="stylesheet" href="styles.css">
  </head>
  <body>
    <div class="center">
      <a href="#" class="button">Press Here</a>
    </div>
    
    <script type="text/javascript" src="scripts.js"></script>
  </body>
</html>

No hay mucho que explicar en este código realmente, lo único que quiero hacer notar es el div con la clase center, como se pueden imaginar solo me sirve para centrar el contenido en la pantalla.


A continuación definimos los estilos para el botón.


/* Estilos para el demo */
body {
  background-color: #fafafa;
  font-family: sans-serif;
  font-size: 16px;
  font-weight: 300;
}

.center {
  left: 50%;
  position: absolute;
  top: 50%;
  transform: translate(-50%,-50%);
}
    
/* Estilos del botón */
.button {
  background-color: #FF5722;
  border-radius: 6px;
  box-shadow: 2px 2px 1px rgba(0,0,0,0.4);
  color: white;
  display: block;
  overflow: hidden;
  padding: 2em 4em;
  position: relative;
  text-decoration: none;
  transition: all 200ms ease-out;
}
.button:hover {
  box-shadow: 3px 3px 5px rgba(0,0,0,0.3);
}

Los estilos definidos en las líneas 20 y 30, son los que sirven para darle ese efecto de profundidad que también es parte de las propiedades del Material Design.


/* Estilos para el efecto de la onda (ripple) */
.ripple {
  background-color: rgba(255,255,255,0.3);
  opacity: 1;
  position: absolute;
  -webkit-transform: scale(0);
  -moz-transform: scale(0);
  transform: scale(0);
  transition: all 500ms ease-out;
}

La clase anterior es la que se usa para crear el efecto y se asigna a un elemento creado dinámicamente como veremos un poco mas abajo. En esta clase se define la animación (línea 41) y también la escala inicial del objeto a 0 para que posteriormente se expanda creando el efecto de onda.


Ahora la parte interesante, el código javascript.


(function () {
  "use strict";
    
  var button = document.querySelector('.button'),
      rippleSize = button.clientWidth * 2.5;
    
  function addRipple(e, i) {
    var posX = e.offsetX,
        posY = e.offsetY,
        ripple = document.createElement('div');
        
    ripple.classList.add('ripple');
    ripple.style.left = (posX - (rippleSize / 2)) + 'px';
    ripple.style.top = (posY - (rippleSize / 2)) + 'px';
    ripple.style.height = rippleSize + 'px';
    ripple.style.width = rippleSize + 'px';
    ripple.style.borderRadius = (rippleSize / 2) + 'px';
        
    if (button.hasChildNodes()) {
      button.insertBefore(ripple, button.firstChild);
    } else {
      button.appendChild(ripple);
    }
        
    setTimeout(function () {
      ripple.style['-webkit-transform'] = 'scale(1)';
      ripple.style['-moz-transform'] = 'scale(1)';
      ripple.style.transform = 'scale(1)';
      ripple.style.opacity = 0;
    }, 10);
        
    setTimeout(function () {
      button.removeChild(ripple);
    }, 500);
  }
    
  button.addEventListener('click', addRipple, false);
}());

Ahora veamos parte por parte que hace el código anterior:

  • Línea 5: Definimos el ancho total del círculo que hará el efecto de onda, en este caso el tamaño es 2.5 veces el ancho del botón para asegurarnos de que siempre abarque todo el botón aún cuando se presione desde una esquina.

  • Líneas 8 y 9: Guardamos la posición en la que se hizo click.

  • Línea 10: Creamos dinámicamente un nuevo elemento que servirá para crear el efecto de onda.

  • Línea 12: Asignamos la clase .ripple que definimos anteriormente al nuevo elemento.

  • Líneas 13 y 14: Colocamos el nuevo elemento en la misma posición que se hizo click.

  • Líneas 15 y 16: Asignamos el tamaño (2.5 veces el tamaño del botón). El elemento aún no será visible gracias a que la clase .ripple tiene una escala cero.

  • Línea 20: Si el botón tiene mas elementos internos, insertamos el nuevo justo antes del primero.

  • Línea 22: Si el botón no tiene mas elementos, simplemente lo agregamos.

  • Líneas 25 al 30: Esperamos unos milisegundos y cambiamos las propiedades del elemento para ejecutar la animación. Esto es necesario, ya que si colocamos el código fuera del setTimeout se ejecutaría antes de que el elemento se encuentre pintado en el DOM y por lo tanto, el efecto no sería visible.
    El tiempo de espera deber ser solo lo suficiente para que el elemento sea pintado en el DOM, mi recomendación es que no sea mayor a 100 milisegundos.

  • Línea 32: Una vez terminada la animación se elimina el elemento para evitar que el botón se llene de divs vacíos.

  • Línea 37: Por último, creamos la suscripción al evento click para ejecutar la función.


Conclusión

Este código puede modificarse para convertirlo en un plugin, definiendo los estilos en el javascript y permitiendo asignar tiempos de animación y colores dinámicamente entre otras cosas, tu imaginación es el límite :D.

Si ya has hecho algo similar pero usaste una técnica distinta, no dudes en compartirlo en los comentarios.



Publicaciones que pueden interesarte

    Deja un comentario

      tope
    Derechos Reservados, Merida Design 2017
    %d bloggers like this: