Coordenadas do Canvas
Nesta página, você encontra informações úteis sobre as coordenadas do canvas HTML, além de exemplos de código para desenhar um círculo e uma linha.
O canvas HTML é um elemento poderoso do HTML5 que permite criar e manipular gráficos em uma página web usando JavaScript. O elemento <canvas> fornece uma superfície de desenho bidimensional que pode ser imaginada como uma grade ou sistema de coordenadas.
Esta página explica como funciona o sistema de coordenadas do canvas, como ler e definir pontos nele, e como mover, dimensionar e rotacionar esse sistema com transformações. Se você ainda não conhece o elemento em si, comece pela introdução ao Canvas.
O Sistema de Coordenadas
A grade do canvas começa no canto superior esquerdo, que tem as coordenadas (0, 0). A partir daí:
- O eixo x aumenta para a direita.
- O eixo y aumenta para baixo (o oposto do que a maioria das pessoas aprendeu nas aulas de matemática, onde y cresce para cima).
Cada ponto no canvas é um par (x, y) medido em pixels a partir dessa origem no canto superior esquerdo.
(0,0)──────── x increases → ────────►
│ ┌───────────────────────────────┐
│ │ (0,0) (300,0) │
y │ │
│ │ (150,75) │
▼ │ │
│ (0,150) (300,150)│
└───────────────────────────────┘Para um canvas de 300 × 150, (0, 0) é o canto superior esquerdo, (300, 0) é o canto superior direito, (0, 150) é o canto inferior esquerdo e (150, 75) é o centro exato.
O contexto de renderização 2D
Você nunca desenha diretamente no elemento <canvas>. Em vez disso, você solicita um contexto de renderização — um objeto que expõe os métodos de desenho (moveTo, lineTo, arc, fillRect, entre outros):
const canvas = document.getElementById("myCanvas");
const ctx = canvas.getContext("2d");getContext("2d") retorna o contexto 2D usado em todos os exemplos abaixo. (Existem outros tipos de contexto, como "webgl" para 3D, mas "2d" é o usado para desenho no canvas.) Cada coordenada passada a um método do contexto é interpretada na grade descrita acima.
Desenhando uma Linha
Os métodos abaixo são usados para desenhar uma linha reta em um canvas:
moveTo(x,y), que especifica o ponto de início da linhalineTo(x,y), que especifica o ponto final da linha
Use um dos métodos de "tinta" para desenhar a linha, por exemplo, stroke().
Exemplo do elemento HTML <canvas> para desenhar uma linha:
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<canvas width="300" height="150" style="border:1px solid #cccccc;" id="canvasExample">
Your browser does not support the HTML5 canvas tag.
</canvas>
<script>
const c = document.getElementById("canvasExample");
const ctx = c.getContext("2d");
// Starting point (0,0) is the top-left corner
ctx.moveTo(0, 0);
// Ending point (300,150) matches the canvas width and height
ctx.lineTo(300, 150);
ctx.strokeStyle = '#359900';
ctx.stroke();
</script>
</body>
</html>No exemplo acima, a linha é desenhada na diagonal de (0, 0) (canto superior esquerdo) até (300, 150) (canto inferior direito). Observe que essa única linha não precisou de beginPath(): quando nada mais foi desenhado ainda, moveTo/lineTo iniciam um novo caminho automaticamente. O círculo abaixo usa beginPath() porque é uma forma separada — veja a explicação nessa seção.
Para mais formas e preenchimentos construídos no mesmo sistema de coordenadas, consulte Desenho no Canvas.
Desenhando um Círculo
Os métodos abaixo são usados para desenhar um círculo em um canvas:
beginPath(), que inicia um novo caminho para que o círculo não se conecte a nada desenhado anteriormente.arc(x, y, r, startAngle, endAngle), que adiciona um arco (uma porção de círculo) ao caminho atual.
Os parâmetros de arc()
| Parâmetro | Significado |
|---|---|
x, y | As coordenadas do centro do círculo. |
r | O raio, em pixels. |
startAngle | Onde o arco começa, em radianos. |
endAngle | Onde o arco termina, em radianos. |
Os ângulos são medidos em radianos, não em graus, e 0 aponta para a direita (o eixo x positivo), girando no sentido horário. Uma volta completa é 2 * Math.PI radianos (360°), portanto um círculo completo vai de 0 a 2 * Math.PI.
Para converter graus em radianos, multiplique por Math.PI / 180:
const radians = degrees * (Math.PI / 180);Arcos parciais
Não é necessário desenhar um círculo completo. Use um ângulo final menor para desenhar apenas parte de um. Por exemplo, um arco de 0 a Math.PI (meia volta completa) desenha a metade inferior de um círculo, pois y aumenta para baixo:
// A half-circle (bottom half) centered at (100, 75) with radius 50
ctx.beginPath();
ctx.arc(100, 75, 50, 0, Math.PI);
ctx.stroke();Exemplo do elemento HTML <canvas> para desenhar um círculo:
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<canvas id="exampleCanvas" width="250" height="200" style="border:1px solid #dddddd;">
The canvas tag is not supported by your browser.
</canvas>
<script>
const canvas = document.getElementById("exampleCanvas");
const ctx = canvas.getContext("2d");
ctx.beginPath();
// Center at (125, 95), radius 70. 125 is half of the 250 width.
ctx.arc(125, 95, 70, 0, 2 * Math.PI);
ctx.strokeStyle = '#1c87c9';
ctx.closePath();
ctx.stroke();
</script>
</body>
</html>No exemplo acima, o círculo está centralizado em (125, 95) com um raio de 70.
beginPath() e closePath()
Esses dois métodos frequentemente causam confusão:
beginPath()descarta qualquer caminho que estava sendo construído e inicia um completamente novo. Chame-o antes de cada forma independente — caso contrário, a nova forma é unida à anterior, e um únicostroke()/fill()estiliza todas juntas.closePath()desenha uma linha reta do ponto atual de volta ao início do caminho, "fechando" o contorno. Para um círculo completo, o final já encontra o início, portantoclosePath()não tem efeito visível aqui — é incluído como bom hábito e importa quando você constrói formas abertas como um polígono.
O exemplo da linha anterior não precisou de nenhum dos dois métodos porque era um caminho único e independente. Assim que você desenhar uma segunda forma, recorra ao beginPath().
Transformações de Coordenadas
Em vez de recalcular cada coordenada manualmente, você pode mover, redimensionar ou rotacionar o sistema de coordenadas inteiro. As transformações afetam tudo que você desenhar depois de chamá-las.
Um padrão comum é envolver o desenho transformado com save() e restore() para que a grade retorne ao normal em seguida:
ctx.save(); // remember the current coordinate system
// ...transform and draw...
ctx.restore(); // put the coordinate system backtranslate(x, y)
Move a origem (0, 0) para uma nova posição. Após translate(50, 30), desenhar em (0, 0) aparece de fato em (50, 30):
ctx.translate(50, 30);
ctx.fillRect(0, 0, 80, 40); // top-left corner now sits at (50, 30)scale(x, y)
Multiplica o tamanho de cada coordenada e dimensão. scale(2, 2) dobra o tamanho de tudo; scale(1, 0.5) mantém a largura mas reduz a altura pela metade:
ctx.scale(2, 2);
ctx.fillRect(10, 10, 30, 30); // drawn at (20, 20), 60×60 in real pixelsrotate(angle)
Rotaciona o sistema de coordenadas no sentido horário em torno da origem atual. O ângulo é em radianos, assim como em arc(). Como a rotação acontece em torno de (0, 0), normalmente você usa translate() para ir até o ponto de pivô primeiro:
ctx.translate(100, 75); // move origin to the pivot point
ctx.rotate(45 * Math.PI / 180); // rotate 45° clockwise
ctx.fillRect(-25, -25, 50, 50); // a square centered on the pivotAs transformações mantêm suas coordenadas na mesma grade que você vinha usando — elas apenas reposicionam ou reformatam essa grade. Para desenhar texto posicionado nesse sistema, consulte Texto no Canvas.