Crysfel’s Blog

Visor de imagenes

Wednesday, July 11, 2007, 04:42:46 pm

Featured, JavaScript, Tutoriales

El día de hoy quiero mostrar como hacer un visor de imágenes, con esta interfase es suficiente para realizar una galería, claro esta que esto es solo la GUI, el backend dependerá de las necesidades de cada proyecto en especifico.

Para que te des una idea de lo que mostrare en este tutorial, puedes ver el siguiente ejemplo.


imagen1imagen2
imagen3imagen4

¿Interesante no?, realizarlo es muy sencillo, así que para comenzar es necesario descargar la última versión de mootools (v1.11) e importarla a tu documento, pues es indispensable para este tutorial.

<script type="text/javascript" src="mootools.v1.11.js"></script>

Ahora bien, lo primero es crear una clase (VisorImagenes), la cual contiene los métodos y propiedades necesarios para visualizar las imágenes.

function VisorImagenes(){
    this.file;
    this.img;

    //Crear la estructura visual
    this.constructor = function(){}

    //Mostrar el visor
    this.aparece = function(f,t){}

    //Cargar la imagen a mostrar
    this.cargaImagen = function(){}

    //Redimensionar el contenedor de la imagen
    this.redimensionar = function(){}
}

Hasta este punto solo cree la estructura de la clase, esto es una especie de prototipo con el fin de visualizar cada paso de este tutorial, file es la url donde se encuentra la imagen a mostrar, img es una referencia al nodo donde se encuentra la imagen en el documento, y los métodos creo que es suficiente el comentario de estos en el código.

Una vez claros en la construcción de esta aplicación es hora de crear la estructura visual, para esto es necesario crear los elementos y agregárselos al body como hijos,aclaro una vez mas que este método simplemente hace la estructura del visor de imágenes al igual que el CSS necesario, a continuación se muestra el pseudo código del método y mas adelante se codifica.

this.constructor = function(){
    //Crear el nodo principal cvrVisor (<div>)
    //Crear el nodo  para el fondo obscuro (<div>)
    //Crear el nodo contenedor de la imagen y el texto (<div>)
    //Crear el nodo de salida del visor (<a>)
    //Crear el nodo para la imagen (<img>)
    //Crear el nodo para el texto (<p>)
    //Asignar coordenadas centrales al contenedor de la imagen y texto
    //Hacer las asignaciones de los nodos creados anteriormente
    //Agregar el arbol que creamos anteriormente al body del documento
}

Primeramente hay que crear el elemento principal, asignándole como id cvrVisor, su función es agrupar todos los elementos necesarios, sus dimensiones son todo el ancho de la pantalla y todo el largo también, esto que he comentado se resume en

var panel = new Element('div', {
        'styles': {
        'position': 'absolute',
        'top':'0px',
        'left':'0px',
        'width': '100%',
        'height':  window.getScrollHeight()+'px'
    },
    id:'cvrVisor'
});

La clase Element crea un nodo o elemento XHTML y lo pone en memoria, es importante señalar que no esta dentro del DOM todavía, simplemente es un nodo perdido en la memoria, es por eso que hacemos una referencia a este con la variable panel, como primer parámetro en el constructor se pasa el elemento XHTML que quieres crear, en este caso un div, el segundo argumento o parámetro es un objeto con propiedades, en este objeto se le pueden pasar eventos, estilos, el ID que le queramos asignar, entre muchas cosas mas, claro esta que estos parámetros son opcionales, si quieres saber mas al respecto te recomiendo darle un vistazo a la http://docs.mootools.net/Native/Element.js documentación en mootools. Lo unico que hicimos anteriormente fue crear una capa con ID cvrVisor, que ocupa toda la pantalla, este elemento es el padre de todos los elementos que continúan.

Siguiendo con el pseudo código es hora de hacer el fondo de color negro que es del mismo tamaño del elemento anterior, la relación se hará mas adelante, por ahora solo se crea en memoria y se guarda la referencia en la variable fondo, no comentare sobre el CSS aplicado pues este tutorial no es sobre CSS, si tienes conocimientos sobre CSS entenderás el porque de esto, si no pues solo te queda creerme por fe o googlear un poco.

var fondo = new Element('div', {
        'styles': {
        'position': 'relative',
        'width': '100%',
        'height': '100%',
        'background-color': '#000'
    },
    'id':'cvrFondo'
});

Ahora se crea el elemento que contiene la imagen y el texto, inicialmente será de 100×100, color blanco y contendrá como fondo una imagen centrada de el cargador, esto con el fin de mostrar al usuario que la imagen se esta cargando, cuando la imagen aparece el cargador queda oculto.

var cont = new Element('div', {
    'styles': {
        'position': 'absolute',
        'top': '0px',
        'left''0px',
        'width': '100px',
        'height''100px',
        'background-color': '#fff',
        'padding': '5px',
        'background-image': 'url(cargador.gif)',
        'background-repeat': 'no-repeat',
        'background-position': 'center'
    },
    'id':'cvrContenedor'
});

Es hora de crear el botón de salida, lo interesante aquí es que ahora agregamos un evento, se trata de cuando se de clic sobre el link, este desaparezca lentamente el fondo y el visor, además de que por medio de CSS se ha posicionado sobre toda la pantalla este botón de salida, al final se le agrega el texto ‘salir’.

var salir = new Element('a', {
    'title':'Clic para salir',
    'styles': {
        'display': 'block',
        'width': '99.9%',
        'height''99.8%'
    },
    'events': {
        'click': function(){
            new Fx.Style($('cvrFondo'), 'opacity',{duration:500,onComplete:function(){$('cvrVisor').style.display = "none";}}).start(0.7,0);
            return false;
        }
    }
});
salir.setText('Salir');

Se crea la imagen, esto no tiene nada especial, solo comentar que no se le esta poniendo el recurso, pues se le asignara dinamicante dependiendo de la imagen que se quiera mostrar.

var img = new Element('img', {
    'styles': {
        'margin': '0px'
    },
    'id':'cvrImagen'
});

Por ultimo se crea el contenedor del texto, el cual contendrá la descripción de la imagen mostrada.

var p = new Element('p', {
    'styles': {
        'margin': '0px',
        'padding': '0px'
    },
    'id':'cvrDescripcion'
});

Ya tenemos todos los elementos necesarios en memoria, pero no los hemos asignado al DOM, así que los siguientes pasos son relacionar los elementos que se han creado y asignárselos al DOM, en este caso como hijos del body, el código esta comentado para mejor entendimiento.

//Se le asigna 70% de opacidad al fondo y se posiciona en el centro de la pantalla
new Fx.Style(fondo, 'opacity').set(0);
cont.style.top = window.getScrollTop() + window.getHeight()/2 - 50 - 15 +"px";
cont.style.left = window.getWidth()/2 - 50 + "px";

// Se agrega la imagen y el texto al contendor de estos
cont.appendChild(img);
cont.appendChild(p);

//Se le agrega el boton salir al fondo
fondo.appendChild(salir);

//Se agrega el fondo y el contenedor de la imagen y texto al visor
panel.appendChild(fondo);
panel.appendChild(cont);

//Se desaparece el visor, esto da como consecuencia
//que todos sus hijos desaparezcan con el
panel.style.display = 'none';

//Se agrega al DOM, en este caso al body
document.body.appendChild(panel);

Hasta este punto ya esta en el DOM la estructura necesaria para el visor, esta estructura es semejante a esto

<div id="cvrVisor" style="position: absolute; top: 0px; left: 0px; width: 100%; height: 837px; display: none;">
    <div id="cvrFondo" style="position: relative; width: 100%; height: 100%; background-color: rgb(0, 0, 0); visibility: hidden; opacity: 0;">
        <a style="display: block; width: 99.9%; height: 99.8%;" href="#">Salir</a>
    </div>
    <div id="cvrContenedor" style="padding: 5px; position: absolute; top: 146px; left: 664px; width: 335px; height: 525px; background-color: rgb(255, 255, 255); background-image: url(cargador.gif); background-repeat: no-repeat; background-position: center;">
        <img id="cvrImagen" title="Imagen" style="visibility: visible;"/>
        <p id="cvrDescripcion" style="margin: 0px; padding: 0px;"></p>
    </div>
</div>

Se ha logrado lo que se buscaba, pues ay tenemos listo los elementos necesarios, ahora es necesario programar los efectos respectivos, lo que sigue ahora es programar el método aparece, de la clase que definimos anteriormente, este método recibe dos parámetros, la url de la imagen a cargar, y la descripción de la misma, el siguiente es el pseudo código de lo que se codificara.

this.aparece = function(f,t){
    //Se asigna a la variable file la url actual
    //Se pone visible el visor de imágenes
    //Se hace la animación de fade in
    //Se asigna la descripción al elemento
    //Se carga la imagen
}

Esto, codificado, queda de la siguiente manera

this.aparece = function(f,t){
    this.file = f;
    $('cvrVisor').style.display = 'block';
    var f = new Fx.Style('cvrFondo', 'opacity',{duration:500});
    f.set(0);
    f.start(0,0.7);
    $('cvrDescripcion').setText(t);
    this.cargaImagen();
}

Lo único interesante es notar que la le estamos asignando 500 milisegundos a la animación, esta animación se la estamos aplicando al elemento con ID cvrFondo, la opacidad va de 0 a 0.7, esto es el 70% de la opacidad, la función cargaIMagen se describe a continuación.

this.cargaImagen = function(){ 
    $('cvrImagen').style.visibility = 'hidden';
    img = new Asset.image(this.file, {id: 'cvrImagen', title:'Imagen', onload: this.redimensionar});
}

Lo que se esta haciendo aquí es ocultar la imagen, al hacer esto es posible ver el cargador en el fondo del contenedor, después cargamos la imagen con la clase Asset, la cual mediante el método image indica cuando ha terminado la carga, de esta manera cuando termine la carga se dispara el método redimensionar el cual analizaremos con mas detalle por se un poco mas interesante.

this.redimensionar = function(){
    //Se remplaza la nueva imagen por la anterior
    $('cvrImagen').replaceWith(img);
    //Se oculta para hacer la animacion de redimension
    $('cvrImagen').style.visibility = 'hidden';

    //Se crea la animacion sobre el elemento cvrContenedor,
//al termino se hace visible la imagen
    var efecto = new Fx.Styles('cvrContenedor', {duration: 500,transition: Fx.Transitions.linear,onComplete: function(){$('cvrImagen').style.visibility = 'visible';}});

    //Se inicia la animacion, modificando las siguientes propiedades
    efecto.start({
            'width': img.getSize().size.x,
            'height': img.getSize().size.y + 25,
            'top': window.getScrollTop() + window.getHeight()/2 - img.getSize().size.y/2 - 15,
        'left': window.getWidth()/2 - img.getSize().size.x/2
    });
}

Lo interésate aquí, es que podemos modificar mas de una propiedad de los elementos al mismo tiempo, para eso se utiliza la Styles, a diferencia de la clase Style, esta puede modificar simultáneamente las propiedades que se le definan, en este caso se modificaron cuatro propiedades, el ancho, alto, coordenada en x y coordenada en y, para saber las nuevas posiciones y tamaños, es necesario saber las dimensiones de la nueva imagen, para esto simplemente accedamos mediante img.getSize().size.x para el width, donde img es la referencia al nodo que se ha cargado recientemente, el cual contiene esa información, de la misma manera para el height cambiando únicamente x por y, una vez que se saben las dimensiones de la imagen, se puede calcular fácilmente las coordenadas donde debe quedar centrada, para esto es necesario saber el ancho de la pantalla del usuario, así como el alto, luego unas simples restas de la mitad de todos los datos y listo, el contenedor queda en el centro de la pantalla.

Por ultimo se tiene que crear una instancia de esta clase.

var visor = new VisorImagenes();

window.addEvent('domready', function(){
    visor.constructor();
});

Lo que se esta haciendo aquí, es crear la instancia, y luego agregar un evento, este evento se dispara cuando el DOM esta listo, es decir que ya se puede comenzar a trabajar con el, esto es muy util pues no se tiene que esperar a que se carguen todas las imágenes del sitio para comenzar a trabajar, al momento de dispararse el evento, lo que se hace es ejecutar el metodo constructor de la clase VisorImagenes.

Para mostrar una imagen es necesario poner dentro de un boton o un link una llamada al metodo aparecer, con sus respectivos datos.

<a href="01.jpg" onClick="visor.aparece(this.href,'Foto ganadora en National Geographic 2006'); return false;">imagen 1</a>
<a href="02.jpg" onClick="visor.aparece(this.href,'Sonrrisa sincera'); return false;">imagen 2</a>
<a href="03.jpg" onClick="visor.aparece(this.href,'Tranquilidad absoluta'); return false;">imagen 3</a>
<a href="04.jpg" onClick="visor.aparece(this.href,'Camino al cielo'); return false;">imagen 4</a>

Si te has dado cuenta, los links son accesibles aún si el usuario tiene desactivado el javascript, la única diferencia es que nuestro visor de imágenes no funcionara, pero se vera la imagen de todas formas.

A continuación expongo el código completo para que copies y pegues en un documento html ;-)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml-strict.dtd">
       
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="es">
<head>
        <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1;" />

    <title>Visor de imagenes by Crysfel</title>
    <script type="text/javascript" src="mootools.v1.11.js"></script>

<style type="text/css">
html,body{
    margin:0px;
    padding:0px;
    align:center;
    height:100%;
    background-color:#ddd;
}
#frame{
    margin:0px auto;
    padding:0px;
    width:800px;
    min-height:100%;
    align:left;
    background-color:#fff;
}

*html frame{
    height:100%;
}

</style>
<script type="text/javascript">

var visor = new VisorImagenes();

window.addEvent('domready', function(){
    visor.constructor();
});

function VisorImagenes(){
    this.file;
    this.img;

    this.constructor = function(){
        var panel = new Element('div', {
            'styles': {
                'position': 'absolute',
                'top':'0px',
                'left':'0px',
                'width': '100%',
                'height':  window.getScrollHeight()+'px'
            },
            id:'cvrVisor'
        });

        var fondo = new Element('div', {
            'styles': {
                'position': 'relative',
                'width': '100%',
                'height': '100%',
                'background-color': '#000'
            },
            'id':'cvrFondo'
        });

        var cont = new Element('div', {
            'styles': {
                'position': 'absolute',
                'top': '0px',
                'left''0px',
                'width': '100px',
                'height''100px',
                'background-color': '#fff',
                'padding': '5px',
                'background-image': 'url(cargador.gif)',
                'background-repeat': 'no-repeat',
                'background-position': 'center'
            },
            'id':'cvrContenedor'
        });
        var salir = new Element('a', {
            'title': 'Click para salir',
            'styles': {
                'display': 'block',
                'width': '99.9%',
                'height''99.8%'
            },
            'events': {
                'click': function(){
                    new Fx.Style($('cvrFondo'), 'opacity',{duration:500,onComplete:function(){$('cvrVisor').style.display = "none";}}).start(0.7,0);
                    return false;
                }
            }
        });
        salir.setText('Salir');
        var img = new Element('img', {
            'styles': {
                'margin': '0px'
            },
            'id':'cvrImagen'
        });

        var p = new Element('p', {
            'styles': {
                'margin': '0px',
                'padding': '0px'
            },
            'id':'cvrDescripcion'
        });
        new Fx.Style(fondo, 'opacity').set(0);

        cont.style.top = window.getScrollTop() + window.getHeight()/2 - 50 - 15 +"px";
        cont.style.left = window.getWidth()/2 - 50 + "px";

        cont.appendChild(img);
        cont.appendChild(p);
        fondo.appendChild(salir);
        panel.appendChild(fondo);
        panel.appendChild(cont);
        panel.style.display = 'none';
        document.body.appendChild(panel);
    }

    this.aparece = function(f,t){
        this.file = f;
        $('cvrVisor').style.display = 'block';
        var f = new Fx.Style('cvrFondo', 'opacity',{duration:500});
        f.set(0);
        f.start(0,0.7);
        $('cvrDescripcion').setText(t);
        this.cargaImagen();
    }

    this.cargaImagen = function(){ 
        $('cvrImagen').style.visibility = 'hidden';
        img = new Asset.image(this.file, {id: 'cvrImagen', title:'Imagen', onload: this.redimensionar});
    }

    this.redimensionar = function(){
        $('cvrImagen').replaceWith(img);
        $('cvrImagen').style.visibility = 'hidden';

        var efecto = new Fx.Styles('cvrContenedor', {duration: 500,transition: Fx.Transitions.linear,onComplete: function(){$('cvrImagen').style.visibility = 'visible';}});
        efecto.start({
                'width': img.getSize().size.x,
                'height': img.getSize().size.y + 25,
                'top': window.getScrollTop() + window.getHeight()/2 - img.getSize().size.y/2 - 15,
            'left': window.getWidth()/2 - img.getSize().size.x/2
        });
    }

}

</script>
</head>
<body>


<div id="frame">

        <a href="01.jpg" onClick="visor.aparece(this.href,'Foto ganadora en National Geographic 2006'); return false;">imagen 1</a>
        <a href="02.jpg" onClick="visor.aparece(this.href,'Sonrrisa sincera'); return false;">imagen 2</a>
        <a href="03.jpg" onClick="visor.aparece(this.href,'Tranquilidad absoluta'); return false;">imagen 3</a>
        <a href="04.jpg" onClick="visor.aparece(this.href,'Camino al cielo'); return false;">imagen 4</a>


</div>

</body>
</html>

Pues bien, esto ha sido todo, espero pueda servirte, actualmente planeo realizar un plugin para wordpress y de esta manera poder integrar una galería de imágenes, esto para un proyecto que estoy desarrollando.

Antes de terminar quiero agradecer al chaka por proporcionar las imágenes de muestra :-)

Hasta la próxima!!

Imprimir Comentarios (5) Leer mas

5 Respuestas para este tema

Wake

Saturday, July 28, 2007, 3:08 pm

Hey chidisimo tendre que probarlo, gracias por compartir esto con los demas!! :D

WALLAS

Thursday, September 13, 2007, 8:18 pm

Ke onda vato, no pues la verdad es que se ve bueno este tutorial!!!
Thanks men ke piensas en los camaradas

Crysfel

Tuesday, October 30, 2007, 3:12 pm

Algo de suma importancia, que olvide mencionar, es que se DEBE especificar el DOCTYPE al documento, para que las funciones window.getScrollTop() y window.getHeight() funcionen correctamente.

sam

Thursday, January 3, 2008, 8:23 pm

Hola Amigo :D muchas gracias por el tutorial, pero no se por que no me funciona. No me carga las imagenes como debiera, si no que simplemente las muestra en la pagina y ya esta. He copy/paste el ultimo que pusiste. :D Algo estara mal o es que yo soy muy torpe que seguramente sea eso. Saludos

crysfel

Saturday, January 5, 2008, 8:55 pm

Ya bajaste la libreria de mootools?? seguramente es eso, si puedes poner un ejemplo en internet te pudiese ayudar mejor.

Saludos

Deja una respuesta