He encontrado un tutorial muy chulo de cómo crear un efecto de desenfoque de movimiento en lHTML usando Javascript y un filtro de desenfoque SVG (Scalable Vector Graphics).
Aquí podéis ver una demo: Ver Demo y aquí os lo podéis descargar: Descarga
El desenfoque de movimiento es una técnica ampliamente utilizada en gráficos en movimiento y en animación en general para hacer que el movimiento parezca más suave y natural.
Motion blur es el rastro dejado por los objetos en movimiento en una fotografía o en una secuencia de imágenes como una película o una animación. Aparece cuando el objeto siendo grabado cambia su posición durante la captura de un fotograma debido a su velocidad o al movimiento de la cámara.
En este tutorial, vamos a echar un vistazo a cómo hacer una aproximación de dicho efecto, para transiciones horizontales o verticales.
Atención: Tened en cuenta que este efecto es altamente experimental y sólo sirve en algunos navegadores modernos. Chrome parece tener el mejor rendimiento para usar este efecto.
Con el fin de aplicar un efecto de desenfoque de movimiento a una animación , tenemos que aplicar un desenfoque direccional al objeto de acuerdo con la velocidad y la dirección en la que se está moviendo , para cada frame.
Echemos un vistazo a los pasos que necesitamos hacer para entender cómo funciona el efecto :
Ajustando el desenfoque:
Dado que el filtro normal de desenfoque de CSS no soporta el desenfoque direccional, vamos a tener que utilizar filtros SVG.
Si queréis saber más sobre los conceptos básicos de los filtros SVG, podéis entrar en este enlace: Creative Gooey Effects article.
Para este efecto , sólo vamos a usar el filtro feGaussianBlur.
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" class="filters"> <defs> <filter id="blur"> <feGaussianBlur in="SourceGraphic" stdDeviation="0,0" /> </filter> </defs> </svg>
El atributo stdDeviation se utiliza para ajustar la intensidad del desenfoque, y puede coger hasta dos parámetros, para el desenfoque en horizontal y en vertical.
Aplicar el filtro a un elemento, como hemos visto antes, es bastante simple :
.selector{ -webkit-filter: url("#blur"); filter: url("../index.html#blur"); }
Para el efecto de desenfoque en movimiento, sin embargo, vamos a tener que actualizar el filtro de forma dinámica para cada cuadro a través de JS .
Primero tendremos que seleccionar y guardar el filtro en una variable para que podamos acceder a él más tarde. Desde que jQuery no funciona bien con los elementos SVG, hemos tenido que seleccionar el elemento utilizando funciones nativas de JS :
Para ajustar la intensidad, es simplemente una cuestión de cambiar el atributo stdDeviation del filtro primitivo. Por ejemplo, para establecer un desenfoque de 12px horizontal
blurFilter.setAttribute("stdDeviation","12,0");
Tened en cuenta que este filtro de desenfoque sólo admite desenfoque direccional ya sea en X o en Y, y no en cualquier dirección arbitraria, por lo que debe planificar sus animaciones en consecuencia.
Tenga en cuenta sin embargo, que el cambio del filtro de desenfoque afecta a todos los objetos vinculados al mismo, por lo que necesitamos un nuevo elemento <filter > para cada objeto al que queramos aplicar este efecto. Aquí está una manera simple de crear estos filtros de forma dinámica :
// pasar por todos los objetos que necesitan el filtro de desenfoque $(".js-blur").each(function(i){ // clona el filtro var blurClone=blur.cloneNode(true); // crea y establece un nuevo ID para que podamos usar el filtro a través de CSS var blurId="blur"+i; blurClone.setAttribute("id",blurId); defs.appendChild(blurClone); // establece el CSS var filter="url(#"+blurId+")"; $(this) .css({ webkitFilter:filter, filter:filter }) // almacena la referencia del filtro en el objeto .data("blur",blurClone) ; });
Midiendo la velocidad
Para el siguiente paso, tenemos que ser capaces de calcular hasta qué punto el objeto se ha movido desde el último fotograma. Tenemos que hacer esto para cada frame. El método para lograr esto puede variar según la forma en que todo está configurado; cómo esta hecha la animación, etc. En este tutorial, vamos a tomar un enfoque más general, que, si bien no puede ser optimizado para todos los casos debería funcionar con la mayoría de JS y CSS animaciones.
Para obtener la posición , vamos a usar la función offset de jQuery, que es justo lo que necesitamos: esta devuelve las coordenadas del elemento relativo al documento (en lugar de su padre), y tiene la propiedad de transformarse en una cuenta.
Para poder comprobar los cambios y actualizar cada cuadro, usaremos requestAnimationFrame.
He aquí un ejemplo :
// el elemento al que queremos aplicar el efecto var $element=$(".selector"); // almacenando la última posición, para poder medir los cambios var lastPos=$element.offset(); // un multiplicador, para poder controlar la intensidad del efecto var multiplier=0.25; // una ayuda para simplificar la configuración del desenfoque function setBlur(x,y){ blurFilter.setAttribute("stdDeviation",x+","+y); } (function updateMotionBlur(){ // obtener la posición actual del elemento var currentPos=$element.offset(); // calcular los cambios del último frame y aplicar el multiplicador var xDiff=Math.abs(currentPos.left-lastPos.left)*multiplier; var yDiff=Math.abs(currentPos.top-lastPos.top)*multiplier; // establecer el desenfoque setBlur(xDiff,yDiff); // almacenar la posición actual para el siguiente frame lastPos=currentPos; // llamar a actualizar en le siguiente frame requestAnimationFrame(updateMotionBlur); })();
Y aquí está el resultado :
Este es el planteamiento básico que tiene sólo un elemento en consideración. Un uso más complicado podría requerir código optimizado para ese caso en particular.
Y eso es todo! Puedes encontrar este proyecto en GitHub y si todo esto te ha sonado a chico, el 15 y 16 de Mayo empieza un nuevo Curso de Diseño Web.