Frontend Development 14 min read

Introduction to HTML5 Canvas: Basics, Usage, and Practical Examples

This article introduces HTML5 Canvas, explains its advantages over SVG, and provides comprehensive guidance on using the Canvas API—including context acquisition, drawing shapes, paths, arcs, gradients, pixel manipulation, state management, transformations, and a complete clock example—illustrated with code snippets and visual demos.

Liulishuo Tech Team
Liulishuo Tech Team
Liulishuo Tech Team
Introduction to HTML5 Canvas: Basics, Usage, and Practical Examples

HTML5 provides the Canvas API, a DOM element that offers a drawing surface for rendering 2D (and limited 3D via WebGL) graphics directly with JavaScript.

Compared with SVG, Canvas does not retain a vector DOM structure; instead, drawing commands are executed on a bitmap canvas, which can yield better performance for dynamic or complex scenes such as animations, games, data visualizations, photo editing, and real‑time video processing.

To start using Canvas, obtain a reference to the <canvas id="canvas"></canvas> element and call getContext('2d') to retrieve the 2D rendering context.

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

The 2D context exposes many properties, for example:

width, height – canvas dimensions (default 300×150)

fillStyle – fill color or gradient

strokeStyle – stroke color or gradient

lineWidth – line thickness

globalAlpha – overall opacity (0‑1)

globalCompositeOperation – how new drawings blend with existing content

ctx.width = 300;
ctx.height = 300;
ctx.fillStyle = '#fff';
ctx.strokeStyle = 'blue';
ctx.lineWidth = 5;
ctx.globalAlpha = 0.3;
ctx.globalCompositeOperation = 'destination-out'; // new shapes become transparent where they overlap old ones

Common shape‑drawing methods include:

fillRect(x, y, w, h) – filled rectangle

strokeRect(x, y, w, h) – rectangle outline

clearRect(x, y, w, h) – clear a region to full transparency

ctx.fillStyle = 'red';
ctx.fillRect(100, 100, 100, 100);
ctx.strokeStyle = 'blue';
ctx.strokeRect(200, 200, 100, 100);
ctx.clearRect(125, 125, 50, 50);
ctx.strokeRect(130, 130, 40, 40);

Path‑based drawing uses a sequence of commands:

beginPath() , closePath()

moveTo(x, y) , lineTo(x, y)

fill() , stroke()

ctx.beginPath();
ctx.moveTo(50, 50);
ctx.lineTo(100, 100);
ctx.lineTo(100, 0);
ctx.fill();

ctx.beginPath();
ctx.moveTo(110, 100);
ctx.lineTo(150, 100);
ctx.lineTo(150, 200);
ctx.lineTo(110, 200);
ctx.closePath(); // close the shape
ctx.stroke();

Arcs are drawn with arc() (angles are in radians) and arcTo() for tangent‑based curves. Example:

// upper‑left quarter of a circle
ctx.beginPath();
ctx.arc(100, 100, 50, Math.PI, Math.PI * 1.5, false);
ctx.strokeStyle = '#ff6700';
ctx.stroke();

Gradients are created via createLinearGradient() or createRadialGradient() and populated with addColorStop(offset, color) :

const gradient = ctx.createLinearGradient(50, 50, 250, 50);
gradient.addColorStop(0, 'blue');
gradient.addColorStop(0.5, 'green');
gradient.addColorStop(1, 'red');
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, 300, 90);

const radial = ctx.createRadialGradient(200, 200, 100, 200, 200, 50);
radial.addColorStop(0, 'yellow');
radial.addColorStop(1, 'green');
ctx.fillStyle = radial;
ctx.fillRect(100, 100, 200, 200);

Pixel‑level operations include drawImage() and getImageData() . The following example lets the user click the canvas to read the color of the clicked pixel and display it:

const div = document.querySelector('div');
let mousedown = false;
function getRandom(){ return Math.round(255 * Math.random()); }
function getColor(){ return `rgb(${getRandom()},${getRandom()},${getRandom()})`; }
const gradient = ctx.createLinearGradient(0,0,300,300);
gradient.addColorStop(0, getColor());
gradient.addColorStop(0.6, getColor());
gradient.addColorStop(1, getColor());
function clear(){ ctx.fillStyle = gradient; ctx.fillRect(0,0,canvas.width,canvas.height); }
function selector(x=150, y=150){
  clear();
  ctx.beginPath();
  ctx.arc(x, y, 5, 0, Math.PI*2);
  ctx.strokeStyle = '#fff';
  ctx.stroke();
  const {data} = ctx.getImageData(x, y, 1, 1);
  const color = `rgba(${data[0]},${data[1]},${data[2]},${data[3]/255})`;
  div.innerText = `color: ${color}`;
  div.style.backgroundColor = color;
}
canvas.addEventListener('mousedown', e=>{ mousedown=true; selector(e.offsetX, e.offsetY); });
canvas.addEventListener('mouseup', ()=>{ mousedown=false; });
canvas.addEventListener('mousemove', e=>{ if(mousedown) selector(e.offsetX, e.offsetY); });
selector();

Canvas state can be saved and restored with save() and restore() , which is essential when applying transformations:

ctx.save();
ctx.translate(100, 100);
ctx.fillStyle = 'red';
ctx.fillRect(0,0,50,50);
ctx.restore();
ctx.fillStyle = 'blue';
ctx.fillRect(0,0,50,50);

Transformations such as translate() , rotate() , scale() , and transform() modify the drawing coordinate system. Example of drawing a rotating color wheel:

const colors = ['red','orange','yellow','green','blue','purple'];
ctx.translate(150,150);
for(let i=0;i<6;i++){
  ctx.beginPath();
  ctx.fillStyle = colors[i];
  ctx.moveTo(0,0);
  ctx.lineTo(100,0);
  ctx.lineTo(100,50);
  ctx.rotate(Math.PI/3);
  ctx.fill();
}

A complete practical example is a real‑time analog clock built entirely with Canvas. The script updates every animation frame, draws the clock face, hour/minute/second hands, and displays the current time:

const p = Math.PI;
function clock(){
  const date = new Date();
  const hour = date.getHours();
  const s = date.getSeconds();
  const m = date.getMinutes();
  const h = hour % 12 || 12;
  ctx.clearRect(0,0,canvas.width,canvas.height);
  ctx.save();
  ctx.translate(150,150);
  ctx.rotate(-p/2);
  // outer circle
  ctx.beginPath();
  ctx.lineWidth = 5;
  ctx.strokeStyle = '#76b2ff';
  ctx.arc(0,0,80,0,p*2);
  ctx.stroke();
  // center dot
  ctx.beginPath();
  ctx.arc(0,0,2,0,p*2);
  ctx.fill();
  // minute/second ticks
  for(let i=0;i<60;i++){
    ctx.beginPath();
    ctx.rotate(p/30);
    ctx.moveTo(75,0);
    ctx.lineWidth = 4;
    ctx.strokeStyle = '#89f086';
    ctx.lineTo(80,0);
    ctx.stroke();
  }
  // hour ticks
  for(let i=0;i<12;i++){
    ctx.beginPath();
    ctx.rotate(p/6);
    ctx.moveTo(70,0);
    ctx.lineTo(80,0);
    ctx.stroke();
  }
  // second hand
  ctx.save();
  ctx.rotate(s * (p/30));
  ctx.lineWidth = 2;
  ctx.strokeStyle = '#ff6700';
  ctx.moveTo(0,0);
  ctx.lineTo(80,0);
  ctx.stroke();
  ctx.restore();
  // minute hand
  ctx.save();
  ctx.rotate(m * (p/30));
  ctx.lineWidth = 3;
  ctx.strokeStyle = '#6700ff';
  ctx.moveTo(0,0);
  ctx.lineTo(70,0);
  ctx.stroke();
  ctx.restore();
  // hour hand
  ctx.save();
  ctx.rotate(h * (p/6));
  ctx.lineWidth = 4;
  ctx.moveTo(0,0);
  ctx.lineTo(60,0);
  ctx.stroke();
  ctx.restore();
  document.querySelector('div').innerText = `Now: ${h} : ${m} : ${s} ${hour>12?'pm':'am'}`;
  window.requestAnimationFrame(clock);
}
clock();

In summary, Canvas equips web developers with a powerful, high‑performance drawing API that enables rich visual experiences ranging from simple shapes to complex interactive graphics, making it an essential tool for modern front‑end development.

JavaScriptcanvasWeb DevelopmentHTML52D Graphics
Liulishuo Tech Team
Written by

Liulishuo Tech Team

Help everyone become a global citizen!

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.