/* global React, Reveal */ const { useRef, useEffect } = React; const PAIRS = [ { proc: "Botox", image: "assets/ba-botox-1.jpg" }, { proc: "Preenchimento Labial", image: "assets/ba-labial-1.jpg" }, { proc: "Botox", image: "assets/ba-botox-2.jpg" }, { proc: "Preenchimento Labial", image: "assets/ba-labial-2.jpg" }, { proc: "Botox", image: "assets/ba-botox-3.jpg" }, ]; function BeforeAfter() { const wrapRef = useRef(null); const isDraggingRef = useRef(false); const isHoveringRef = useRef(false); const dragState = useRef({ startX: 0, scrollLeft: 0 }); // useEffect 1: roda APENAS UMA VEZ na montagem // - Posiciona scroll no meio (para permitir rolar nos dois sentidos) // - Configura loop infinito // - Configura auto-scroll useEffect(() => { const wrap = wrapRef.current; if (!wrap) return; let rafId; let lastTime = performance.now(); const pixelsPerSecond = 25; // Posicionar no meio (uma única vez) const initPos = () => { const oneSetWidth = wrap.scrollWidth / 3; wrap.scrollLeft = oneSetWidth; }; setTimeout(initPos, 100); // Loop infinito (quando chega no fim, salta invisivelmente para o início) const handleScroll = () => { const oneSetWidth = wrap.scrollWidth / 3; if (wrap.scrollLeft >= oneSetWidth * 2) { wrap.scrollLeft -= oneSetWidth; } else if (wrap.scrollLeft <= 0) { wrap.scrollLeft += oneSetWidth; } }; const handleMouseEnter = () => { isHoveringRef.current = true; }; const handleMouseLeaveLocal = () => { isHoveringRef.current = false; }; // Auto-scroll (lê os refs em tempo real - não recria o loop) const animate = (now) => { const delta = (now - lastTime) / 1000; lastTime = now; if (!isDraggingRef.current && !isHoveringRef.current) { wrap.scrollLeft += pixelsPerSecond * delta; } rafId = requestAnimationFrame(animate); }; wrap.addEventListener('scroll', handleScroll, { passive: true }); wrap.addEventListener('mouseenter', handleMouseEnter); wrap.addEventListener('mouseleave', handleMouseLeaveLocal); rafId = requestAnimationFrame(animate); return () => { cancelAnimationFrame(rafId); wrap.removeEventListener('scroll', handleScroll); wrap.removeEventListener('mouseenter', handleMouseEnter); wrap.removeEventListener('mouseleave', handleMouseLeaveLocal); }; }, []); // <-- array vazio: roda apenas na montagem // Drag handlers - usam refs em vez de state para evitar re-render const handleMouseDown = (e) => { isDraggingRef.current = true; wrapRef.current.classList.add('dragging'); dragState.current.startX = e.pageX - wrapRef.current.offsetLeft; dragState.current.scrollLeft = wrapRef.current.scrollLeft; }; const stopDragging = () => { isDraggingRef.current = false; if (wrapRef.current) wrapRef.current.classList.remove('dragging'); }; const handleMouseMove = (e) => { if (!isDraggingRef.current) return; e.preventDefault(); const x = e.pageX - wrapRef.current.offsetLeft; const walk = (x - dragState.current.startX) * 1.5; wrapRef.current.scrollLeft = dragState.current.scrollLeft - walk; }; // Triplica para loop infinito const items = [...PAIRS, ...PAIRS, ...PAIRS]; return (
— Antes & Depois —

Resultados que falam por si.

Cada transformação respeita a beleza natural — discreta, equilibrada e duradoura.

{items.map((p, i) => (
{p.proc} Antes Depois
{p.proc}
))}
); } window.BeforeAfter = BeforeAfter;