W3docs

Canvas Coordinates

On this page, you can find useful information about the HTML canvas coordinates, as well as to learn to draw a circle and a line with our code examples.

HTML canvas is a powerful element in HTML5 that lets you create and manipulate graphics on a web page using JavaScript. The <canvas> element provides a two-dimensional drawing surface that you can think of as a grid or coordinate system.

This page explains how the canvas coordinate system works, how to read and write points on it, and how to move, scale, and rotate that system with transforms. If you are new to the element itself, start with the Canvas introduction first.

The Coordinate System

The canvas grid starts in the upper-left corner, which has the coordinates (0, 0). From there:

  • The x-axis increases to the right.
  • The y-axis increases downward (this is the opposite of the math classes most people remember, where y goes up).

Each point on the canvas is a pair (x, y) measured in pixels from that top-left origin.

(0,0)──────── x increases → ────────►
  │  ┌───────────────────────────────┐
  │  │ (0,0)                  (300,0) │
  y  │                               │
  │  │            (150,75)           │
  ▼  │                               │
     │ (0,150)              (300,150)│
     └───────────────────────────────┘

For a 300 × 150 canvas, (0, 0) is the top-left corner, (300, 0) is the top-right corner, (0, 150) is the bottom-left corner, and (150, 75) is the exact center.

The 2D rendering context

You never draw on the <canvas> element directly. Instead you ask it for a rendering context — an object that exposes the drawing methods (moveTo, lineTo, arc, fillRect, and so on):

const canvas = document.getElementById("myCanvas");
const ctx = canvas.getContext("2d");

getContext("2d") returns the 2D context used for all of the examples below. (Other context types exist, such as "webgl" for 3D, but "2d" is what canvas drawing uses.) Every coordinate you pass to a context method is interpreted in the grid described above.

Drawing a Line

The methods below are used to draw a straight line on a canvas:

  • moveTo(x,y), which specifies the starting point of the line
  • lineTo(x,y), which specifies the ending point of the line

Use one of the "ink" methods to draw a line, for example, stroke().

Example of the HTML <canvas> element to draw a line:

<!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>

In the example above, the line is drawn diagonally from (0, 0) (top-left) to (300, 150) (bottom-right). Notice that this single line did not need beginPath(): when nothing else has been drawn yet, moveTo/lineTo start a fresh path automatically. The circle below uses beginPath() because it is a separate shape — see the explanation in that section.

For more shapes and fills built on the same coordinate system, see Canvas drawing.

Drawing a Circle

The methods below are used to draw a circle on a canvas:

  • beginPath(), which starts a new path so the circle is not connected to anything drawn before it.
  • arc(x, y, r, startAngle, endAngle), which adds an arc (a portion of a circle) to the current path.

The arc() parameters

ParameterMeaning
x, yThe coordinates of the center of the circle.
rThe radius, in pixels.
startAngleWhere the arc begins, in radians.
endAngleWhere the arc ends, in radians.

Angles are measured in radians, not degrees, and 0 points to the right (the positive x-axis), turning clockwise. A full turn is 2 * Math.PI radians (360°), so a complete circle goes from 0 to 2 * Math.PI.

To convert degrees to radians, multiply by Math.PI / 180:

const radians = degrees * (Math.PI / 180);

Partial arcs

You do not have to draw a full circle. Use a smaller end angle to draw just part of one. For example, an arc from 0 to Math.PI (half a full turn) draws the bottom half of a circle, because y increases downward:

// A half-circle (bottom half) centered at (100, 75) with radius 50
ctx.beginPath();
ctx.arc(100, 75, 50, 0, Math.PI);
ctx.stroke();

Example of the HTML <canvas> element to draw a circle:

<!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>

In the example above, the circle is centered at (125, 95) with a radius of 70.

beginPath() and closePath()

These two methods often cause confusion:

  • beginPath() discards any path you were building and starts a brand-new one. Call it before each independent shape — otherwise the new shape is joined to the previous one, and a single stroke()/fill() styles them all together.
  • closePath() draws a straight line from the current point back to where the path started, "closing" the outline. For a full circle the end already meets the start, so closePath() here has no visible effect — it is included as a habit and matters when you build open shapes such as a polygon.

The line example earlier needed neither method because it was a single, standalone path. As soon as you draw a second shape, reach for beginPath().

Coordinate Transforms

Instead of recalculating every coordinate by hand, you can move, resize, or rotate the whole coordinate system. Transforms affect everything you draw after you call them.

A common pattern is to wrap transformed drawing in save() and restore() so the grid returns to normal afterward:

ctx.save();      // remember the current coordinate system
// ...transform and draw...
ctx.restore();   // put the coordinate system back

translate(x, y)

Moves the origin (0, 0) to a new position. After translate(50, 30), drawing at (0, 0) actually appears at (50, 30):

ctx.translate(50, 30);
ctx.fillRect(0, 0, 80, 40); // top-left corner now sits at (50, 30)

scale(x, y)

Multiplies the size of every coordinate and dimension. scale(2, 2) makes everything twice as large; scale(1, 0.5) keeps width but halves height:

ctx.scale(2, 2);
ctx.fillRect(10, 10, 30, 30); // drawn at (20, 20), 60×60 in real pixels

rotate(angle)

Rotates the coordinate system clockwise around the current origin. The angle is in radians, like arc(). Because rotation happens around (0, 0), you usually translate() to the desired pivot first:

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 pivot

Transforms keep your coordinates in the same grid you have been using all along — they just relocate or reshape that grid. For drawing positioned text on this system, see Canvas text.

Practice

Practice
What are the characteristics of the HTML5 <canvas> element coordinates?
What are the characteristics of the HTML5 <canvas> element coordinates?
Was this page helpful?