martes, 7 de septiembre de 2010

Doodle de Google, con jQuery


Tanto misterio rodea el nuevo doodle de Google, tanto que medio mucha curiosidad. La semana pasada nos presentaba un doodle al parecer con canvas en el cual se animaba la molecula de carbono, pero gran sorpresa me dio ver que este doodle estaba hecho con puros div's.

Despues de muchas vesiones, logre que quedara algo similar, mis respetos para los desarrolladores de Gooogle. Mi version la pueden checar en este link.

HTML
El codigo html ha sido algo de lo mas sencillo, un conjunto de div's, los cuales van a estar colocados en la posicion deseada, como es un copia de la idea, el tamaño de los mismos es aleatorio.


CSS
En este punto basta con indicarle que tendra una posicion se absoluta, y sobre todo, las clases para los colores. El top y left asi como el ancho y alto los he definido en el atributo style de cada div.

Javascript
Primer paso: Almacenar posicion y tamaño. Como la idea que es las particulas(div's) anden volando por toda la pantalla, y para que se vea mas espectacular, cambien de tamaño, es necesario el almacenamiento de los datos iniciales de cada particula. Con la funcion data(), asigno un objeto que contiene dichos datos para recuperarlos porteriormente.

$('#mip').find('div.particle').each(function(){
var oPosition = $(this).position();
oPosition.width = $(this).width();
$(this).data('offset',oPosition);
});

[Inicio de Actualizacion]
Paso 1.1: Deten la propagacion del evento: Refinando el codigo, encontre que cuando de casualidad el mouse llega a tocar una particula genera un evento mousemove, el cual por Bubbling es capturado por el evento mousemove del contenedor de las particulas, con los cual es importante detener la progagacion del evento

$('#mip div.particle').mousemove(function(e){
e.stopPropagation();
});

[Fin de Actualizacion]
Segundo paso: Escuchador del evento. Asigno un escuchado al evento mousemove del div que contiene a las particulas.

$('#mip').mousemove(function(e){//codigo});

Tercer paso: El movimiento de la particula. Una vez que se genera el evento mousemove se obtiene datos y se realizan los siguientes calculos:
a) ¿Donde esta la particula? Con la funcion position obtengo un objeto que me proporciona el top y left actual de la particulas dentro del div contenedor

o = $(this).position();

b) ¿Que tanto se va a alejar la particula? Por medio de dos numero generados aleatoriamente, rx y ry.

ry = Math.floor(Math.random()*200);
rx = Math.floor(Math.random()*200);

c) ¡Ahi viene el mouse! Tal parece que las particulas no va a ser amigas del mouse, se valida que el mouse este los suficientemente cerca de la particula, en este caso ocupo una variable m que define el margen alredor, entre comillas (toma el top y left a partir del cual esta dibujada la particula, pero casi no se nota), de la particula.

ex = e.layerX;
ey = e.layerY;
if(
((o.top<=ey&&(o.top+m)>ey)&&(o.left<=ex &&(o.left+m)>ex))||
((o.top>ey&&(o.top-m)<=ey)&&(o.left<=ex &&(o.left+m)>ex))||
((o.top<=ey&&(o.top+m)>ey)&&(o.left>ex &&(o.left-m)<=ex))||
((o.top>ey&&(o.top-m)<=ey)&&(o.left>ex &&(o.left-m)<=ex))
)

d) ¿De que lado viene el mouse? Se determina de que lado de la particula se genero el evento,
con lo cual los valores almacenado en rx y ry se sumaran o restaran en el sentido contrario
con respecto al punto donde se genero el evento.

y = o.top<=ey?((o.top+m)<=ey?o.top:o.top-(ry+m)):
((o.top-m)>ey?o.top:o.top+(ry+m));
x = o.left<=ex?((o.left+m)<=ex?o.left:o.left-(rx+m)):
((o.left-m)>ex?o.left:o.left+(rx+m));

e) ¡Muevete! Para animar las particulas ocupo la funcion animate, a la cual se le pasa como primer parametro los datos calculados(top,left,ancho,alto,opacidad) almacenados en un objeto, como segundo parametro otro objeto el cual va a tener la duracion, el tipo de movimiento para los estilos, en este caso el top y left; y por ultimo la funcion callback, la cual hara que regrese la particula a su lugar.

h = Math.floor(Math.random()*100);
op = {top:y,
left:x,
width:rx,
height:rx,
opacity:(Math.floor(Math.random()*100)/100)}
$(this)
.stop()
.animate(op,
{duration:randomFromTo(500,1000),
specialEasing:{top:'easeOutBounce',
left:'easeOutBounce'},
complete:function(){/*Regresa la particula*/});

Cuarto Paso: I'll be back. Por ultimo la particula debe de regresar al lugar que le corresponde y con la misma forma, con lo cual se obtiene los datos almacenados en la particula y asginarlos a sus correspondientes atributos de estilo.

y = $(this).data('offset').top;
x = $(this).data('offset').left;
h = $(this).data('offset').width;
$(this).animate({top:y,
left:x,
width:h,
height:h,
opacity:1},
{duration:randomFromTo(800,1000),
specialEasing:{top:'easeOutBounce',
left:'easeOutBounce'}});


He aqui el codigo completo

Me he divertido mucho haciendo este codigo. Cualquier duda, comentario o apartacion seran bien recibido.

Saludos.