<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Controle Deslizante Antes e Depois</title>
<style>
/* Estilos básicos de reset */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* Container principal - isolando do contexto externo */
.comparison-container {
position: relative;
width: 100%;
max-width: 100%; /* Preenche completamente o contêiner pai */
margin: 0 auto;
overflow: hidden;
/* Garante isolamento */
box-sizing: border-box;
contain: layout style;
}
/* Imagem "depois" (fundo) */
.after-image {
position: relative;
width: 100%;
height: auto;
display: block;
}
.after-image img {
display: block;
width: 100%;
height: auto;
}
/* Imagem "antes" (frente com divisor) */
.before-container {
position: absolute;
top: 0;
left: 0;
width: 50%; /* Começa em 50% */
height: 100%;
overflow: hidden;
}
.before-container img {
display: block;
width: 200%; /* Importante: dobro da largura para compensar o container de 50% */
height: 100%;
object-fit: cover;
object-position: left;
}
/* Divisor/Handle */
.slider-divider {
position: absolute;
top: 0;
left: 50%; /* Começa em 50% */
width: 4px;
height: 100%;
background-color: white;
cursor: ew-resize;
z-index: 10;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.5);
}
/* Botão circular no divisor */
.slider-button {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 40px;
height: 40px;
border-radius: 50%;
background-color: white;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.5);
z-index: 11;
cursor: ew-resize;
display: flex;
justify-content: center;
align-items: center;
}
/* Setas no botão */
.slider-button::before,
.slider-button::after {
content: '';
position: absolute;
width: 10px;
height: 2px;
background-color: #333;
}
.slider-button::before {
transform: rotate(45deg);
left: 10px;
}
.slider-button::after {
transform: rotate(-45deg);
right: 10px;
}
/* Etiquetas "antes" e "depois" */
.label {
position: absolute;
bottom: 20px;
background-color: rgba(0, 0, 0, 0.7);
color: white;
padding: 5px 10px;
border-radius: 4px;
font-family: Arial, sans-serif;
font-size: 14px;
font-weight: bold;
z-index: 9;
}
.before-label {
left: 10px;
}
.after-label {
right: 10px;
}
/* Responsivo para dispositivos móveis */
@media (max-width: 767px) {
.slider-button {
width: 30px;
height: 30px;
}
.label {
font-size: 12px;
padding: 4px 8px;
}
}
</style>
</head>
<body>
<!-- Identificador único para este componente -->
<div id="before-after-systeme" class="comparison-container">
<!-- Imagem DEPOIS (fundo completo) -->
<div class="after-image">
<img src="https://via.placeholder.com/800x500/0288d1/FFFFFF?text=DEPOIS" alt="Depois">
</div>
<!-- Imagem ANTES (parte visível controlada pelo slider) -->
<div class="before-container">
<img src="https://via.placeholder.com/800x500/d32f2f/FFFFFF?text=ANTES" alt="Antes">
</div>
<!-- Divisor deslizante -->
<div class="slider-divider">
<div class="slider-button"></div>
</div>
<!-- Etiquetas -->
<div class="label before-label">ANTES</div>
<div class="label after-label">DEPOIS</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Função para inicializar o slider (podemos chamá-la múltiplas vezes)
function initBeforeAfterSlider(containerId) {
// Use um seletor específico ou um ID se fornecido
const container = containerId ? document.getElementById(containerId) : document.querySelector('.comparison-container');
if (!container) return; // Sai se o container não for encontrado
// Elementos DOM
const beforeContainer = container.querySelector('.before-container');
const sliderDivider = container.querySelector('.slider-divider');
const beforeImage = beforeContainer.querySelector('img');
// Função para atualizar a posição do slider
function updateSliderPosition(clientX) {
// Obtém as dimensões do container
const rect = container.getBoundingClientRect();
// Calcula a posição do mouse relativa ao container (em percentagem)
let position = (clientX - rect.left) / rect.width;
// Limita entre 0 e 1 (0% e 100%)
position = Math.max(0, Math.min(1, position));
// Converte para percentagem
const percentPosition = position * 100;
// Atualiza a posição do divisor e do container "antes"
sliderDivider.style.left = `${percentPosition}%`;
beforeContainer.style.width = `${percentPosition}%`;
// Ajusta a posição da imagem "antes" para compensar
const scale = 100 / percentPosition;
// Só ajusta se a largura for maior que zero (evita divisão por zero)
if (percentPosition > 0) {
beforeImage.style.width = `${scale * 100}%`;
beforeImage.style.objectPosition = 'left';
}
}
// Flag para verificar se está arrastando
let isDragging = false;
// ID para identificar exclusivamente este slider
const sliderId = containerId || 'slider-' + Math.random().toString(36).substring(2, 9);
// Função para iniciar o arrasto
const startDrag = function(e) {
e.preventDefault();
isDragging = sliderId; // Guarda o ID do slider atual
};
// Função para finalizar o arrasto
const endDrag = function() {
if (isDragging === sliderId) {
isDragging = false;
}
};
// Função para mover o slider durante o arrasto
const moveSlider = function(clientX) {
if (isDragging !== sliderId) return;
updateSliderPosition(clientX);
};
// Eventos de mouse
sliderDivider.addEventListener('mousedown', startDrag);
document.addEventListener('mousemove', function(e) {
moveSlider(e.clientX);
});
document.addEventListener('mouseup', endDrag);
// Eventos de toque (mobile)
sliderDivider.addEventListener('touchstart', function(e) {
startDrag(e);
});
document.addEventListener('touchmove', function(e) {
if (isDragging !== sliderId) return;
// Usa a posição do primeiro toque
moveSlider(e.touches[0].clientX);
});
document.addEventListener('touchend', endDrag);
document.addEventListener('touchcancel', endDrag);
// Clique direto no container
container.addEventListener('click', function(e) {
updateSliderPosition(e.clientX);
});
// Inicializa a posição para 50%
setTimeout(function() {
updateSliderPosition(container.getBoundingClientRect().left + container.offsetWidth / 2);
}, 200);
// Re-inicializa quando todos os recursos carregarem
window.addEventListener('load', function() {
updateSliderPosition(container.getBoundingClientRect().left + container.offsetWidth / 2);
});
// Ajusta quando a janela é redimensionada
window.addEventListener('resize', function() {
updateSliderPosition(container.getBoundingClientRect().left + container.offsetWidth / 2);
});
return {
update: function() {
updateSliderPosition(container.getBoundingClientRect().left + container.offsetWidth / 2);
}
};
}
// Inicializa todos os sliders na página
document.querySelectorAll('.comparison-container').forEach(function(container, index) {
container.id = container.id || 'comparison-' + index;
initBeforeAfterSlider(container.id);
});
// Re-inicializa após um pequeno atraso (para garantir que tudo foi renderizado)
setTimeout(function() {
document.querySelectorAll('.comparison-container').forEach(function(container) {
initBeforeAfterSlider(container.id);
});
}, 500);
});
</script>
</body>
</html>