jsFlow: Cover Flow para Javascript


Coverflow
Imagen capturada de jsFlow.


Buscando la manera de conseguir el efecto cover flow he encontrado desde aplicaciones en PHP y Javascript hasta tutoriales para hacerlo manualmente en Photoshop o Flash. En mi caso necesito obtener el cover flow de una imagen en tiempo real, por lo que he descartado cualquier método a golpe de ratón. Con flash cada vez me hablo menos y por otro lado dejarle la carga del proceso al servidor es algo que quería evitar, así que la única opción posible era Javascript.

Encontré este bonito script para generar el cover flow de cualquier imagen, pero al leerme el acuerdo de licencia (para una vez que lo hago...) se me quitaron las ganas de usarlo por sus restricciones.

Sin embargo le debo a ese acuerdo de licencia que en estos momentos pueda enseñaros mi propio Cover FLow para Javascript: jsFlow, el cual por supuesto sí va a poder usarse en cualquier web, independientemente de la cantidad de publicidad y/o pornografía que se recoja en ella, o de los trillones que facture anualmente, si se diera el caso.

jsFlow permite por medio de una sencilla llamada a un función obtener el efecto cover flow de una imagen. Su sintaxis es la siguiente:

jsFlow(idImage,reflection,light,angle,deep,imageSource)

  • idImage: ID de la imagen de la que queremos obtener su efecto cover flow.
  • Reflection: Expresado en pixels indica el tamaño vertical que tendrá el reflejo que proyecta la imagen.
  • Light: Indica el nivel de luz que queremos para el reflejo, donde 0 es el mínimo y 255 el máximo. Light es el equivalente al canal alpha o transparencia.
  • Angle: Expresado en grados permite indicar el ángulo que queremos aplicar, entre un rango de 0 a 180 grados.
  • Deep: Expresado en píxeles indica la profundidad. Cuanto mayor más pronunciado será el efecto de perspectiva.
  • imageSource: (opcional). Nos permite indicar el ID de una imagen distinta para tomarla como referencia.


Veamos algunos ejemplos



El siguiente script muestra jsFlow en funcionamiento. Pulsando sobre cada uno de los botones se ejecuta la función jsFlow variando el ángulo.





  • Left: jsFlow(´muestra´,50,100,25,100,´original´);
  • Center: jsFlow(´muestra´,50,100,0,0,´original´);
  • Right: jsFlow(´muestra´,50,100,155,100,´original´);


¿Cómo funciona jsFlow?

Para los más curiosos paso a explicar el modo de trabajo de jsFlow.

// Definimos la función jsFlow

function jsFlow(idImage,reflection,light,angle,deep,imageSource){

  /*
  Si no se ha especificado una imagen de origen alternativa (imageSource) usaremos la misma que haya en idImage.
  Cargamos en memoria la imagen, y creamos un canvas o lienzo que usaremos para trabajar la imagen.
  */
  imageSource=(!imageSource)?idImage:imageSource;
  var image = document.getElementById(imageSource);
  var reflexCanvas = document.createElement("canvas"); 
  var reflexCanvasContext = reflexCanvas.getContext("2d");
  
  /*
  Obtenemos el tamaño de la imagen y le asignamos el mismo a nuestro canvas haciéndolo más alto para que
  podamos dibujar el reflejo. 
  */
  var w = image.width;
  var h = image.height;
  reflexCanvas.width = w;
  reflexCanvas.height = h + reflection;
  
  /*
  Convertimos el parámetro angle expresado en grados a radianes y calculamos el ancho con el que veremos la imagen.
  */
  radianes = ((90+angle) * (Math.PI/180));
  w2 = Math.abs(parseInt(Math.sin(radianes)*w));

  /*
  Copiamos la imagen en el canvas, aplicamos la compresión tal, que nos de la imagen del ancho calculado anteriormente y obtenemos una matriz de los datos para poder trabajar la imagen.
  */
  reflexCanvasContext.drawImage(image,0,0,w,h,0,0,w2,h);
  var imageData = reflexCanvasContext.getImageData(0,0, w, h+reflection);

  /*
  Aplicamos el reflejo leyendo los píxeles de la parte inferior de la imagen y escribiéndolos bajo esta, respetando el color y aplicando el canal alfa correspondiente a la luz indicada en el parámetro light.
  En la matriz cada pixel viene expresado por 4 valores: Rojo, Verde, Azul y Alfa, por lo que multiplicamos por 4 para obtener el pixel de cada coordenada.
  */
   for (y = 0; y <= reflection; y++){
   	   for (x = 0; x <= w2; x++){	 				 
						 origen = (w*(h-y)+x)*4; // = ((h-y)*4)*w+(x*4)
						 destino = (w*(h+y)+x)*4; // = ((h+y)*4)*w+(x*4)

						 imageData.data[destino] = imageData.data[origen];
						 imageData.data[destino+1] = imageData.data[origen+1];
						 imageData.data[destino+2] = imageData.data[origen+2];
						 imageData.data[destino+3] = light-(y*light)/reflection;	   
						 }
  	   }
			
   /*
   Volcamos la matriz que hemos obtenido en el canvas.
   */
   reflexCanvasContext.putImageData(imageData,0,0);

   /*
   Sustituimos la imagen idImage por el canvas, que contiene la versión comprimida y con reflejo, manteniéndole el mismo Id.
   */	 
   document.getElementById(idImage).parentNode.replaceChild(reflexCanvas,document.getElementById(idImage));
   reflexCanvas.id = idImage;

   /*
   Creamos un nuevo canvas, esta vez para trabajar la perspectiva de la imagen.
   */
   var perspectiveCanvas = document.createElement("canvas"); 
   var perspectiveCanvasContext = perspectiveCanvas.getContext("2d");
	
   /*
   Asignamos al nuevo canvas el tamaño exacto para contener la imagen con el reflejo que habíamos calculado.
   */ 
   perspectiveCanvas.width = w2;
   perspectiveCanvas.height = h + reflection;

   /*
   Calculamos la posición del extremo opuesto de la imagen teniendo en cuenta el ángulo indicado.
   */
   h2 = Math.abs(parseInt (Math.cos(radianes) * deep));
   
   /*
   Aplicamos la perspectiva recorriendo la imagen horizontalmente y aplicando la reducción proporcinal de cada columna
   */
   for (x = 0; x <= w2; x++){
     	 crop=(x * h2) / w2;
	   	 size=h + reflection - crop;
			 pos=( angle > 90)?w2 - x:x;
   		 perspectiveCanvasContext.drawImage(reflexCanvas,pos,0,1,h+reflection,pos,crop/2,1,size);
	   	 }
	
   /*
   Sustituimos la imagen calculada por la original manteniéndole el mismo Id.
    */
   document.getElementById(idImage).parentNode.replaceChild(perspectiveCanvas,reflexCanvas);
   perspectiveCanvas.id = idImage;
}


Algunas características de jsFlow:

  • jsFlow solo funciona por el momento en Firefox. Próximas versiones prometen ser compatibles con otros navegadores.
  • jsFlow puede aplicarse sobre cualquier imagen (jpg,bmp,gif,png... incluso GIFs animados)
  • La imagen resultante se comporta como un objeto más del navegador, pudiéndose guardar (formato PNG)


Y para terminar una sencilla aplicación a modo de ejemplo de jsFlow recorriendo cada ángulo de una imagen, espero que os guste ¡y lo incluyáis en vuestros trabajos!





Descargar jsFlow.js 2.2Kb

27-04-2009


Comentarios:

Pues yo pienso que:


Suscribirse