Communitygithub.com

MaybeIceloveU2/scroll-zoom-reveal

Efeitos cinematográficos para sites: zoom com scroll que revela uma cena em tela cheia, efeito de cursor com campo de pixels OLED e mais.

O que é scroll-zoom-reveal?

Este skill oferece dois efeitos visuais impressionantes e sem dependências para sites de landing page, portfólios, produtos ou jogos. O primeiro é um efeito de 'scroll zoom reveal': uma cena (render, screenshot de jogo, vídeo) ocupa a tela inteira enquanto o usuário rola, e então a 'câmera' se afasta para revelar a cena rodando dentro de um laptop, tablet ou monitor. Abaixo, um texto aparece com fade-in e uma galeria com abas e crossfade é exibida. O segundo efeito é um 'campo de pixels OLED' interativo: um fundo composto por minúsculos subpixels RGB que reagem ao cursor do mouse, criando um rastro brilhante, fluido e mutável (um clique gera uma ondulação). Ambos os efeitos utilizam Vanilla JS, CSS e WebGL, sem frameworks ou dependências externas. Funcionam em HTML puro, React, Next.js, Vue e Astro. O skill inclui todos os arquivos necessários (CSS, JS, HTML de demonstração) e instruções detalhadas de como integrar, personalizar temas e trocar a mídia da cena.

Funciona com~Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/MaybeIceloveU2/scroll-zoom-reveal/tree/HEAD

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Prévia

Do README da skill

scroll-zoom-reveal preview

Documentação

Scroll Zoom Reveal

Um efeito de scroll pronto para uso, sem dependências:

  1. Cena fixa em tela cheia: um título sobre uma cena escurecida que preenche a viewport.
  2. Movimento de câmera + afastamento: a cena se estabiliza levemente, então a 'câmera' se afasta. A cena revela estar em um monitor de laptop (a moldura e a base aparecem).
  3. Revelação do aplicativo: painéis do editor (barra de ferramentas, organizador, propriedades, timeline) deslizam e a cena se encolhe dentro do painel da viewport.
  4. Texto com fade-in abaixo (data-zr-fade), depois uma galeria com abas e crossfade com um seletor deslizante.

Todos os arquivos prontos estão em assets/ ao lado deste arquivo:

ArquivoFinalidade
assets/zoom-reveal.cssTodos os estilos (tokens de tema em .zr)
assets/zoom-reveal.jsComponente + fades + galeria. Expõe window.ZoomReveal, inicializa automaticamente [data-zoom-reveal] / [data-zr-gallery] / [data-zr-fade]
assets/oled-field.jsOpcional. Campo de subpixels OLED reativo ao cursor (window.OledField, inicializa automaticamente [data-zr-oled]). Os estilos estão em zoom-reveal.css
assets/placeholder-scenes.jsOpcional. Pinta proceduralmente arte de placeholder original no canvas (ZRScenes.drawCity, ZRScenes.drawCanyon) até que imagens reais existam
assets/demo.htmlPágina funcional completa. Comece por esta marcação.

Como usar em um site

  1. Copie os assets para o projeto (ex.: public/zoom-reveal/ ou src/vendor/zoom-reveal/). Copie placeholder-scenes.js apenas se ainda não houver artwork real.
  2. Leia assets/demo.html e copie o bloco <section class="zr" data-zoom-reveal>…</section> (mais o bloco da galeria, se desejado). Mantenha a estrutura de classes exatamente:
section.zr[data-zoom-reveal]          ← o comprimento do scroll vive aqui (--zr-length)
  .zr-sticky                          ← palco fixo de 100vh
    .zr-glow                          (brilho ambiente opcional)
    .zr-device                        ← redimensionado pelo JS
      .zr-lid > .zr-display
        .zr-viewport > .zr-media > img | video | canvas   ← SUA CENA
        .zr-chrome > .zr-panel.zr-toolbar / .zr-left / .zr-right / .zr-bottom  (UI do app opcional)
      .zr-base                        (base do laptop; remova para monitor/tablet)
    .zr-scrim + header.zr-intro       ← título sobre a cena, desvanece primeiro
    .zr-caption                       ← legenda pequena, aparece no final
  1. Carregue zoom-reveal.css no <head> e zoom-reveal.js no final do <body>.
  2. Troque a mídia: substitua o canvas de demonstração pela cena real:
    • Imagem: <img src="cena.avif" alt="" decoding="async">. Exporte com pelo menos o tamanho da viewport × DPR (2560–3200px de largura). O efeito começa com a imagem preenchendo toda a tela.
    • Vídeo com scrub no scroll: <video data-zr-scrub muted playsinline preload="auto" src="cena.mp4"></video>. O JS mapeia o progresso do scroll para currentTime. Codifique com cada quadro como keyframe para que a busca seja suave: ffmpeg -i in.mov -c:v libx264 -g 1 -crf 22 -an -movflags +faststart cena.mp4.
  3. Reescreva todo o texto (eyebrow, título, legenda, rótulos dos painéis, nome do arquivo, rótulos da galeria) para se adequar ao site. Nunca publique o texto fictício "Orbit / Forge" da demonstração.
  4. Tema com os tokens em .zr: --zr-bg, --zr-fg, --zr-muted, --zr-accent, --zr-length (distância do scroll, padrão 360vh).

Opções

Passe JSON no atributo, ex.: data-zoom-reveal='{"maxWidth":1000,"viewport":{"top":0,"right":0,"bottom":0,"left":0}}', ou construa em JS: new ZoomReveal(el, options).

OpçãoPadrãoSignificado
maxWidth1180Largura máxima final da tela (px)
widthRatio / heightRatio0.82 / 0.64Tamanho final da tela em relação à viewport
aspect0.625Altura ÷ largura da tela (16:10). Telefone ≈ 2.16, ultrawide ≈ 0.42
overscan1.04Quão além da viewport a tela começa (esconde a moldura)
dolly1.14Zoom interno inicial da mídia; estabiliza em 1
lift0.035Quanto o dispositivo sobe no final
timelineveja JSJanelas de progresso [início,fim] para intro, dolly, zoom, chrome, caption
viewport{top:6.5,right:21,bottom:22,left:15}Insetos finais (% da tela) do painel da cena dentro da UI do app. Defina todos como 0 e remova .zr-chrome para um puro "cena → tela do dispositivo" sem UI do app
onProgress—fn(p) callback com progresso 0..1

Eventos: a seção dispara zr:resize com {width, height, finalWidth}, o tamanho em pixels no qual a mídia é disposta. Use para dimensionar canvas ou escolher uma fonte de imagem.

React / Next.js

Importe o CSS globalmente. Remova data-zoom-reveal da marcação e construa manualmente para vinculá-lo ao ciclo de vida do componente ('use client' no Next):

useEffect(() => {
  import('./zoom-reveal/zoom-reveal.js').then(() => {  // registra window.ZoomReveal
    const zr = new window.ZoomReveal(ref.current, { maxWidth: 1100 });
    const gal = galRef.current && new window.ZoomReveal.Gallery(galRef.current);
    window.ZoomReveal.initFades();
    cleanup = () => zr.destroy();
  });
  let cleanup = () => {};
  return () => cleanup();
}, []);

Converta class → className e style="--v:78%" → style={{'--v':'78%'}}.

Campo de pixels OLED (efeito de cursor)

Um fundo em tela cheia de minúsculas barras de subpixels RGB, levemente iluminadas. Mover o cursor agita uma pequena simulação de fluido. Os pixels ao longo do caminho acendem, crescem e mudam de cor de violeta para ciano para lima para branco quente, então o brilho deriva na direção do cursor, se espalha e desvanece. Um clique ou toque envia uma ondulação. Quando o cursor está ocioso (e em telas sensíveis ao toque), um "cursor fantasma" lento o mantém ativo. A renderização é um shader de fragmento WebGL1, a simulação é uma pequena grade de CPU, e só é executada enquanto a seção está na tela. Sem WebGL, cai para um spotlight CSS.

Use atrás de um bloco de especificações/estatísticas, um hero ou uma faixa CTA. Qualquer elemento funciona: adicione class="zr-oled" data-zr-oled, coloque conteúdo dentro, carregue zoom-reveal.css + oled-field.js. O componente insere o canvas automaticamente. Veja o bloco "OLED PIXEL FIELD" em assets/demo.html.

<section class="zr-oled" data-zr-oled='{"cell":7}'>
  <div class="seu-conteudo">…estatísticas / título…</div>
</section>
<script src="oled-field.js"></script>
OpçãoPadrãoSignificado
cell6px CSS por pixel (3 barras de subpixels). 5–9 parece bom; use maior no mobile para desempenho
radius2.4Raio do pincel em células
strength0.55Quanta luz o cursor adiciona. Os padrões são deliberadamente sutis; 1 é ousado
decay0.94Desvanecimento por quadro; maior = rastros mais longos (0.92 curto … 0.97 longo)
flow0.55Quão longe o brilho deriva ao longo da direção do cursor
diffusion0.35Quão rápido o brilho se espalha
base0.09Brilho da grade não iluminada
palette['#5a3cff','#1fd6ff','#b6ff4a','#fff4d8']4 cores, baixa → alta energia. Combine com a marca, ex.: quente ['#ff3c5a','#ff9a1f','#ffe14a','#fff8e8']
ambient / ripplestrueCursor fantasma enquanto ocioso / ondulação ao clicar

Para um visual mais ousado (mais próximo de um efeito de destaque), use {"radius":3.2,"strength":1,"decay":0.962,"flow":0.9}. Mantenha os padrões sutis atrás de seções com muito texto.

API: const f = new OledField(el, opts), f.pulse(clientX, clientY) (dispara uma ondulação a partir do código), f.destroy() (chame na limpeza do React). Dê ao texto sobre o campo uma text-shadow escura suave para que permaneça legível sobre rastros brilhantes.

Armadilhas (verifique estas antes de finalizar)

  • Sticky quebra se qualquer ancestral de .zr tiver overflow: hidden/auto/clip ou um transform. Use overflow-x: clip no body se o overflow horizontal precisar ser ocultado.
  • Não envolva .zr em bibliotecas de scroll suave que transformam a página (Locomotive v4 etc.). Lenis está ok.
  • O dispositivo é disposto grande e redimensionado para baixo, então a mídia permanece nítida. Não coloque tamanhos fixos em px dentro de .zr-device: use em (1em = 1% da largura do display).
  • Movimento reduzido é tratado: a seção desafixa e mostra o estado final; a galeria para de reproduzir automaticamente; o campo OLED continua reagindo ao cursor, mas remove o cursor fantasma e as ondulações.
  • Animações pausam em abas em segundo plano (requestAnimationFrame para). Ao testar o campo OLED em um painel do navegador, mantenha a página visível ou parecerá congelada.
  • Abaixo de ~500px de largura, o laptop é pequeno. Considere {"widthRatio":0.92} ou aspect correspondente a um quadro de telefone no mobile.
  • Teste rolando lentamente de cima para baixo no navegador nas larguras desktop e mobile. Confirme que o título desvanece antes do afastamento começar, nenhuma moldura aparece no início, e a legenda não sobrepõe a base.
  • Use artwork e texto originais ou licenciados. Isso recria a técnica de movimento; não copie imagens, renders de produto ou texto de outra marca.

Habilidades Relacionadas