Este site

Este site também é meu, do motor ao design.

O motor de scroll, as páginas e o design saíram do mesmo método que uso nos sistemas: levantar o que precisa acontecer, desenhar e construir. Esta é a única página técnica do site, de propósito. Abra o devtools: cada afirmação abaixo dá para conferir.

O que é.

Vanilla JS, zero dependência, 30 KB. O scroll da página vira currentTime de vídeo: a câmera se move de verdade, o scroll só controla o tempo.

  const UNLOAD_VH = LOAD_VH * 2;
  function unloadClip(s) {
    if (!s.video) return;
    const v = s.video;
    try { v.pause(); } catch (e) {}
    const src = v.src;
    v.removeAttribute('src'); try { v.load(); } catch (e) {}
    if (src && src.indexOf('blob:') === 0) { try { URL.revokeObjectURL(src); } catch (e) {} }
    if (v.parentNode) v.parentNode.removeChild(v);
    s.el.classList.remove('has-clip');
    s.video = null; s.hasClip = false; s.ready = false; s.loading = false;
  }

trecho literal de scrub-engine.js, o descarregamento de blob que eu acrescentei ao motor original

Cinco problemas que deram trabalho.

Todos reais, tirados do fonte.

Scroll não é tempo

Mapear scroll em tempo de vídeo linearmente deixa a cena passando rápido demais justo onde a copy está no pico. O linger remapeia o tempo por cena com uma função monótona, a câmera assenta no meio e acelera nas bordas, sem tocar os frames de emenda (f(0)=0, f(1)=1).

Host sem byte-range congela o vídeo

Sem Range HTTP, video.seekable fica em [0,0] e todo seek cai no frame 0. O motor baixa cada clipe como Blob e toca de um object URL, sempre seekável, e só dispara o fetch perto da cena: 1,6 viewport nas páginas de projeto, 0,6 na trilha, onde as cenas são curtas. Medido no meio da trilha: no máximo quatro clipes vivos, e zero depois que ela termina.

iOS pinta a tela em branco

Vídeo mudo que nunca deu play não pinta frame após seek no Safari. O still fica como poster até o evento seeked, não o loadedmetadata, e cada vídeo é "aquecido" (play→pause) no primeiro toque.

Nove cenas seguram 30 MB

O motor original nunca chamava revokeObjectURL. Acrescentei o descarregamento: a cena que sai do dobro da janela de carga (1,2 viewport na trilha) devolve o blob e volta ao still, a distância dupla evita carregar e descarregar na borda. Rolar de volta recarrega.

Reduced-motion custa zero byte

Sob prefers-reduced-motion o motor não baixa nenhum vídeo: as 27 stills fazem crossfade entre si. Acessibilidade e desempenho pela mesma porta.

Emenda entre cenas

Dentro de cada projeto, a cena B começa no último frame real da cena A (frame-lock, medido em 17-21 dB, composição idêntica, só grão). Entre projetos diferentes não há clipe de ligação: a trilha usa crossfade direto e assume isso, em vez de fingir um voo contínuo que não existe.

Os números.

Contados no disco a cada build, não digitados.

18clipes de vídeo, 63,7 MB no acervo
3,3 MBpor cena da trilha, em média, a rajada de entrada (duas primeiras cenas) é 4,8 MB
54imagens webp somando 1,3 MB, imagem aqui é de graça
30 KBde motor, sem framework, sem bundler

Abra o devtools e confira.

Network: um fetch por cena, tipo blob. Elements: o vídeo some quando a cena sai do dobro da janela de carga. Performance: nenhum framework.

Contato

Quer ver isso de perto?

Diegorafacarvalho@gmail.com +55 47 98801-8335

Santa Catarina, Brasil, remoto. Costumo responder no mesmo dia.

Sem formulário

  • Recrutador não preenche formulário, copia o e-mail. Ele está aí em cima.
  • A versão rápida é uma página só, imprime em A4 e serve para encaminhar ao tech lead.
  • Qualquer sistema daqui eu mostro em chamada: o processo que mudou, os módulos, as telas e como foi construído.
  • Os sistemas foram desenvolvidos para empresas e o código não é público. Este site também é meu, do motor de scroll ao design: veja como funciona.