Creación de una biblioteca de zoom de imágenes con Vanilla JavaScript

En este tutorial, vamos a crear una biblioteca de JavaScript simple para agregar efectos de zoom al pasar el mouse por encima de las imágenes. Haremos toda la biblioteca desde cero, sin depender de jQuery ni de ninguna otra dependencia externa. ¡Entremos de inmediato!

El Proyecto

Puede ver este tipo de efecto en muchos sitios de compras, incluidos los muy populares como eBay y Amazon. Por lo general, consiste en un grupo de fotos pequeñas que se pueden ampliar e inspeccionar con más detalle con una lupa flotante.

Para mantener el tutorial simple, no agregaremos demasiadas funciones a la biblioteca. Contendrá solo un archivo JavaScript, además de un archivo CSS opcional para diseñar rápidamente una galería como la de arriba.

Diseñando la Biblioteca

Antes de comenzar a construir la biblioteca, echemos un vistazo a cómo queremos que la gente la use. Tomar esa decisión de diseño primero hará que el desarrollo de la biblioteca real sea más fácil más adelante.

Dado que estamos creando un complemento de galería, las personas que lo usen necesitarán tener algo de HTML repetitivo. Este marcado contendrá sus imágenes, un div vacío para el efecto de zoom, así como algunas clases predefinidas para hacer que la biblioteca funcione.

<div id="my-gallery" class="vanilla-zoom">
    <div class="sidebar">
        <img src="images/image-1.jpg" class="small-preview">
        <img src="images/image-2.jpg" class="small-preview">
        <img src="images/image-3.jpg" class="small-preview">
    </div>
    <div class="zoomed-image"></div>
</div>

Las personas son libres de cambiar este diseño y agregar tantas imágenes como quieran. Sin embargo, es importante que cada imagen tenga el .small-preview clase, y que hay un div vacío con el .zoomed-image clase.

La biblioteca se basará principalmente en JavaScript, pero también hay algunos estilos CSS importantes que deben configurarse. Los usuarios pueden incluir nuestro archivo CSS directamente en su HTML.

<link rel="stylesheet" href="vanilla-zoom/vanilla-zoom.css">

Ahora que el marcado y los estilos están configurados, todo lo que queda es incluir la biblioteca e inicializarla.

<script src="vanilla-zoom/vanilla-zoom.js"></script>
<script>
    vanillaZoom.init('#my-gallery');
</script>

Incluir el archivo .js de la biblioteca hace que el vanillaZoom objeto globalmente disponible. El objeto tiene solo un método que es para inicializar el complemento. Toma un solo parámetro:la identificación de nuestra galería. De esta manera podemos tener varias galerías independientes inicializadas en una página.

Desarrollo de la biblioteca

Cuando construimos bibliotecas de JavaScript front-end, debemos asegurarnos de registrar su API correctamente. Hay muchas maneras de hacer esto, posiblemente la más fácil de las cuales es este método de Jordan Checkman. Le recomendamos que lea la publicación completa de su blog, pero en resumen se reduce a esto:

(function(window) {
  function define_library() {
    // Create the library object and all its properties and methods.
    var vanillaZoom = {};
    vanillaZoom.init = function(galleryId) {
      // Our library's logic goes here.
    }
    return vanillaZoom;
  }

  // Add the vanillaZoom object to global scope if its not already defined.
  if(typeof(vanillaZoom) === 'undefined') {
    window.vanillaZoom = define_library();
  }
  else{
    console.log("Library already defined.");
  }
})(window);

El código anterior está envuelto en una función autoejecutable. De esta manera cuando agregamos el vanilla-zoom.js archivo a nuestro proyecto, la biblioteca se registrará automáticamente y el vanillaZoom el objeto con todos sus métodos estará disponible para el usuario.

Nuestra biblioteca solo tiene un método:vanillaZoom.init(galleryId) . Su trabajo es seleccionar los elementos DOM de la galería y agregarles detectores de eventos.

Primero comprobamos si se han añadido los elementos adecuados al HTML y los seleccionamos. No podemos usar jQuery, por lo que debemos confiar en los métodos nativos de JavaScript para trabajar con el DOM.

var container = document.querySelector(el);

if(!container) {
    console.error('Please specify the correct class of your gallery.');
    return;
}

var firstSmallImage = container.querySelector('.small-preview');
var zoomedImage = container.querySelector('.zoomed-image');

if(!zoomedImage) {
    console.error('Please add a .zoomed-image element to your gallery.');
    return;
}

if(!firstSmallImage) {
    console.error('Please add images with the .small-preview class to your gallery.');
    return;
}
else {
    // Set the source of the zoomed image.
    zoomedImage.style.backgroundImage = 'url('+ firstSmallImage.src +')';
}

En la última línea del código anterior, tomamos la fuente de imagen de una de las imágenes de vista previa y la configuramos como fondo de nuestro elemento ampliable. Esto sucede tan pronto como vanillaZoom.init(galleryId) se llama, asegurándonos de que nuestra galería no se quede vacía.

Hacemos lo mismo cuando se hace clic en una de las vistas previas. Esto permite al usuario seleccionar qué imagen desea ampliar.

container.addEventListener("click", function (event) {
  var elem = event.target;

  if (elem.classList.contains("small-preview")) {
      zoomedImage.style.backgroundImage = 'url('+ elem.src +')';
  }
});

El elemento de lupa tiene un par de detectores de eventos adjuntos. El primero se activa cuando el cursor ingresa al elemento, aumentando el tamaño de la imagen de fondo, creando así un efecto de zoom.

zoomedImage.addEventListener('mouseenter', function(e) {
    this.style.backgroundSize = "250%"; 
}, false);

Dado que la imagen ahora es muy grande, no cabrá en el contenedor y solo una parte será visible. Queremos que los usuarios puedan seleccionar qué parte de la imagen se amplía, por lo que agregamos un detector de movimiento del mouse que cambia la posición del fondo.

zoomedImage.addEventListener('mousemove', function(e) {

  // getBoundingClientReact gives us various information about the position of the element.
  var dimentions = this.getBoundingClientRect();

  // Calculate the position of the cursor inside the element (in pixels).
  var x = e.clientX - dimentions.left;
  var y = e.clientY - dimentions.top;

  // Calculate the position of the cursor as a percentage of the total size of the element.
  var xpercent = Math.round(100 / (dimentions.width / x));
  var ypercent = Math.round(100 / (dimentions.height / y));

  // Update the background position of the image.
  this.style.backgroundPosition = xpercent+'% ' + ypercent+'%';

}, false);

Cuando el cursor sale de la imagen ampliada, queremos que vuelva a la normalidad. Esto se hace fácilmente devolviendo el tamaño de fondo a cover y la posición de fondo a center .

zoomedImage.addEventListener('mouseleave', function(e) {
    this.style.backgroundSize = "cover"; 
    this.style.backgroundPosition = "center"; 
}, false);

Y con eso, ¡hemos terminado!

Soporte del navegador

La biblioteca debería funcionar en todos los navegadores de escritorio modernos, aunque es posible que algunos de los CSS de flexbox no se muestren correctamente en IE más antiguos.

Lamentablemente, el efecto de zoom no se traduce muy bien en dispositivos táctiles. Debido a esto y al espacio limitado de la pantalla, es mejor presentar sus imágenes de otra manera para dispositivos móviles. En nuestro CSS, simplemente ocultamos el elemento de zoom y enumeramos las imágenes verticalmente, pero puede probar otras soluciones, como un carrusel.

Conclusión

Puede obtener el código fuente completo de este artículo, así como el código de demostración (con imágenes cortesía de Burst), desde Descargar botón cerca de la parte superior de la página. Eres libre de usar la biblioteca en todos tus proyectos, comerciales o personales (nuestra licencia). ¡Feliz codificación!