Explicativo envolvente
Uma história visual em um único take. Um único elemento herói (no estilo de referência, uma bola branca que começa como o botão de uma chave) viaja por uma cadeia de pequenas "estações" de interface, e cada estação reage a ele: ele rola ao longo de um controle deslizante e o empurra até 100, cai do final e quica em uma pilha de notificações que aparecem conforme ele passa, aterrissa em um teclado e quica de tecla em tecla digitando uma palavra, pressiona Enter e é lançado de volta ao ar. A câmera nunca corta: ela mantém o herói perto do centro e faz zoom para cada interação, e no clímax ela se afasta bastante para que o espectador veja todo o percurso de uma só vez, antes de mergulhar de volta para onde tudo começou.
Para um produto, as estações são as etapas do seu fluxo de trabalho, dispostas espacialmente em um canvas, e o herói é a coisa que se move através desse fluxo de trabalho. O plano aberto é o momento "agora você entende como funciona".
Você escreve como uma única página HTML que renderiza qualquer quadro a partir de um valor de tempo, depois renderiza para MP4 com desfoque de movimento e trilha sonora.
Etapa 1: Obter o briefing (uma mensagem, depois vá)
Pergunte tudo em uma mensagem, depois trabalhe sozinho. Apenas o produto é obrigatório; para qualquer coisa deixada em branco, decida você mesmo e diga o que escolheu.
- Produto: nome e o que ele faz em algumas frases. Uma URL do site é ainda melhor.
- A única coisa que o espectador deve lembrar (por exemplo, "digite uma ideia, obtenha um aplicativo ao vivo").
- Marca: cores, fontes, arquivo de logotipo, ou "use o site". Se nenhum, use a paleta padrão abaixo.
- Formato: 16:9 (1920×1080) ou 9:16 (1080×1920). Padrão 16:9.
- Duração: o padrão é fornecido abaixo para este estilo.
- Música: a própria faixa do usuário (um caminho de arquivo), ou deixe você sintetizar uma. Padrão: sintetizar.
- Direção (opcional): cenas desejadas, um slogan, uma chamada para ação, qualquer coisa para evitar.
Se eles forneceram uma URL, leia-a (busca na web) para obter a redação real do produto, recursos, cores e nomes de fontes antes de escrever qualquer coisa. Use as palavras reais deles para rótulos de interface e slogans.
Nunca invente fatos. Nenhum número de clientes, receita, classificações, depoimentos ou citações inventados. Números apenas se o usuário ou o site os declarar; caso contrário, use barras relativas, progresso e linhas de esqueleto de espaço reservado. Conteúdo de exemplo dentro da interface (um prompt, um nome de arquivo, um nome de projeto, preços em um recibo) é aceitável e deve ser plausível; afirmações sobre o próprio produto (estatísticas, contagens de usuários, classificações, ofertas como "grátis") não são. Chamadas para ação usam apenas uma URL ou oferta que o usuário ou o site forneceu; sem nenhuma, termine com o nome e slogan.
Logotipos. Use um logotipo apenas se o usuário fornecer o arquivo ou se for seu próprio produto e eles o solicitaram. Caso contrário, escreva o nome como texto na fonte da marca. Logotipos de terceiros (integrações) apenas se fornecidos; caso contrário, ladrilhos arredondados neutros com o nome.
Pergunte também (opcional): o fluxo de trabalho em 3 a 6 etapas (o que o usuário faz → o que o produto faz → o resultado). Se eles forneceram uma URL, derive-o do site.
Duração padrão para este estilo: 12 segundos, loop contínuo. Faixa de 10 a 30 (mais longo = mais estações, não estações mais lentas).
Etapa 2: Projetar o percurso, depois construir
1. Escolha o herói
O herói é um objeto único, simples e legível sobre o qual a história do produto gira, e ele nunca desaparece ou é substituído (pode mudar de forma por um momento, depois retornar): uma bola/botão (padrão, funciona para qualquer coisa), um cursor de texto ou cursor, um arquivo ou bloco de documento, um balão de mensagem, uma moeda ou pedido, um ponto de dados. Deve se encaixar naturalmente na interface de uma estação (um botão, um polegar, uma tecla, um alfinete).
2. Mapeie o fluxo de trabalho nas estações
Cada etapa se torna uma estação: um elemento de interface real e compacto com o qual o herói interage fisicamente, e que muda visivelmente por causa disso. Inspire-se nestas mecânicas:
| Mecânica | O herói... | A estação reage |
|---|---|---|
| Interruptor / botão | é o botão, ou o pressiona | liga, preenche com cor |
| Controle deslizante / progresso | rola ao longo dele como o polegar | o valor é contado em uma dica de ferramenta, a trilha preenche |
| Pilha de notificações | cai e quica em cada cartão | cada cartão aparece conforme é atingido, com uma mensagem que narra a história |
| Teclado / entrada | quica de tecla em tecla | cada tecla é pressionada, letras aparecem na entrada acima |
| Lista / tabela | desliza pelas linhas | cada linha é destacada, marcada ou classificada |
| Gráfico | torna-se o ponto principal da linha | a linha é desenhada atrás dele, as barras sobem conforme ele passa |
| Chat | entra como um balão | a resposta é digitada |
| Botão de implantar / enviar | é lançado por ele | um toast ou URL aparece |
Os rótulos e mensagens das estações contam a história em algumas palavras cada, com um pouco de humor (a referência usa Slider · Reached 100, Gravity · Something is falling, Messages · What now?, depois digita retry). Para um produto, escreva-os a partir do seu fluxo de trabalho real (por exemplo, uma ferramenta de codificação: prompt digitado → Agent · Writing 12 files → progresso → Preview · Ready → Deploy pressionado → Live at myapp.app).
3. Organize o mundo
Coloque as estações em um grande canvas (cerca de 3× o quadro), na ordem em que o herói as visita, de modo que o caminho ziguezagueie (direita ao longo do topo, desça pelo meio, atravesse a parte inferior). A gravidade deve fazer sentido: quedas vão para baixo, lançamentos vão para cima. Deixe o ponto de cada estação fixo durante todo o vídeo. O mundo é um canvas escuro com uma grade de pontos fraca que se move com a câmera (a grade é o que torna os movimentos da câmera legíveis).
4. Roteie o caminho do herói
A posição do herói é uma função pura do tempo, construída a partir de segmentos entre pontos de contato (cada contato está em uma batida):
- Rolando/deslizando ao longo de uma estação: posição por
easeou uma mola ao longo da trilha; o valor da estação é derivado da posição do herói. - Saltos e quedas entre contatos: uma parábola (
xlinear no tempo,y = y0 + v·t + ½·g·t², resolvavpara aterrissar no próximo contato na batida). Constante de gravidade em todo o vídeo. - Impactos: compressão no contato (escala 1.25 × 0.8 por cerca de 60 ms, retorno com mola), esticamento ao longo da velocidade durante o voo (até 1.15 × 0.9), mais um pequeno empurrão para baixo no que foi atingido.
- O lançamento: a última estação lança o herói para cima e de volta ao início em um longo arco, enquanto cada estação se reinicia ao contrário atrás dele (valores diminuem, notificações são descartadas, a entrada é limpa) para que o loop se feche. Execute o arco de lançamento em câmera lenta: primeiro escolha a altura do ápice que você deseja (o topo do percurso), que fixa o tempo de voo real sob sua gravidade, depois distorça o tempo para que o voo preencha a janela de revelação, mais lento no ápice (frequentemente 5–10× lá; por exemplo, velocidade
1 − 0.9·sin(πu)^0.6ao longo do arco). Agende os reinícios da estação durante a pausa de revelação, depois que o espectador viu o percurso completo, não no momento do lançamento. - Costura: coloque o ponto de loop na aterrissagem do herói na primeira estação.
seek(duration)deve parecer exatamente comoseek(0); a compressão de aterrissagem e o pressionamento de tecla também aparecem no tempo 0. Para som, renderize a trilha sonora dentro debuildAudioem seu próprioOfflineAudioContextligeiramente mais longo, dobre a cauda além dedurationde volta ao início e toque esse buffer no contexto fornecido. - Gravidade é lateral. Organize as estações para que as quedas façam sentido de lado: os cartões de notificação formam uma escada (cada cartão deslocado lateralmente em mais do que sua largura, para que o herói nunca passe por um), e o teclado é visto de frente com o herói pulando entre as teclas em pequenos arcos.
- O slot vazio: quando o herói fazia parte de uma estação (um botão, um polegar) e sai, a estação mantém um contorno fraco do slot que deixou, que se preenche novamente quando o herói retorna.
5. A câmera
A câmera é a parte difícil; acerte-a antes de polir qualquer outra coisa.
- Seguir: alvo da câmera = uma mistura da posição do herói (mais uma liderança de cerca de 0,15 s de sua velocidade) e uma âncora fixa para a estação atual, suavizada por uma mola criticamente amortecida (
w≈ 6) para que nunca trema nos impactos. Peso em direção à âncora cerca de 0,7 durante uma interação (a estação fica emoldurada), 0,15 durante quedas e saltos (o herói lidera), 0,85 na pausa de recompensa. A suavização precisa de histórico, então cozinhe-a no carregamento (veja o contrato da página), começando no tempo 0 a partir do enquadramento fixo da primeira estação e mesclando no seguimento durante os primeiros 0,8 s. O herói nunca sai da metade central do quadro. - Zoom: apertado durante cada interação: a estação preenche cerca da metade da largura do quadro e o herói tem 50–70 px na tela (em 1080p). Ligeiramente mais amplo durante quedas e saltos para que a próxima estação já esteja visível. Enquadre a estação, não o canvas vazio.
- A pausa de recompensa: antes do lançamento, permaneça no resultado final (o toast, a URL ao vivo) por 0,4–0,6 s, totalmente em quadro.
- A revelação: no lançamento, a câmera para de seguir e suaviza para um enquadramento fixo que encaixa todo o percurso (cerca de 0,3×), com uma ligeira inclinação 3D (
perspective+rotateXde 15–25°) para profundidade. Segure por cerca de 1 s enquanto o herói arqueia através dele; aumente a escala do herói e dê a ele um halo suave para que continue sendo a coisa mais brilhante e visível (pelo menos 24 px na tela). Em seguida, mergulhe para um enquadramento fixo da primeira estação, cronometrado para que o herói aterrisse lá enquanto a câmera chega, e mescle de volta ao seguimento. - Desfoque de movimento real: o herói e o mundo borram em movimentos rápidos; isso faz parte da aparência.
Aparência
- Paleta padrão (escura estilo iOS): canvas
#0C0C0E, grade de pontos#1E1E22, superfícies#1C1C1F/#2C2C2E, texto#F2F2F7, secundário#8E8E93, destaque#0A84FF, herói branco#FFFFFF. As cores da marca substituem o destaque; o herói continua sendo a coisa mais brilhante na tela. Uma variante clara (canvas#F2F2F4, herói = destaque) é aceitável se a marca for clara. - Interface de sistema de aparência real: interruptores, controles deslizantes com marcas de escala, cartões de notificação com um quadrado de ícone de aplicativo, um título, uma linha de corpo e
now; um teclado com teclas e uma tecla Enter. Fonte: tipo SF (Inter ou Geist). - Um cursor pode iniciar a cadeia (clica na primeira estação) e depois sai do caminho.
- Proibido: cortes, fade para preto, sobreposições de texto que explicam o que está acontecendo (os próprios rótulos das estações são o único texto), mais de um herói, estações que não reagem, física que parece flutuante.
Som
Um groove minimalista apertado a 110–120 BPM (kick suave, hi-hats secos, um baixo pluck abafado), e os contatos do herói são o instrumento principal: cada impacto toca uma nota tick ou marimba curta e afinada (o tom aumenta à medida que a história avança), pressionamentos de tecla clicam, movimentos de controle deslizante tocam ticks finos que aceleram com o valor, notificações ganham um pop suave, o lançamento ganha um whoosh para cima e o mergulho um whoosh para baixo. Cada som aterrissa exatamente em seu contato visual.
Como a página deve ser construída
Um único arquivo HTML auto-contido (CSS e JS inline; imagens apenas se o usuário as forneceu). Desenhe com DOM + transformações CSS, SVG ou um canvas em tela cheia, o que couber.
O contrato da página
window.VIDEO = {w, h, duration}ewindow.seek(t), uma função pura do tempo: ela define cada elemento para o tempot(segundos). Sem transições ou animações CSS, semsetTimeout, sem estado carregado do quadro anterior. Qualquer quadro deve renderizar corretamente por conta própria, em qualquer ordem. Medir layout dentro deseek(por exemplo,offsetLeft,measureText) é aceitável; é determinístico.- Aleatoriedade (grão, partículas, ruído em áudio) vem de um gerador com semente, nunca
Math.random. - Qualquer coisa que precise de um histórico (uma câmera que fica atrás de um objeto em movimento, uma simulação) é cozida uma vez no carregamento: percorra-a de 0 a
durationa 1/240 s, armazene os valores e façaseeklê-los de volta com interpolação. Para loops, inicie a simulação do estado em que o loop começa (veja a regra de costura do estilo). - Loops:
seek(t)usat % duration; efeitos que atravessam a costura (uma compressão de aterrissagem, uma cauda de som) são desenhados ou mixados em ambas as extremidades. - Com
?renderna URL: sem controles, sem escala de visualização; o palco é exatamentew × hno canto superior esquerdo. Sem ele: o palco é dimensionado com CSS para caber na janela e os controles de visualização são mostrados. - Fontes: incorpore-as. Baixe os arquivos woff2 (Fontes do Google ou da marca) e incorpore-os como
@font-facebase64, para que a renderização nunca retroceda silenciosamente. Para uma variação de peso, use uma fonte variável com um intervalo ([email protected]). - Camadas: dê aos planos de cena fundos transparentes e deixe um fundo de palco atrás deles fornecer a cor base, para que uma camada posterior nunca esconda uma anterior acidentalmente. Texto posicionado absolutamente recebe
white-space: nowrap. - Velocidade: grande
CSS filter: blur()e grandes gradientes desfocados são muito lentos para capturar. Desenhe gradientes e brilhos em um canvas uma vez no carregamento (ou como uma imagem) e mova isso.
Ajudantes: cole estes e construa tudo sobre eles
// resposta de degrau de mola amortecida 0 -> 1. w = velocidade (8 lento, 14 normal, 22 rápido), z = amortecimento (1 = sem ultrapassagem)
function spring(t, w = 14, z = 0.82) {
if (t <= 0) return 0;
if (z >= 1) return 1 - Math.exp(-w * t) * (1 + w * t);
const wd = w * Math.sqrt(1 - z * z);
return 1 - Math.exp(-z * w * t) * (Math.cos(wd * t) + (z * w / wd) * Math.sin(wd * t));
}
// um valor que muda de alvo muitas vezes, saltando para cada: track(start, [[time, value, w?, z?], ...]) -> f(t)
const track = (v0, keys) => t => { let v = v0, p = v0; for (const [tk, val, w, z] of keys) { v += (val - p) * spring(t - tk, w, z); p = val; } return v; };
// keyframes de easing precisos (melhor para movimentos de câmera): kf([[t0, v0], [t1, v1, easeFn?], ...]) -> f(t)
const kf = keys => t => { if (t <= keys[0][0]) return keys[0][1]; for (let i = 1; i < keys.length; i++) { const [a, va] = keys[i - 1], [b, vb, e = ease] = keys[i]; if (t <= b) return lerp(va, vb, e((t - a) / (b - a))); } return keys[keys.length - 1][1]; };
const clamp = (x, a = 0, b = 1) => Math.min(b, Math.max(a, x));
const ease = x => (x = clamp(x), x < .5 ? 4 * x * x * x : 1 - Math.pow(-2 * x + 2, 3) / 2); // easeInOutCubic
const lerp = (a, b, k) => a + (b - a) * k;
const seg = (t, a, b) => clamp((t - a) / (b - a)); // 0..1 progresso de t através de [a, b]
const rng = s => () => (s = (s +
…
[truncado para tradução]