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.
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 onesCommon 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.
Liulishuo Tech Team
Help everyone become a global citizen!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.