Skip to main content

Efecto de desenfoque de movimiento (Motion Blur) con SVG (Scalable Vector Graphics).

By 2 junio, 2015noviembre 15th, 2016Diseño web

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.

— Motion blur en Wikipedia

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.

MotionBlur_01
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");

 

 

MotionBlur_02
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 :

blur_modal

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.

Stefano Andreoli

CEO y Creative Director en Estudio Andreoli™. Docente en Monster Academy, HTML.it, IED Madrid y Jurado en Mediastars Festival. Pues.. un poco liado.

Dejar un comentario