Este código cria uma galeria de imagens com rolagem infinita, onde as imagens se movem continuamente da direita para a esquerda. Vamos detalhar cada parte do código (HTML, CSS e JavaScript) para entender como ele funciona.
O HTML define a estrutura básica da galeria de imagens.
<div id="photo-gallery-container">
<div id="photo-gallery">
<!-- Imagens com links -->
<a class="photo-link" href="URL_IMAGEM_LARGA">
<img class="photo" src="URL_THUMBNAIL" alt="Descrição da Imagem">
</a>
<!-- Outras imagens seguem a mesma estrutura -->
</div>
</div>
#photo-gallery-container
: Contêiner principal que envolve a galeria.#photo-gallery
: Contêiner que hospeda as imagens e seus links..photo-link
: Links que envolvem as imagens. Cada link contém uma imagem
(<img>
)..photo
: As imagens em si, que são exibidas como thumbnails.O CSS define o layout e a aparência da galeria.
#photo-gallery-container {
white-space: nowrap; /* Impede que as imagens quebrem para a próxima linha */
width: 100vw; /* Ocupa toda a largura da viewport */
position: fixed; /* Fixa o contêiner na tela */
top: 50%; /* Centraliza verticalmente */
transform: translateY(-50%); /* Ajusta a centralização */
padding: 3vh 0; /* Adiciona padding vertical */
}
#photo-gallery {
display: inline-block; /* Permite que as imagens fiquem em linha */
width: max-content; /* A largura se ajusta ao conteúdo */
}
.photo-link {
display: inline-block; /* Exibe os links em linha */
width: 33vh; /* Largura fixa para cada imagem */
height: 33vh; /* Altura fixa para cada imagem */
margin: 0 3vh; /* Margem entre as imagens */
border-radius: 5px; /* Bordas arredondadas */
box-shadow: 0 12.5px 12.5px rgba(0, 0, 0, .15); /* Sombra */
overflow: hidden; /* Esconde partes da imagem que ultrapassam o contêiner */
transition: transform 0.3s; /* Animação de escala ao passar o mouse */
}
.photo-link:hover {
transform: scale(1.15); /* Aumenta a imagem ao passar o mouse */
}
.photo {
width: 100%; /* Ocupa 100% da largura do link */
height: 100%; /* Ocupa 100% da altura do link */
object-fit: cover; /* Garante que a imagem cubra o espaço sem distorcer */
}
white-space: nowrap;
: Mantém as imagens em uma única linha.position: fixed;
: Fixa a galeria na tela, independente da rolagem da página.
transform: translateY(-50%);
: Centraliza verticalmente o contêiner.object-fit: cover;
: Garante que as imagens cubram o espaço sem distorcer.O JavaScript cria a rolagem infinita e replica os itens da galeria para criar um efeito contínuo.
function initInfiniteCarousel(selector, speed) {
const carousel = document.querySelector(selector);
if (!carousel) return;
const originalItems = Array.from(carousel.querySelectorAll('a'));
let totalScroll = 0;
let singleCycleWidth = 0;
// Clonar itens até preencher a tela
function fillCarousel() {
singleCycleWidth = originalItems.reduce((acc, item) => {
return acc + item.offsetWidth + parseFloat(getComputedStyle(item).marginRight);
}, 0);
const numClones = Math.ceil(window.innerWidth / singleCycleWidth) * 2;
for (let i = 0; i < numClones; i++) {
originalItems.forEach(item => {
const clone = item.cloneNode(true);
clone.classList.add('clone');
carousel.appendChild(clone);
});
}
}
// Animar a rolagem
function animateScroll() {
totalScroll += speed;
if (totalScroll >= singleCycleWidth) totalScroll = 0;
carousel.style.transform = `translateX(-${totalScroll}px)`;
requestAnimationFrame(animateScroll);
}
fillCarousel();
animateScroll();
}
initInfiniteCarousel('#photo-gallery', 1);
function debounce(func, wait) {
let timeout;
return (...args) => {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), wait);
};
}
fillCarousel()
:
singleCycleWidth
).animateScroll()
:
translateX
) continuamente.initInfiniteCarousel()
:
debounce()
:
resize
).transform: translateX
.Aqui está o código completo para você testar:
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Galeria com Rolagem Infinita</title>
<style>
#photo-gallery-container {
white-space: nowrap;
width: 100vw;
position: fixed;
top: 50%;
transform: translateY(-50%);
padding: 3vh 0;
}
#photo-gallery {
display: inline-block;
width: max-content;
}
.photo-link {
display: inline-block;
width: 33vh;
height: 33vh;
margin: 0 3vh;
border-radius: 5px;
box-shadow: 0 12.5px 12.5px rgba(0, 0, 0, .15);
overflow: hidden;
transition: transform 0.3s;
}
.photo-link:hover {
transform: scale(1.15);
}
.photo {
width: 100%;
height: 100%;
object-fit: cover;
}
</style>
</head>
<body>
<div id="photo-gallery-container">
<div id="photo-gallery">
<a class="photo-link" href="URL_IMAGEM_LARGA">
<img class="photo" src="URL_THUMBNAIL" alt="Descrição da Imagem">
</a>
<!-- Adicione mais imagens aqui -->
</div>
</div>
<script>
function initInfiniteCarousel(selector, speed) {
const carousel = document.querySelector(selector);
if (!carousel) return;
const originalItems = Array.from(carousel.querySelectorAll('a'));
let totalScroll = 0;
let singleCycleWidth = 0;
function fillCarousel() {
singleCycleWidth = originalItems.reduce((acc, item) => {
return acc + item.offsetWidth + parseFloat(getComputedStyle(item).marginRight);
}, 0);
const numClones = Math.ceil(window.innerWidth / singleCycleWidth) * 2;
for (let i = 0; i < numClones; i++) {
originalItems.forEach(item => {
const clone = item.cloneNode(true);
clone.classList.add('clone');
carousel.appendChild(clone);
});
}
}
function animateScroll() {
totalScroll += speed;
if (totalScroll >= singleCycleWidth) totalScroll = 0;
carousel.style.transform = `translateX(-${totalScroll}px)`;
requestAnimationFrame(animateScroll);
}
fillCarousel();
animateScroll();
}
initInfiniteCarousel('#photo-gallery', 1);
</script>
</body>
</html>