# Sites com Rolagem Animada e Vídeo: Guia Completo de Criação

> Como criar um site premium com efeito de vídeo por rolagem (estilo Apple): segmentação de quadros em WebP, suavização LERP no Canvas, remapeamento de tempo de permanência e sistema editorial Precision Editorial.

Animated Video Scroll é uma técnica para criar sites cinematográficos de página única, onde a rolagem da página controla diretamente a reprodução do material em vídeo. Quando o usuário rola a página com a roda do mouse ou desliza na tela do smartphone, o vídeo muda suavemente quadro a quadro, sincronizando-se com o ritmo de leitura e o surgimento dos blocos de informação.

Esse efeito tornou-se a marca registrada das apresentações de produtos premium da Apple, Tesla, Porsche e dos principais estúdios de design do mundo.

> [!IMPORTANT]
> Esta técnica **não consiste em incorporar um player de vídeo comum** nem utiliza GIFs animados. Sua base reside em uma sequência quadro a quadro de imagens WebP leves, renderizadas por hardware em um elemento `<canvas>` via WebGL ou 2D Context, garantindo resposta imediata a cada pixel de scroll.

---

## 1. O que é um site de scroll com vídeo e suas vantagens

O vídeo tradicional no fundo de uma página tem dois defeitos substanciais: ele segue seu próprio ritmo, ignorando a atenção do leitor, e impõe alta carga à rede e à bateria do dispositivo móvel.

Um site controlado pelo scroll resolve esse problema:

- **Controle total da atenção:** O usuário escolhe seu próprio ritmo de visualização. Se ele parar em um parágrafo importante, o objeto no quadro congela no ângulo desejado.
- **Ausência de latências e buffering:** O arquivo de vídeo é previamente dividido em quadros estáticos WebP otimizados, portanto o navegador não precisa realizar a decodificação pesada de contêineres MP4 durante a rolagem rápida.
- **Sincronização narrativa:** Teses textuais, rótulos gráficos, métricas numéricas e especificações técnicas aparecem exatamente quando a câmera demonstra o detalhe correspondente do objeto.

### Correspondência com o tipo de projeto

| Tipo de produto | Por que o vídeo de scroll é adequado | Foco principal no quadro |
| :--- | :--- | :--- |
| **Automóveis e máquinas** | Destaca aerodinâmica, detalhes do chassi, materiais do interior | Movimento suave da câmera ao longo da carroceria, mudança de ângulos |
| **Eletrônicos premium** | Demonstra montagem de precisão, espessura do corpo, óptica | Desmontagem em componentes (exploded view), macrofotografia |
| **Arquitetura e imóveis** | Cria sensação espacial de volume e iluminação | Voo através da fachada até o interior |
| **Moda e joalheria** | Mostra textura do tecido, jogo de luz sobre o metal | Movimento delicado da luz ao redor da peça |

---

## 2. Arquitetura e estrutura de arquivos da skill

A skill é construída como um pipeline de engenharia modular. Cada componente é responsável por sua etapa isolada de trabalho:

```text
animated-sites-engine/
├── SKILL.md            # Instrução de roteiro: da análise do vídeo à implementação
├── visual-system.md    # Sistema de design Precision Editorial e regras de grade
├── extract_frames.py   # Utilitário Python para recorte e otimização WebP
└── evals.json          # Benchmark e critérios de verificação da qualidade do site
```

### 1. SKILL.md — instrução principal e algoritmo de roteiro
Descreve o ciclo de vida da criação da página: desde a análise técnica do material de origem usando `ffprobe` até a estruturação em capítulos semânticos, cálculo da duração do scroll e montagem da aplicação HTML/JS final.

### 2. visual-system.md — guia do sistema Precision Editorial
Estabelece regras estéticas rigorosas: rejeição a clichês baratos (brilhos neon infundados, painéis de vidro e fonte Playfair), paleta pronta "Trackline" para narrativas técnicas, 5 esquemas básicos de posicionamento de texto e pares tipográficos.

### 3. extract_frames.py — script de extração e compressão de quadros
Utilitário de console em Python. Lê automaticamente os metadados do vídeo via `ffprobe`, calcula a quantidade proporcional de quadros, recorta fluxos separados para Desktop e Mobile no formato WebP e gera o `manifest.json`.

### 4. evals.json — cenários de verificação de qualidade
Contém um caso de referência de teste (baseado em um vídeo da Porsche), que verifica a suavidade do LERP, o comportamento do canvas ao redimensionar a janela, a acessibilidade para teclado e o peso dos assets.

---

## 3. Mecânica de reprodução: Canvas, LERP e Dwell-Remap

No núcleo do funcionamento está o elemento `<canvas>`, fixado em toda a tela (`position: fixed`). A rolagem da página é convertida em progresso relativo de 0.0 a 1.0, que determina qual número exato de quadro deve ser exibido.

```text
Posição de rolagem (0.0 — 1.0)
          │
          ▼
┌───────────────────────┐
│     Dwell-Remap       │ ──► Desaceleração artificial nos centros dos capítulos
└──────────┬────────────┘
           │
           ▼
┌───────────────────────┐
│     Filtro LERP       │ ──► targetFrame alcança a rolagem com passos suaves
└──────────┬────────────┘
           │
           ▼
┌───────────────────────┐
│   HTML5 2D Canvas     │ ──► ctx.drawImage(loadedImages[frameIndex], ...)
└───────────────────────┘
```

### 1. Suavização via LERP (Interpolação Linear)

Se os quadros forem alternados estritamente a cada evento de scroll, a animação ficará irregular, especialmente em mouses com roda de rolagem discreta. 

Para obter fluidez cinematográfica, aplica-se a interpolação linear: o quadro sendo renderizado na tela (`currentFrame`) "alcança" suavemente o quadro alvo (`targetFrame`).

```javascript
let currentFrame = 0;
let targetFrame = 0;
const lerpFactor = 0.075; // Коефіцієнт згладжування (0.05 — 0.1)

function renderLoop() {
  // Наближаємо поточний кадр до цільового
  currentFrame += (targetFrame - currentFrame) * lerpFactor;
  
  const frameToDraw = Math.round(currentFrame);
  drawCanvasFrame(frameToDraw);

  requestAnimationFrame(renderLoop);
}

window.addEventListener("scroll", () => {
  const maxScroll = document.documentElement.scrollHeight - window.innerHeight;
  const progress = Math.min(Math.max(window.scrollY / maxScroll, 0), 1);
  targetFrame = progress * (totalFrames - 1);
}, { passive: true });
```

### 2. Desaceleração perto de cada capítulo (Dwell-Remap)

Para que o usuário tenha tempo de ler o título e o texto sem precisar parar a roda do mouse com precisão cirúrgica, aplica-se a técnica **Dwell-Remap**. Perto do centro de cada capítulo, a velocidade de rolagem dos quadros é artificialmente desacelerada, mantendo o movimento fluido nos intervalos entre eles.

```javascript
function applyDwellRemap(rawProgress, chapterPoints = [0.2, 0.5, 0.8], dwellWidth = 0.08, strength = 0.45) {
  let remapped = rawProgress;
  
  for (const center of chapterPoints) {
    const distance = Math.abs(rawProgress - center);
    if (distance < dwellWidth) {
      // Плавне згасання коефіцієнта швидкості по косинусоїді
      const factor = Math.cos((distance / dwellWidth) * (Math.PI / 2));
      const delta = (rawProgress - center) * (1 - factor * strength);
      remapped = center + delta;
      break;
    }
  }
  return Math.min(Math.max(remapped, 0), 1);
}
```

### 3. Carregamento progressivo de quadros

Para evitar flashes brancos e não esperar pelo carregamento de todo o pacote (100–150 quadros), aplica-se uma estratégia em duas etapas:

1. **Prioridade crítica:** Os primeiros 5 quadros e os quadros-chave dos capítulos principais são carregados instantaneamente.
2. **Fila em segundo plano:** Os demais quadros são baixados em pequenos lotes via `requestIdleCallback` ou fila de promessas. Se o quadro necessário ainda estiver em trânsito, o canvas exibe o quadro já carregado mais próximo.

---

## 4. Processo de desenvolvimento passo a passo: do vídeo ao código

Todo o processo de produção é dividido em sete etapas sequenciais:

### Etapa 1. Análise do vídeo com ffprobe

Antes da geração do código, os parâmetros técnicos do arquivo de origem são analisados:

```bash
ffprobe -v error -select_streams v:0 \
  -show_entries stream=width,height,duration,r_frame_rate,codec_name \
  -of default=noprint_wrappers=1 input.mp4
```

Cria-se uma folha de contato com 6 quadros de referência para avaliar o movimento da câmera, a posição do objeto e a disponibilidade de espaço negativo (negative space) para o texto.

### Etapa 2. Formulação do conceito de design

Formula-se uma tese clara:
- **Protagonista:** Quem ou o que está no centro das atenções.
- **Emoção-alvo:** Precisão técnica, luxo tranquilo, adrenalina, meditatividade.
- **Par tipográfico:** Título contrastante e acento monoespaçado de engenharia.
- **Recurso distintivo:** Telemetria, tracking variável, contador de microquadros.

### Etapa 3. Recorte e otimização dos quadros

A quantidade de quadros e a altura do scroll são ajustadas de acordo com a duração do vídeo:

| Duração do vídeo | Quantidade de quadros | Altura recomendada do scroll | Peso total alvo (WebP) |
| :--- | :--- | :--- | :--- |
| **0–5 segundos** | 60–80 quadros | 450–550vh | 4–7 MB |
| **5–15 segundos** | 90–130 quadros | 600–750vh | 8–12 MB |
| **15–30 segundos** | 130–180 quadros | 750–900vh | 10–15 MB |
| **30+ segundos** | 180–200 quadros | 900–1000vh | 12–16 MB |

Execução da extração via script Python:

```bash
python3 extract_frames.py \
  --input ./raw/porsche-gt3.mp4 \
  --output ./public/frames \
  --desktop-frames 120 \
  --mobile-frames 80 \
  --quality 62
```

### Etapa 4. Roteiro por capítulos

A página é dividida em 4–6 seções substantivas. Por exemplo:
1. **Capítulo 1: Introdução (0–15%)** — Nome do modelo, silhueta minimalista.
2. **Capítulo 2: Aerodinâmica (20–40%)** — Foco na geometria da asa traseira e dutos de ar.
3. **Capítulo 3: Powertrain (45–65%)** — Exibição do motor ou chassi com dados de telemetria.
4. **Capítulo 4: Final e ação (75–100%)** — Revelação completa do veículo e botão de test-drive.

### Etapa 5. Composição de camadas e layout ao redor do vídeo

O texto nunca deve cobrir os detalhes principais no quadro. Dependendo da trajetória de movimento do objeto, a posição dos blocos de texto muda suavemente da margem esquerda para a direita ou fica fixada no terço inferior da tela.

### Etapa 6. Montagem baseada no template inicial

Utiliza-se um esqueleto HTML5 robusto com lógica de pré-carregamento pronta e suporte a responsividade, ao qual são conectados tokens de cores individuais e o manifesto de quadros.

### Etapa 7. Verificação e crítica

> [!TIP]
> Sempre teste sites de scroll através de um servidor HTTP local (`python3 -m http.server`), e não abrindo o arquivo diretamente via `file:///`. As políticas CORS do navegador bloqueiam o carregamento de quadros WebP via `fetch()` ao abrir arquivos localmente.

---

## 5. Sistema visual: tipografia e paleta Trackline

O sistema **Precision Editorial** exige a rejeição de excessos decorativos em favor de um layout suíço equilibrado e da estética de instrumentos de controle.

### Combinações tipográficas

:::tabs
=== Archivo + IBM Plex Mono (Esportivo-técnico)
- **Títulos:** Archivo (Black, tracking apertado `-0.03em`)
- **Texto principal:** Archivo (Regular, 15px)
- **Legendas técnicas e telemetria:** IBM Plex Mono (Medium, 11px, Uppercase)
- **Ideal para:** Automóveis, aviação, engenharia pesada, mecanismos de relógios.
=== Roboto Flex + Roboto Mono (Engenharia moderna)
- **Títulos:** Roboto Flex (Variable width, Bold)
- **Texto principal:** Roboto (Regular, 16px)
- **Legendas técnicas:** Roboto Mono (12px, tabular-nums)
- **Ideal para:** Software corporativo, sistemas robotizados, equipamentos de laboratório.
=== Barlow Condensed + Manrope (Adrenalina cinematográfica)
- **Títulos:** Barlow Condensed (Extra Bold, Uppercase)
- **Texto principal:** Manrope (Medium, 15px)
- **Legendas técnicas:** Space Mono (11px)
- **Ideal para:** Esportes radicais, esports, moda, lançamentos de coleções.
=== Anybody + Source Code Pro (Acento industrial)
- **Títulos:** Anybody (Bold, Ultra-expanded)
- **Texto principal:** Inter (Regular, 15px)
- **Legendas técnicas:** Source Code Pro (11px)
- **Ideal para:** Escritórios de arquitetura, carros elétricos conceituais.
:::

### Paleta de cores "Trackline"

A paleta é construída sobre as cores de uma pista real: carbono fosco, alumínio frio e acentos de corrida discretos.

```css
:root {
  /* Базові відтінки */
  --color-carbon: #080a09;    /* Глибокий чорний вуглепластик (основний фон) */
  --color-paper: #f1f0e9;     /* Теплий матовий білий (основний текст) */
  --color-alloy: #a8aca8;     /* Металевий алюміній (другорядні підписи) */
  --color-track: #414541;     /* Графітовий асфальт (межі сітки, розділювачі) */
  
  /* Акцентні інженерні маркери */
  --color-petrol: #12372d;    /* Глибокий петролеум для підкладок карток */
  --color-signal: #d9381e;    /* Гоночний червоний (активні стани, алерти) */
  --color-heritage: #c5a059;  /* Золотистий колір для прогрес-бару та таймінгу */
}
```

> [!NOTE]
> As cores de sinal (`--color-signal` e `--color-heritage`) são usadas pontualmente — para marcar o capítulo ativo ou o indicador de posição, ocupando não mais que 3% da área da tela.

---

## 6. Composição de camadas, movimento e recursos distintivos

A página é construída a partir de três camadas independentes em termos de profundidade visual:

```text
┌─────────────────────────────────────────────────────────────┐
│ 3. Camada de interface: barra de progresso, indicador de    │
│    capítulo, botões de ação                                  │
├─────────────────────────────────────────────────────────────┤
│ 2. Camada de informações: título, descrição, bloco de       │
│    telemetria                                                │
├─────────────────────────────────────────────────────────────┤
│ 1. Camada Canvas: vídeo em tela cheia com renderização LERP │
└─────────────────────────────────────────────────────────────┘
```

### 5 variantes de layout de texto

| Esquema de layout | Posicionamento do conteúdo | Cenário ideal de uso |
| :--- | :--- | :--- |
| **Masthead Statement** | Título gigante centralizado em tela cheia | Primeira tela de abertura (introdução ao vídeo) |
| **Side Margin Annotation** | Coluna estreita (3–4 cols) à direita ou esquerda | Objeto move-se na parte oposta do quadro |
| **Split Statement** | Título à esquerda, descrição técnica à direita | Objeto permanece estabilizado estritamente no centro |
| **Telemetry Dock** | Barra horizontal inferior com dados instrumentais | Demonstração de dinâmica, velocidade, potência |
| **Final Callout** | Bloco focado com uma única ação principal (CTA) | Tela final após o término da sequência de vídeo |

### Princípios de animação de elementos DOM

Como o próprio vídeo no canvas já cria movimento intenso, a animação dos blocos de texto deve ser contida:
- **Surgimento via máscara:** O texto sobe de baixo através de um container com `overflow: hidden`.
- **Deslocamento:** Não mais que 16–24px no eixo Y.
- **Timings:** 600–800ms para entrada do capítulo com curva `cubic-bezier(0.16, 1, 0.3, 1)`.
- **Nenhum desfoque:** O filtro `filter: blur()` é estritamente proibido — ele causa recalculo de camadas do navegador e destrói os 60 FPS estáveis.

---

## 7. Antipadrões: rejeição aos clichês "luxuosos" obsoletos

A maioria dos landing pages de vídeo genéricos parece barata devido a um conjunto de clichês típicos de design. Eis o que deve ser totalmente evitado:

| Clichê obsoleto | Por que é ruim | Alternativa profissional |
| :--- | :--- | :--- |
| **Playfair Display + grotesco fino** | Template padrão de "pseudo-luxo" | Grotescos de precisão: Archivo, Roboto Flex, Manrope |
| **Glassmorphism (vidro fosco)** | Desfoca o vídeo de fundo, sobrecarrega a GPU | Texto limpo e contrastante no espaço livre do quadro |
| **Partículas flutuantes e poeira** | Distraindo a atenção do objeto real | Canvas limpo sem lixo decorativo artificial |
| **Gradientes neon violeta-azul** | Associados a landing pages de cripto genéricas | Cores naturais retiradas diretamente dos quadros do vídeo |
| **Cursor customizado com lag** | Cria sensação de lentidão e é incômodo de usar | Cursor nativo do sistema com hovers claros |

---

## 8. Performance, acessibilidade (A11y) e otimização mobile

Sites de scroll com grande quantidade de gráficos exigem disciplina técnica rigorosa:

### 1. Limitação do Device Pixel Ratio (DPR)
Smartphones modernos têm telas com DPR 3.0 ou 3.5. Renderizar o canvas nessa resolução aumenta a área de cálculo quase 10 vezes, superaquecendo imediatamente o processador.

```javascript
// Обмежуємо максимальний DPR значенням 2.0
const dpr = Math.min(window.devicePixelRatio || 1, 2);
canvas.width = window.innerWidth * dpr;
canvas.height = window.innerHeight * dpr;
ctx.scale(dpr, dpr);
```

### 2. Pausa de renderização para abas ocultas
Quando o usuário alterna para outra aba, a renderização deve parar instantaneamente:

```javascript
document.addEventListener("visibilitychange", () => {
  if (document.hidden) {
    cancelAnimationFrame(animationFrameId);
  } else {
    requestAnimationFrame(renderLoop);
  }
});
```

### 3. Modo de redução de movimento (prefers-reduced-motion)
Para pessoas com sistema vestibular sensível, a rolagem contínua quadro a quadro pode causar vertigem.

> [!IMPORTANT]
> Se a opção `prefers-reduced-motion: reduce` estiver ativada no sistema operacional, o site deve exibir um poster estático de alta qualidade ou uma galeria de slides simplificada, em vez da rolagem infinita de quadros.

```css
@media (prefers-reduced-motion: reduce) {
  .scroll-container {
    height: auto !important;
  }
  canvas {
    display: none !important;
  }
  .static-hero-fallback {
    display: block !important;
  }
}
```

---

## 9. Workshop prático: criação e execução do projeto

Vamos criar uma estrutura mínima funcional de um site de scroll.

### Etapa 1. Geração de quadros a partir do vídeo

Coloque o vídeo na pasta de trabalho e execute o recorte:

```bash
mkdir my-scroll-site && cd my-scroll-site
python3 extract_frames.py --input sample.mp4 --output ./frames --desktop-frames 120
```

O script criará o arquivo de manifesto `frames/manifest.json`:

```json
{
  "totalFrames": 120,
  "desktop": {
    "pathPattern": "frames/desktop/frame-%04d.webp",
    "width": 1920,
    "height": 1080,
    "totalWeightMb": 9.4
  },
  "recommendedScrollVh": 700
}
```

### Etapa 2. Estrutura de arquivos do projeto pronto

```text
my-scroll-site/
├── index.html              # Estrutura HTML e lógica do player de canvas
├── styles.css              # Tokens Precision Editorial e media queries
├── app.js                  # Ciclo LERP, remapeamento de dwell e tratamento de scroll
└── frames/
    ├── desktop/            # frame-0001.webp ... frame-0120.webp
    ├── mobile/             # frame-0001.webp ... frame-0080.webp
    └── manifest.json       # Metadados e dimensões
```

### Etapa 3. Execução do ambiente local

Para o correto pré-carregamento dos recursos, inicie um servidor HTTP local:

```bash
python3 -m http.server 3000
```

Abra no navegador o endereço `http://localhost:3000` e verifique a fluidez do movimento dos quadros e a correção da troca de capítulos.

---

## 10. Checklist final de prontidão do site de scroll

Antes do lançamento do projeto, verifique a conformidade com todos os critérios de engenharia e visuais:

### Métricas técnicas
- [x] O peso total dos quadros da versão desktop não excede 12 MB (mobile — até 5 MB).
- [x] Os primeiros 5 quadros possuem pré-carregamento prioritário (`preload`).
- [x] O coeficiente DPR é limitado ao valor `2` para prevenir superaquecimento de dispositivos móveis.
- [x] O loop `requestAnimationFrame` para ao mudar para outra aba do navegador.

### Experiência do usuário e acessibilidade
- [x] Implementada transição suave via LERP entre quadros sem solavancos bruscos.
- [x] Configurado Dwell-Remap para leitura confortável do texto perto de cada capítulo.
- [x] Suporte ao modo `prefers-reduced-motion` com poster estático.
- [x] Todos os elementos clicáveis têm tamanho mínimo de 44×44px.

### Design e estética
- [x] Utilizado um par tipográfico de engenharia claro, sem clichês de pseudo-luxo.
- [x] O texto não cobre o objeto principal em movimento no quadro.
- [x] As cores da interface são derivadas diretamente do material do vídeo.
- [x] A página termina com uma chamada para ação (CTA) clara e inequívoca.