The Canvas API
The Canvas API lets you draw graphics pixel by pixel with JavaScript — shapes, lines, text, and images — by calling methods on a <canvas> element's 2D rendering context.
Learn The Canvas API in our free JavaScript course — an interactive lesson with runnable examples, a practice exercise and a quick reference.
Part of the free JavaScript course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
It powers charts, games, image editors, data visualizations, and any custom drawing the browser's normal HTML and CSS cannot express.
💡 About the runnable demos: A real <canvas> needs a browser, so the drawing code lives in the read-only blocks. Each Try it Yourself computes the geometry — the exact coordinates a shape would be drawn at — and logs it, which is the part people actually get wrong. Paste the read-only snippets into a browser to see them paint.
🖌️ Real-World Analogy: The canvas is a painter's canvas and the context is your set of brushes and pens . You don't move shapes around like furniture (that's the DOM); you paint them on. Want something to move? You wipe the canvas and repaint the whole scene a little differently — 60 times a second.
Grab the 2D context with canvas.getContext("2d") . The coordinate system starts at the top-left : X grows right, Y grows down . The quickest things to draw are rectangles: fillRect(x, y, w, h) paints a solid box, strokeRect outlines one, and clearRect erases a region.
To center a box you must offset by half its size — the classic coordinate bug. Let's compute that placement for real:
Anything beyond rectangles is a path . Start with beginPath() , move the "pen" with moveTo(x, y) , draw straight segments with lineTo(x, y) , and draw circles or arcs with arc(cx, cy, radius, startAngle, endAngle) — angles in radians . Finish by calling fill() or stroke() .
💡 Tip: Always call beginPath() before a new shape. Forget it and your new path connects to the previous one, producing stray lines.
A circle is really just points placed with trigonometry. Here we compute the points where arc would place markers around a circle — the basis of every pie chart and clock face:
Replace the blank with the argument that asks for the 2D drawing context.
Draw labels with ctx.font and fillText(text, x, y) . To animate, use requestAnimationFrame : it calls your function right before the next repaint. Each frame you clearRect the whole canvas, update positions, redraw, and schedule the next frame. Because the canvas is immediate-mode, nothing persists — you repaint the entire scene every time.
The motion itself is just arithmetic per frame. Here we compute the box's x-position over several frames, including the wrap-around — exactly what the loop above does:
Replace the blank so each cell's x is its column times the cell size.
ctx.clearRect(0, 0, canvas.width, canvas.height) .
Before you can draw a bar chart you must compute each bar's rectangle. Given some values and a chart height, produce the fillRect arguments for each bar so they sit on the baseline and scale to the tallest value.
Up next: Checkpoint: Browser APIs — tie it all together. 🏁
Practice quiz
How do you get the 2D drawing context from a canvas element?
- canvas.getContext('2d')
- canvas.context2d()
- canvas.draw('2d')
- canvas.get2D()
Answer: canvas.getContext('2d'). canvas.getContext('2d') returns the CanvasRenderingContext2D object, the toolbox of methods like fillRect, arc, and fillText.
Where is the origin (0, 0) on a canvas?
- The center
- The bottom-left corner
- The top-left corner
- The top-right corner
Answer: The top-left corner. The coordinate system starts at the top-left: X grows right and Y grows downward.
Which method paints a solid filled rectangle?
- strokeRect(x, y, w, h)
- clearRect(x, y, w, h)
- fillRect(x, y, w, h)
- drawRect(x, y, w, h)
Answer: fillRect(x, y, w, h). fillRect(x, y, w, h) paints a solid box; strokeRect outlines one and clearRect erases a region.
What units does arc() use for its start and end angles?
- Degrees
- Radians
- Pixels
- Percentages
Answer: Radians. arc() angles are in radians; a full circle is Math.PI * 2 (using 360 would be wrong).
To draw a custom path, which method should you call first to start a new shape?
- closePath()
- beginPath()
- moveTo()
- fill()
Answer: beginPath(). Always call beginPath() before a new shape; forgetting it makes the new path connect to the previous one, producing stray lines.
Which API is used to animate by running a draw function before each repaint?
- setInterval
- requestAnimationFrame
- setTimeout
- queueMicrotask
Answer: requestAnimationFrame. requestAnimationFrame calls your draw function right before the next repaint (about 60 times a second).
How do you erase the whole canvas at the start of each animation frame?
- ctx.reset()
- ctx.fillRect(0, 0, w, h)
- ctx.clearRect(0, 0, canvas.width, canvas.height)
- ctx.beginPath()
Answer: ctx.clearRect(0, 0, canvas.width, canvas.height). Because canvas is immediate-mode, you clearRect(0, 0, canvas.width, canvas.height) to wipe before repainting each frame.
To center an 80x40 box on a 300x200 canvas, what are the fillRect x and y?
- x: 150, y: 100
- x: 110, y: 80
- x: 80, y: 40
- x: 220, y: 160
Answer: x: 110, y: 80. fillRect takes the top-left corner, so x = 300/2 - 80/2 = 110 and y = 200/2 - 40/2 = 80.
What is the difference between fill and stroke?
- fill outlines, stroke fills inside
- fill paints the inside, stroke draws the outline
- They are identical
- fill is for text, stroke is for shapes
Answer: fill paints the inside, stroke draws the outline. fill paints the inside of a shape using fillStyle; stroke draws only its outline using strokeStyle and lineWidth.
Why should you size a canvas with width/height attributes instead of CSS?
- CSS sizing is slower to load
- Attributes set the real pixel resolution; CSS just stretches the bitmap and looks blurry
- CSS only works in Firefox
- Attributes enable WebGL automatically
Answer: Attributes set the real pixel resolution; CSS just stretches the bitmap and looks blurry. Setting width/height attributes sets the real pixel resolution; using CSS stretches a smaller bitmap and produces a blurry result.