frontend
Canvas API in JavaScript
January 24, 2026
Canvas API in JavaScript
Overview
The HTML5 Canvas API provides a powerful way to draw graphics, animations, and interactive content using JavaScript. The Canvas element creates a fixed-size drawing surface that you can manipulate with JavaScript to render 2D shapes, images, text, and animations.
Basic Setup
/** Canvas drawing using vanilla js */
window.addEventListener("load", (e) => {
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
canvas.height = window.innerHeight;
canvas.width = window.innerWidth;
let painting = false;
function startPosition() {
painting = true;
draw(e);
}
function endPosition() {
painting = false;
ctx.beginPath();
}
function draw(e) {
if (!painting) return;
ctx.lineWidth = 5;
ctx.lineCap = "round";
ctx.lineTo(e.clientX, e.clientY);
ctx.stroke();
}
canvas.addEventListener("mousedown", startPosition);
canvas.addEventListener("mouseup", endPosition);
canvas.addEventListener("mousemove", draw);
});
Getting Started
HTML Setup
<canvas id="canvas"></canvas>
JavaScript Setup
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
// Set canvas size
canvas.width = 800;
canvas.height = 600;
Drawing Shapes
Lines
ctx.beginPath();
ctx.moveTo(50, 50);
ctx.lineTo(200, 100);
ctx.stroke();
Rectangles
// Filled rectangle
ctx.fillStyle = "blue";
ctx.fillRect(10, 10, 100, 100);
// Stroked rectangle
ctx.strokeStyle = "red";
ctx.lineWidth = 5;
ctx.strokeRect(150, 10, 100, 100);
// Clear rectangle
ctx.clearRect(50, 50, 50, 50);
Circles and Arcs
ctx.beginPath();
ctx.arc(100, 100, 50, 0, Math.PI * 2);
ctx.fillStyle = "green";
ctx.fill();
ctx.stroke();
Paths
ctx.beginPath();
ctx.moveTo(50, 50);
ctx.lineTo(100, 100);
ctx.lineTo(150, 50);
ctx.closePath();
ctx.stroke();
Text
// Fill text
ctx.font = "30px Arial";
ctx.fillStyle = "black";
ctx.fillText("Hello Canvas", 10, 50);
// Stroke text
ctx.strokeText("Hello Canvas", 10, 100);
// Text alignment
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText("Centered", canvas.width / 2, canvas.height / 2);
Images
const img = new Image();
img.onload = function() {
// Draw image
ctx.drawImage(img, 0, 0);
// Draw scaled image
ctx.drawImage(img, 0, 0, 200, 200);
// Draw cropped image
ctx.drawImage(img, 50, 50, 100, 100, 0, 0, 200, 200);
};
img.src = "image.jpg";
Transformations
// Save context state
ctx.save();
// Translate
ctx.translate(100, 100);
// Rotate
ctx.rotate(Math.PI / 4);
// Scale
ctx.scale(2, 2);
// Draw something
ctx.fillRect(0, 0, 50, 50);
// Restore context state
ctx.restore();
Gradients
Linear Gradient
const gradient = ctx.createLinearGradient(0, 0, 200, 0);
gradient.addColorStop(0, "red");
gradient.addColorStop(1, "blue");
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, 200, 100);
Radial Gradient
const radialGradient = ctx.createRadialGradient(100, 100, 0, 100, 100, 100);
radialGradient.addColorStop(0, "white");
radialGradient.addColorStop(1, "black");
ctx.fillStyle = radialGradient;
ctx.fillRect(0, 0, 200, 200);
Patterns
const pattern = ctx.createPattern(img, "repeat");
ctx.fillStyle = pattern;
ctx.fillRect(0, 0, canvas.width, canvas.height);
Animation
let x = 0;
function animate() {
// Clear canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Draw
ctx.fillRect(x, 50, 50, 50);
// Update
x += 2;
if (x > canvas.width) x = 0;
// Next frame
requestAnimationFrame(animate);
}
animate();
Interactive Drawing
class DrawingApp {
constructor(canvasId) {
this.canvas = document.getElementById(canvasId);
this.ctx = this.canvas.getContext("2d");
this.isDrawing = false;
this.lastX = 0;
this.lastY = 0;
this.setupEventListeners();
}
setupEventListeners() {
this.canvas.addEventListener("mousedown", (e) => this.startDrawing(e));
this.canvas.addEventListener("mousemove", (e) => this.draw(e));
this.canvas.addEventListener("mouseup", () => this.stopDrawing());
this.canvas.addEventListener("mouseout", () => this.stopDrawing());
}
startDrawing(e) {
this.isDrawing = true;
const rect = this.canvas.getBoundingClientRect();
this.lastX = e.clientX - rect.left;
this.lastY = e.clientY - rect.top;
}
draw(e) {
if (!this.isDrawing) return;
const rect = this.canvas.getBoundingClientRect();
const currentX = e.clientX - rect.left;
const currentY = e.clientY - rect.top;
this.ctx.beginPath();
this.ctx.moveTo(this.lastX, this.lastY);
this.ctx.lineTo(currentX, currentY);
this.ctx.stroke();
this.lastX = currentX;
this.lastY = currentY;
}
stopDrawing() {
this.isDrawing = false;
}
clear() {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
Common Use Cases
1. Data Visualization
function drawBarChart(data) {
const barWidth = canvas.width / data.length;
const maxValue = Math.max(...data);
data.forEach((value, index) => {
const barHeight = (value / maxValue) * canvas.height;
ctx.fillRect(index * barWidth, canvas.height - barHeight, barWidth - 2, barHeight);
});
}
2. Game Development
class Game {
constructor() {
this.player = { x: 100, y: 100, width: 50, height: 50 };
this.animate();
}
update() {
// Update game state
}
render() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillRect(this.player.x, this.player.y, this.player.width, this.player.height);
}
animate() {
this.update();
this.render();
requestAnimationFrame(() => this.animate());
}
}
3. Image Manipulation
function applyFilter(imageData) {
const data = imageData.data;
for (let i = 0; i < data.length; i += 4) {
// Grayscale filter
const gray = data[i] * 0.299 + data[i + 1] * 0.587 + data[i + 2] * 0.114;
data[i] = gray;
data[i + 1] = gray;
data[i + 2] = gray;
}
return imageData;
}
Best Practices
- Use requestAnimationFrame: For smooth animations
- Clear Properly: Always clear before redrawing
- Save/Restore Context: Use save/restore for transformations
- Optimize Drawing: Batch operations when possible
- Handle Resize: Update canvas size on window resize
- Memory Management: Clean up event listeners
Performance Tips
- Offscreen Canvas: Use for pre-rendering
- Image Caching: Cache frequently used images
- Reduce Redraws: Only redraw changed areas
- Use Layers: Multiple canvases for different layers
- Optimize Paths: Minimize path operations
Browser Compatibility
Canvas API is supported in all modern browsers. For older browsers, consider using polyfills or fallbacks.