Capítulo 31
Vetores no canvas
2 min de leitura 383 palavras 1 gravura
Vetor = seta com comprimento e direção. Clique define a ponta; mostramos componentes e módulo.
Trabalhe sobre uma cópia da pasta inicio do exemplo correspondente. Leia, digite, mude uma coisa, preveja, recarregue e confira. A referência completa fica na raiz da pasta do exemplo, no pacote anexo.
O que você pratica
- |v| é?
- ox,oy origem?
- Componente y invertida na tela?

Clique o plano
Eixos e seta laranja. O texto mostra (vx, vy) e o módulo.
Erro comum: confundir y da tela (desce) com y matemático (sobe) — o exemplo já inverte na leitura.
Módulo
No início |v| está 0. Use hipotenusa.
Math.hypot(vx, vy)
Pare e experimente. Confira com um triângulo 3-4-5 aproximado.
Ponte
Vetores alimentam forças, raios e transforms.
Não publique exercícios com dados reais. Conteúdo fictício de Recife.
Como o exemplo desta etapa funciona
A referência desta etapa reúne app.js, index.html, styles.css. Abra o resultado pronto, localize o trecho que produz vetores no canvas e só então compare com inicio. Os dois diretórios são independentes: você pode errar, restaurar e repetir sem buscar arquivos de outro capítulo.
Leitura do resultado
Observe primeiro o que permanece parado e o que responde a uma ação. Depois altere um único número, cor, coordenada ou condição. Antes de recarregar, escreva o efeito esperado. Essa previsão separa uma mudança compreendida de uma tentativa ao acaso.
Diagnóstico guiado
Se a cena sumir, confira a primeira mensagem do Console e o caminho dos arquivos. Em SVG, revise viewBox, atributos e ordem das formas. Em p5.js, confirme a biblioteca local e se setup e draw foram escritos corretamente. Em Canvas ou WebGL, verifique o contexto e os limites numéricos antes de mudar outra coisa.
Critério de avanço
Avance quando conseguir descrever a cena, modificar um parâmetro com previsão e restaurar a referência sem copiar arquivos de uma etapa posterior.
Atividades
- hypot calcula?
- Sem clique a seta?
- Algebra visual ≠ prova formal?
Respostas comentadas
Só abra depois de tentar.
Atividade 1. Raiz de vx²+vy².
Atividade 2. Começa num tip inicial.
Atividade 3. Sim — intuição no canvas.
Exemplo deste capítulo: pacote de exemplos/31-vetores/.
O arquivo completo
Referência do exemplo 31-vetores, reproduzida aqui para que você possa conferir sem sair da página.
index.html
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Vetores — Laboratório da Luz</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<a class="skip" href="#conteudo">Ir ao conteúdo</a>
<header>
<p class="tag">Laboratório da Luz · Recife</p>
<h1>Vetores</h1>
</header>
<main id="conteudo">
<p class="dica">Vetores</p>
<div class="stage"><canvas id="g" width="480" height="300"></canvas></div>
<p id="out" class="dica"></p>
<div class="controles">
<label>Ângulo <input id="ang" type="range" min="0" max="6.28" step="0.01" value="0.4"></label>
<label>Escala <input id="esc" type="range" min="0.4" max="2" step="0.05" value="1.2"></label>
</div>
</main>
<footer>
<p>Conteúdo fictício para estudo local. Não publique dados reais.</p>
</footer>
<script src="app.js"></script>
</body>
</html>
app.js
const canvas=document.getElementById("g"); const ctx=canvas.getContext("2d");
let tip={x:320,y:120};
function drawArrow(x0,y0,x1,y1,color){
ctx.strokeStyle=color; ctx.fillStyle=color; ctx.lineWidth=3;
ctx.beginPath(); ctx.moveTo(x0,y0); ctx.lineTo(x1,y1); ctx.stroke();
const ang=Math.atan2(y1-y0,x1-x0);
ctx.beginPath(); ctx.moveTo(x1,y1);
ctx.lineTo(x1-14*Math.cos(ang-0.4), y1-14*Math.sin(ang-0.4));
ctx.lineTo(x1-14*Math.cos(ang+0.4), y1-14*Math.sin(ang+0.4));
ctx.closePath(); ctx.fill();
}
function render(){
ctx.fillStyle="#f4f0e8"; ctx.fillRect(0,0,canvas.width,canvas.height);
const ox=80, oy=220;
ctx.strokeStyle="#bbb"; ctx.lineWidth=1;
ctx.beginPath(); ctx.moveTo(40,oy); ctx.lineTo(440,oy); ctx.moveTo(ox,40); ctx.lineTo(ox,260); ctx.stroke();
drawArrow(ox,oy,tip.x,tip.y,"#c45c26");
const vx=tip.x-ox, vy=oy-tip.y;
document.getElementById("out").textContent=`vetor ≈ (${vx.toFixed(0)}, ${vy.toFixed(0)}) |v| ≈ ${Math.hypot(vx,vy).toFixed(1)}`;
}
canvas.addEventListener("click",(e)=>{
const r=canvas.getBoundingClientRect();
tip={x:e.clientX-r.left, y:e.clientY-r.top}; render();
});
render();