Basics
Drawing your first shapes with fillRect, strokeRect, and clearRect.
In the Foundation lesson you learned what Canvas is, how the coordinate system works, and what the ctx object does. Now it’s time to draw. This lesson covers the three rectangle methods, the simplest way to put shapes on screen, plus colors, draw order, and practical examples.
fillRect: Drawing Filled Rectangles
The simplest drawing command is fillRect(x, y, width, height). It fills a rectangle with the current fillStyle color. You’ll also see ctx.fillText(text, x, y) used in many demos to add labels; it draws a string at the given position using the current ctx.font and fillStyle.
fillRect parameters:
ctx.fillRect(x, y, width, height)
│ │ │ │
│ │ │ └── how tall (in pixels)
│ │ └────────── how wide (in pixels)
│ └─────────────── Y of the top-left corner
└────────────────── X of the top-left corner
Example: ctx.fillRect(50, 30, 200, 100)
(50,30) ─────────── 200px ──────────┐
│ │
100px │
│ │
└───────────────────────────────┘
(250,130) Try this: Change the first rectangle’s color to '#ff2d7b' and make its width 300. Hit Run. Notice how the second rectangle draws on top, and its rgba transparency lets the first one show through.
fillStyle: Color Formats Explained
Before drawing, you set the color with ctx.fillStyle. Canvas accepts many color formats. Here are the most common ones:
Which format should I use? For beginners, named colors (like ‘red’, ‘dodgerblue’) are easiest. For precise control, use hex codes (‘#00e5ff’). When you need transparency, use rgba. The fillStyle stays set until you change it; it’s like dipping your brush in paint.
strokeRect: Outlined Rectangles
strokeRect(x, y, width, height) draws just the outline of a rectangle, without filling the inside. You control the outline color with strokeStyle, thickness with lineWidth, and pattern with setLineDash([dashLength, gapLength]) for dashed or dotted lines.
How lineWidth works: The stroke is centered on the edge of the rectangle. A lineWidth of 10 means 5 pixels inside the edge and 5 pixels outside. This is why thick outlines can look like they’re “growing” the rectangle.
lineWidth = 10
5px outside
──────████████████──────
█ █
█ inside █ 5px inside
█ █
──────████████████──────
5px outside
The stroke sits ON the boundary line,
half in, half out. clearRect: Erasing Pixels
clearRect(x, y, width, height) makes a rectangular area fully transparent. It erases whatever was drawn there. Think of it as a rectangular eraser.
The most common use of clearRect is clearing the entire canvas before redrawing (for animation):
// Clear everything: ctx.clearRect(0, 0, canvas.width, canvas.height);
Draw Order: What Happens When Shapes Overlap
Canvas works like painting on paper with opaque paint: the last thing you draw covers everything before it. This is called the painter’s algorithm. Just like a real painter, the newest layer goes on top.
Key insight: Canvas has no “layers” and no “z-index.” If you want shape A behind shape B, draw A first. If you want to change the order later, you have to clear the canvas and redraw everything in the new order. This is why animation always follows the pattern: clear -> draw everything -> repeat.
Practical Example: Drawing a Robot
Let’s use everything we’ve learned to draw something fun: a robot made entirely from rectangles!
Practical Example: A Simple House
Another example using mostly rectangles. Notice how draw order matters for the windows and door (they need to be drawn after the wall). The roof uses beginPath(), moveTo(), lineTo(), and fill() to draw a triangle, and the moon uses arc() to draw a circle. These are path commands covered fully in Lesson 2.
Putting It All Together: Night Cityscape
Here’s a more complex scene showing how many simple rectangles combine into something impressive. Study the code; it’s all fillRect, strokeRect, and clearRect!
Challenges
Try these exercises to practice what you’ve learned. You can open your browser’s console (F12) and create your own canvas, or modify the demo code above by looking at the patterns.
Challenge 1: Traffic Light
Draw a traffic light:
- A tall dark rectangle for the housing
- Three circles (red, yellow, green) stacked vertically
- A pole (thin rectangle) below
Hint: You know fillRect for the housing and pole.
For circles, use:
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2);
ctx.fill();
(We'll cover arcs fully in Lesson 2!) Challenge 2: Checkerboard
Draw an 8x8 checkerboard pattern:
- Use a nested for loop (row and column)
- Alternate colors based on (row + col) % 2
- Each square should be 40x40 pixels
Hint:
for (var row = 0; row < 8; row++) {
for (var col = 0; col < 8; col++) {
if ((row + col) % 2 === 0) {
ctx.fillStyle = '#c8c8d0';
} else {
ctx.fillStyle = '#1a1a2a';
}
ctx.fillRect(col * 40, row * 40, 40, 40);
}
} Challenge 3: Bar Chart
Draw a bar chart from an array of data:
var data = [80, 150, 60, 200, 120];
- Each bar is 50px wide with 20px gaps
- Bar height = the data value
- Bars grow UP from the bottom (y = canvasHeight - value)
- Different color for each bar
- Labels underneath each bar
This is a common real-world use of Canvas! What you learned in this lesson:
Concept How to do it ──────────────────── ─────────────────────────────── Set fill color ctx.fillStyle = '#ff0000' Set stroke color ctx.strokeStyle = '#00ff00' Fill a rectangle ctx.fillRect(x, y, w, h) Outline a rectangle ctx.strokeRect(x, y, w, h) Erase an area ctx.clearRect(x, y, w, h) Set line thickness ctx.lineWidth = 5 Make dashed lines ctx.setLineDash([dash, gap]) Key ideas: - (0,0) is top-left. Y goes DOWN. - Canvas size != CSS size. Use HTML attributes. - Later draws cover earlier draws (painter's algorithm). - fillStyle/strokeStyle persist until you change them.