HTML Canvas Basics

Introduction to Canvas

The HTML <canvas> element provides a powerful drawing surface for creating graphics, animations, data visualizations, and interactive applications directly in the browser using JavaScript.

Key Features of Canvas:
  • Pixel-based rendering (raster graphics)
  • Immediate mode rendering (draw and forget)
  • High performance for animations and games
  • Programmatic drawing with JavaScript
  • Support for both 2D and 3D (WebGL) contexts

Canvas vs. SVG

Feature Canvas SVG
Rendering Pixel-based (raster) Shape-based (vector)
DOM Integration Single HTML element Each shape is a DOM element
Event Handling Manual implementation required Built-in per-element events
Resolution Dependency Resolution-dependent Resolution-independent
Performance with Many Objects Better for many objects (>1000) Better for fewer objects (<1000)
Text Rendering Less accessible, not selectable Accessible, selectable

Getting Started with Canvas

Creating a Canvas Element

To use Canvas, you first need to add the <canvas> element to your HTML:

<canvas id="myCanvas" width="600" height="400">
    Your browser does not support the canvas element.
</canvas>
Important: Always specify the width and height attributes directly on the canvas element, not through CSS. Using CSS to resize the canvas will scale the rendered output, potentially causing distortion.

Accessing the Canvas Context

To draw on the canvas, you need to get a reference to its rendering context:

// Get the canvas element
const canvas = document.getElementById('myCanvas');

// Get the 2D rendering context
const ctx = canvas.getContext('2d');

// Now you can use ctx to draw on the canvas

Canvas Coordinate System

The canvas uses a coordinate system where:

  • The origin (0,0) is at the top-left corner
  • X-axis runs horizontally from left to right
  • Y-axis runs vertically from top to bottom
Canvas coordinate system

Image source: MDN Web Docs. © Mozilla Contributors. Licensed under CC-BY-SA 2.5.

Basic Drawing Operations

Drawing Rectangles

Canvas provides three methods for drawing rectangles:

// Draw a filled rectangle
ctx.fillRect(x, y, width, height);

// Draw a rectangular outline
ctx.strokeRect(x, y, width, height);

// Clear a rectangular area
ctx.clearRect(x, y, width, height);

Drawing Paths

For more complex shapes, you need to create paths:

// Begin a new path
ctx.beginPath();

// Move to starting point
ctx.moveTo(x, y);

// Draw lines
ctx.lineTo(x, y);

// Draw arcs/curves
ctx.arc(x, y, radius, startAngle, endAngle, counterclockwise);

// Close the path
ctx.closePath();

// Stroke or fill the path
ctx.stroke();
ctx.fill();

Styling and Colors

Colors and Transparency

You can set colors for fills and strokes:

// Using CSS color values
ctx.fillStyle = 'red';
ctx.strokeStyle = '#00ff00';
ctx.fillStyle = 'rgb(0, 0, 255)';
ctx.strokeStyle = 'rgba(255, 0, 0, 0.5)'; // Red with 50% opacity

Line Styles

Customize the appearance of lines:

// Line width
ctx.lineWidth = 5;

// Line cap style (butt, round, square)
ctx.lineCap = 'round';

// Line join style (miter, round, bevel)
ctx.lineJoin = 'bevel';

// Dashed lines
ctx.setLineDash([5, 15]); // Alternating 5px dash and 15px gap
ctx.lineDashOffset = 0;

Gradients and Patterns

Create gradients and patterns for fills and strokes:

// Linear gradient
const linearGradient = ctx.createLinearGradient(x0, y0, x1, y1);
linearGradient.addColorStop(0, 'white');
linearGradient.addColorStop(1, 'black');
ctx.fillStyle = linearGradient;

// Radial gradient
const radialGradient = ctx.createRadialGradient(x0, y0, r0, x1, y1, r1);
radialGradient.addColorStop(0, 'white');
radialGradient.addColorStop(1, 'black');
ctx.fillStyle = radialGradient;

// Pattern
const img = document.getElementById('patternImg');
const pattern = ctx.createPattern(img, 'repeat');
ctx.fillStyle = pattern;

Text and Images

Drawing Text

Canvas provides methods for rendering text:

// Text styling
ctx.font = 'bold 24px Arial, sans-serif';
ctx.textAlign = 'center'; // start, end, left, right, center
ctx.textBaseline = 'middle'; // top, hanging, middle, alphabetic, ideographic, bottom
ctx.direction = 'ltr'; // ltr, rtl

// Draw filled text
ctx.fillText('Hello Canvas', x, y, maxWidth);

// Draw outlined text
ctx.strokeText('Hello Canvas', x, y, maxWidth);

Drawing Images

You can draw images onto the canvas:

// Basic image drawing
ctx.drawImage(image, x, y);

// Scaled image drawing
ctx.drawImage(image, x, y, width, height);

// Cropped and scaled image drawing
ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
Note: The image parameter can be an HTMLImageElement, HTMLVideoElement, HTMLCanvasElement, or ImageBitmap.

Transformations

Basic Transformations

Canvas supports various transformations to modify the coordinate system:

// Translation - move the origin
ctx.translate(x, y);

// Rotation - rotate around the current origin
ctx.rotate(angleInRadians);

// Scaling - scale drawing operations
ctx.scale(x, y);

// Save and restore the transformation state
ctx.save(); // Push the current state onto the stack
// ... perform transformations and drawing ...
ctx.restore(); // Pop the state from the stack

Custom Transformations

For more complex transformations, you can use the transform matrix:

// Apply a custom transformation matrix
ctx.transform(a, b, c, d, e, f);

// Reset and set the transformation matrix
ctx.setTransform(a, b, c, d, e, f);

// Reset to the identity matrix
ctx.resetTransform();

Compositing and Clipping

Compositing Operations

Control how new shapes are drawn on top of existing content:

// Set the compositing operation
ctx.globalCompositeOperation = 'source-over'; // Default - draw new shapes on top

// Other common values:
// 'source-in' - show new shape only where it overlaps with existing content
// 'source-out' - show new shape only where it doesn't overlap with existing content
// 'destination-over' - draw new shapes behind existing content
// 'destination-in' - show existing content only where it overlaps with new shape
// 'destination-out' - show existing content only where it doesn't overlap with new shape
// 'lighter' - add color values
// 'multiply' - multiply color values
// 'screen' - inverse multiply
// 'xor' - exclusive OR

Clipping Paths

Restrict drawing to a specific region:

// Create a clipping path
ctx.beginPath();
ctx.arc(100, 100, 75, 0, Math.PI * 2);
ctx.clip();

// All subsequent drawing will be clipped to the circle
ctx.fillRect(0, 0, 200, 200); // Only shows within the circle

Animation Basics

Animation Loop

Create animations by repeatedly drawing frames:

function draw() {
    // Clear the canvas
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    
    // Update animation state
    // ...
    
    // Draw the current frame
    // ...
    
    // Request the next frame
    requestAnimationFrame(draw);
}

// Start the animation
requestAnimationFrame(draw);
Best Practice: Always use requestAnimationFrame for animations instead of setTimeout or setInterval. It provides better performance and automatically pauses when the tab is not visible.

Canvas Performance Tips

  • Pre-render complex shapes to off-screen canvases and reuse them
  • Batch drawing operations to minimize state changes
  • Use appropriate canvas size - larger canvases require more memory and processing
  • Avoid unnecessary clearRect calls if only part of the canvas changes
  • Use requestAnimationFrame for animations
  • Consider using WebGL for complex 3D graphics or when hardware acceleration is needed
  • Optimize loops in animation code to avoid garbage collection
  • Use integer pixel values when possible to avoid anti-aliasing

Browser Support and Fallbacks

Canvas is supported in all modern browsers, but it's good practice to provide fallback content:

<canvas id="myCanvas" width="600" height="400">
    <p>Your browser doesn't support canvas. Please upgrade to a modern browser.</p>
    <img src="fallback-image.png" alt="Fallback image">
</canvas>

Always check for canvas support before using it:

const canvas = document.getElementById('myCanvas');
if (canvas.getContext) {
    const ctx = canvas.getContext('2d');
    // Canvas is supported, proceed with drawing
} else {
    // Canvas is not supported, handle fallback
    console.log('Canvas not supported');
}

Resources and Further Reading

Popular Canvas Libraries

  • Konva.js - 2D canvas library for drawing and animations
  • Chart.js - Simple yet flexible JavaScript charting
  • PixiJS - Fast 2D rendering library
  • Fabric.js - Canvas library with interactive object model
  • Three.js - 3D library using WebGL