MÓDULO 2.3

🎯 Coordenadas, seletores & bounding boxes

O detalhe que dá ar profissional: a bbox real vira a mira do cursor no canvas. Aqui você aprende o mapeamento de coordenadas, seletores robustos e a região de zoom/destaque.

7
Tópicos
~30
Minutos
Inter.
Nível
Precisão
Tipo
bbox → centro → cursor VIEWPORT 1280×800 {x,y,w,h} WIN_L + sx SHOT_T + sy CANVAS 1920×1080 ponta no centro a bbox real = mira do cursor, do destaque e do zoom
1

📍 Coordenadas viewport-relative

As bboxes vêm relativas ao viewport. No vídeo, viram coordenadas do canvas somando o offset da janela.

Conceito Principal

A captura roda num viewport fixo (ex.: 1280×800). Toda bbox vem nesse espaço. No canvas 1920×1080, o screenshot é desenhado dentro da janela e cada ponto é mapeado.

O mapeamento (ponto do shot → canvas)
// WIN_L = (1920 - VW) / 2 · SHOT_T = WIN_T + TITLE_H
canvasX = WIN_L + sx;
canvasY = SHOT_T + sy;
// o centro da bbox mapeada = para onde o cursor vai
📐
WIN_L
centraliza X
📏
SHOT_T
topo + título
🎯
centro
mira do cursor
2

📐 Capturar a bbox de cada alvo

Para cada passo com target, o capture.mjs lê o rect e arredonda para {x,y,w,h}.

Como o capture lê a bbox (trecho real)
const box = evalJSON(`(()=>{
const el = finder(target);
if(!el) return null;
const r = el.getBoundingClientRect();
return{x:Math.round(r.x), y:Math.round(r.y),
w:Math.round(r.width), h:Math.round(r.height)};
})()`);
⚠️
Alvo não encontrado = bbox null

Se o seletor não bate, o capture grava target: null e imprime ! alvo não encontrado no passo X. É o sinal claro de seletor errado — corrija antes de renderizar.

3

🧷 Seletores robustos

data-testid, role e texto visível sobrevivem à mudança de estado. Os refs @eN não.

✓ Seletores estáveis
  • [data-testid="gerar"]
  • role + nome acessível
  • Texto visível: {tag:"button",text:"Gerar"}
  • Atributos: input[name=height]
✗ Seletores frágeis
  • Refs @eN em telas que mudam
  • Classes geradas (CSS-in-JS) que mudam no build
  • nth-child posicional num layout dinâmico
  • Texto com acento/espaço que não bate exato
💡
Refs deslocam depois de "Gerar"

No POC, ao surgir o link "baixar PNG", todos os refs deslocaram. Por isso, em estado mutável, use CSS selectors ou {tag,text} — e re-snapshot quando o DOM muda muito.

4

🎯 O cursor mira o centro da box

O cursor é um SVG global com o hotspot na ponta. O tween compensa o offset para a ponta cair no centro.

Mecânica do cursor
1
Cursor é global, não por cena

Um único #cursor animado na timeline principal — desliza continuamente enquanto os screenshots trocam.

2
Hotspot na ponta

A ponta fica em ~(6,3) dentro do SVG de 42px. O tween usa x = alvoX - 6, y = alvoY - 3.

3
Clique = pulse + ripple

scale:.82 yoyo + um #ripple âmbar que expande no alvo no instante do clique.

💡
Easing curvo evita o robótico

O movimento usa duration:.7, ease:"power3.inOut", começando ~0,35s após a cena aparecer. O cursor chega ao alvo antes da explicação principal.

5

🔍 Região de zoom / destaque

A mesma bbox posiciona o anel de destaque e o push-in do zoom. Uma coordenada certa serve aos três efeitos.

📊 Três usos da mesma bbox
Cursor
A ponta cai no centro da box.
Destaque (.hlbox)
Anel âmbar com glow, ~6px de folga, posicionado na box.
Zoom
transformOrigin no centro do alvo.
Zoom no resultado (zoom:true)
// push-in cinematográfico no "tcharam"
gsap.to(img, { scale: 1.12,
transformOrigin: `${cx}px ${cy}px`, duration: narrDur });
💡
Destaque foca sem cobrir

O .hlbox é só box-shadow (anel + glow): entra com back.out e pulsa, focando o olhar no controle ativo sem tapar nada.

6

📜 Lidar com alvo fora da tela

Se o alvo está abaixo da dobra, role até ele antes de capturar e medir — e faça as duas coisas após o mesmo scroll.

⚠️
Scroll ainda é manual

O capture.mjs hoje não rola a página. Em telas longas, dirija o agent-browser na mão (scrollIntoView) antes do screenshot. Adicionar scroll/scrollTo é o item nº 1 do backlog.

💡
As bboxes são viewport-relative

Como a bbox é medida no viewport atual, ela bate com o screenshot daquele scroll — desde que o shot e a medição saiam depois do mesmo scrollIntoView.

7

✅ Conferir que pegou o elemento certo

Compare a bbox com o screenshot antes de renderizar. O capture imprime cada bbox no log para conferência rápida.

Log do capture.mjs (conferência)
> viewport 1280x800; abrindo http://localhost:8000/
[00] home: shot=00-home.png target=—
[01] prompt: shot=01-prompt.png target=129,252 482x96
[02] size: shot=02-size.png target=179,501 44x26
! alvo não encontrado no passo height
✓ Conferir na captura
  • Bbox cai sobre o controle visível no shot
  • Nenhum aviso de "alvo não encontrado"
  • w/h plausíveis (não 0×0 nem a tela inteira)
✗ Sinais de problema
  • target=— onde devia haver bbox
  • Bbox sobre o elemento errado
  • Coordenadas fora dos limites do shot

🎯 Resumo do módulo

  • bbox viewport-relative → canvasX = WIN_L + sx, canvasY = SHOT_T + sy
  • capture lê getBoundingClientRect; alvo sem match = bbox null + aviso
  • prefira data-testid / role / texto visível a refs @eN
  • cursor global com hotspot na ponta; clique = pulse + ripple
  • a mesma bbox serve cursor, destaque e zoom; confira no log antes de renderizar
Próximo módulo
2.4
⏳ Páginas longas, inputs React & multi-estado
Os casos difíceis das demos reais — e o que já funciona vs o que é roadmap.
Ir para o módulo 2.4 →