Sustitución de imagen con efecto mosaico

En este efecto se trata de cambiar la imagen de un bloque con efectos dinámicos.

La imagen antigua va a desaparecer y la nueva va a ir apareciendo por cuadrículas.

La imagen nueva aparece en forma de mosaicos, como si las imágenes estuvieran formadas por celdas

Solución

<body>

<div class="mosaic-container" >

<!-- Los tiles se generarán por JavaScript -->

</div>

</body>

<script>

//Crea un grid de tiles dentro de un contenedor

function buildGrid(cols, rows, className, width, height){

for (let y = 0; y < rows; y++) {

for (let x = 0; x < cols; x++) {

const tile = document.createElement('div');

tile.className = className;

tile.style.backgroundPosition = `-${x * (width/cols)}px -${y * (height/rows)}px`;

container.appendChild(tile);

}

}

}

//Mostrar tiles secuencialmente

function showTile(container){

container.children[container.idx].classList.add('show');

const maxIdx = tiles.length

container.idx++

if (container.idx < maxIdx){

setTimeout(showTile, 100, container)

}

else{

container.idx=0

setTimeout(hideTile, 2000, container)

}

}

//Ocultar tiles secuencialmente

function hideTile(container){

container.children[container.idx].classList.remove('show');

const maxIdx = tiles.length

container.idx++

if (container.idx < maxIdx){

setTimeout(hideTile, 100, container)

}

}

//Mostrar tiles en orden aleatorio

function showTileRnd(container){

const tiles = container.children

const maxIdx = tiles.length

//establce orden aleatorio de aparición de los tiles

if(!container.tilesIdxs){

container.tilesIdxs = [...Array(maxIdx).keys()];

shuffleList(container.tilesIdxs);

}

let idx = container.tilesIdxs[container.idx];

tiles[idx].classList.add('show');

container.idx++;

if (container.idx < maxIdx){

setTimeout(showTileRnd, 50, container)

}

else{

container.idx=0;

setTimeout(hideTileRnd, 2000, container)

}

}

//Ocultar tiles en orden aleatorio

function hideTileRnd(container){

const tiles = container.children

const maxIdx = tiles.length

let idx = container.tilesIdxs[container.idx];

tiles[idx].classList.remove('show');

container.idx++;

if (container.idx < maxIdx){

setTimeout(hideTileRnd, 50, container)

}

}

//Baraja el orden de una lista

function shuffleList(idxs) {

for (let i = idxs.length - 1; i > 0; i--) {

const j = Math.floor(Math.random() * (i + 1));

[idxs[i], idxs[j]] = [idxs[j], idxs[i]];

}

}

//Establecer valores iniciales y lanzar la animación

const cols = 5, rows = 5;

const width = 500, height = 500;

const container = document.querySelector('.mosaic-container');

container.style.setProperty('--width', `${width}px`);

container.style.setProperty('--height', `${height}px`);

container.style.setProperty('--cols', `${cols}`);

container.style.setProperty('--rows', `${rows}`)

container.idx =0;

buildGrid(cols, rows, 'tile', width, height);

const tiles = document.querySelectorAll('.tile');

//Llama a intervalos de 50ms a showTile

setTimeout(showTile, 50, container)

</script>

<style>

.mosaic-container {

position: relative;

width: var(--width);

height: var(--height);

display: grid;

grid-template-columns: repeat(var(--cols), 1fr);

grid-template-rows: repeat(var(--rows), 1fr);

overflow: hidden;

background-image: url('/imgs/back_1.webp');

perspective: 1500px;

}

.tile {

width: 100%;

height: 100%;

opacity: 0;

background-image: url('/imgs/back_2.webp');

background-size: var(--width) var(--height);

transform: rotateX(90deg) scale(1);

transition: opacity 0.3s, transform 0.3s;

}

.tile.show {

opacity: 1;

transform: rotateX(0deg) scale(1);

}

</style>

Explicación

El elemento body contine un bloque con la clase mosaic-container cuyo contenido se va a crear mediante Javascript.

Va a contener un grid cuyas celdas tendrán como fondo otra imagen, esta va a reemplazar a la primera en forma animada

El código JavaScript

El javascript es el que hace la magia

Primero calcula las variables que usará el CSS para los estilos del grid conteniendo las imágenes que se van a intercambiar.

Estas variables CSS las coloca mediante el atributo style en el bloque mosaic-container

Este mosaic-container tiene una imagen de fondo Img_A

Luego construye el grid creando los bloques div que hemos configurado con las rows y columns.

Cada celda de este grid está incialmente oculta y tiene una parte de la imagen de fondo Img_B

A partir de aquí solo se trata de ir mostrando las celdas individuales añadiéndole la clase show, de esta forma se deja de ver la img_A y se ve por partes la Img_B

Esto se hace con un setTimeInterval que llama a una función que muestra la celda

Aquí puedes poner la animación que quieras, en el ejemplo es tan solo un giro y fade

En el ejemplo las celdas se muestran de forma secuencial, pero tienes otra función para mostrarla en forma aleaatoria showTileRnd

Los estilos CSS

El estilo mosaic-container es el contenedor de la imagen. Usa un layout tipo grid definido mediante variables CSS que lee desde el bloque HTML

Como el efecto es de giro 3D le ponemos la propiedad perspective

El estilo tile define como se ve cada cuadrícula del grid, cada mosaico.

Y la clase show es la que hace que la celda o mosaico sea visible. El cambio de .tile a show los puedes animar como quieras

Notas

En este ejemplo se sustituyen dos imágenes solamente, primero la Img_A se ve sustituida por la Img_B.

Una vez substituida espera 2seg y vuelve a ocultar la Img_B apra que se vea la img_Atras un intervalo vuelve al estado original. Pero en el intervalo puedes cambiar las src de las imágenes para tener más imágenes, como un carrusel.