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.