Comparación de imágenes con clip-path y javascript

Superposición de imágenes una sobre otra en la que en función de la posición del cursor será mostrada diferentes porciones de las imágenes
javascript,css
Comparación de imágenes con clip-path y javascript

En una publicación anterior realicé superposición de imágenes para comparar diferentes imágenes en la que se podía elegir dos imágenes dadas para compararlas

En esta ocasión he realiado lo mismo pero con muchísimo menos código y para mi gusto más customizable. Para ello he usado la propiedad CSS clip-path. Aunque si se quisiera usar habría que ajustar con algún polyfill o alguna otra alternativa para navegador Edge

Puede verse en este enlace externo o en este Pen

Código HTML para la superposición y comparación de imágenes

Consiste en un contenedor con imágenes dentro añadidas como background, cada una de ellas superpuestas sobre la anterior

<div class="container js-comparator">
  <div class="bg bg--2-left" style="background-image: url(img/ws06-gray_main.jpg);"></div>
  <div class="bg bg--2-right" style="background-image: url(img/ws06-purple_main.jpg);"></div>
</div>

Código CSS para la superposición y comparación de imágenes

Consiste en superponer las diferentes imágenes una encima de otra y en detectar las coordenadas relativas X e Y del cursor dentro del contenedor de las imágenes. Los valores X e Y actualiza el valor de variables CSS en el evento mousemove. (Esto puede ser mejorado para hacerlo “touch friendly”)

La superposición de imágenes lo hago usando display grid y cada una de las imágenes usando el mismo grid-area

La parte interesante aquí es la definición de clip-path de cada contenedor de imagen mediante polígono de puntos. Los puntos “extremos” son referencias fijas y algunos puntos internos mediante posición variable con variables de CSS y actualizados mediante javascript con el evento mousemove

Pongo el código del primer ejemplo, el resto sería jugar con diferentes puntos y con mayor cantidad de imágenes

body {
  display: flex;
  flex-wrap: wrap;
  margin: 0;
  background-color: #f1f1f1;
}
.container {
  width: 480px;
  max-width: 96%;
  margin: 10px auto 40px;
  filter: drop-shadow(0px 0px 3px #ccc);
  cursor: pointer;
  display: grid;
  grid-template-areas: "img";
  &.active {
    cursor: move;
  }
}
.js-comparator {
  &--2 {
    --x: 50%;
  }
  //resto css
}
.bg {
  background-position: center;
  background-size: contain;
  background-repeat: no-repeat;
  width: 100%;
  height: inherit;
  max-width: inherit;
  grid-area: img;
  padding-top: 110%;
  margin: auto;
  &--small {
    padding-top: 90%;
  }

  &--2-left {
    clip-path: polygon(0 0, var(--x) 0, var(--x) 100%, 0 100%);
  }
  &--2-right {
    clip-path: polygon(var(--x) 0, 100% 0, 100% 100%, var(--x) 100%);
  }
  //resto css
}

Código JAVASCRIPT para la superposición y comparación de imágenes

Actualización de variables CSS

El método const coord = () => {} detecta la posición del “ratón” y actualiza las variables CSS –x e –y con el valor relativo a su contenedor

const coord = () => {
  const viewportX = event.clientX;
  const viewportY = event.clientY;

  const boxRectangle = event.target.getBoundingClientRect();
  const localX = viewportX - boxRectangle.left;
  const localY = viewportY - boxRectangle.top;

  const container = event.target.closest('.js-comparator');
  container.style.setProperty('--x', `${localX}px`);
  container.style.setProperty('--y', `${localY}px`);
}

Manejador del comparador

El método const handleComparator = () => {} registra o elimina el listener del evento mousemove del ratón sobre cada uno de los “comparadores”

const handleComparator = () => {
  const container = event.target.closest('.js-comparator');
  if (!container.classList.contains('active')) {
    container.classList.add('active')
    container.addEventListener('mousemove', coord, false);
  } else {
    container.classList.remove('active')
    container.removeEventListener('mousemove', coord, false);
  }
}

Activar el comparador

Se selecionan todos los nodos del DOM con clase js-comparator y a cada uno de ellos se registra el listener del evento click del ratón para activar el manejador del comparador

document.addEventListener('DOMContentLoaded', () => {

  const boxes = document.querySelectorAll('.js-comparator');
  boxes.forEach(box => box.addEventListener('click', handleComparator, false) );

});

Puede verse todo el código en mi Git

Código en mi GitHub