JavaScript provides two primary ways to create graphics in the browser: Canvas (pixel-based, imperative) and SVG (vector-based, declarative). This chapter covers both with practical drawing examples.
The <canvas> element provides a bitmap drawing surface. You access its 2D rendering context through JavaScript and issue drawing commands.
<canvas id="myCanvas" width="400" height="300"></canvas>
<script>
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
</script>
// Rectangle
ctx.fillStyle = '#3b82f6';
ctx.fillRect(20, 20, 150, 100);
ctx.strokeStyle = '#1e293b';
ctx.lineWidth = 3;
ctx.strokeRect(20, 20, 150, 100);
// Circle (arc)
ctx.beginPath();
ctx.arc(300, 70, 40, 0, Math.PI * 2);
ctx.fillStyle = '#22c55e';
ctx.fill();
ctx.stroke();
ctx.beginPath();
ctx.moveTo(50, 200);
ctx.lineTo(200, 250);
ctx.lineTo(100, 280);
ctx.closePath();
ctx.fillStyle = '#eab308';
ctx.fill();
ctx.font = 'bold 24px Arial';
ctx.fillStyle = '#0f172a';
ctx.fillText('Hello Canvas!', 50, 50);
ctx.strokeText('Hello Canvas!', 50, 90);
const gradient = ctx.createLinearGradient(0, 0, 400, 0);
gradient.addColorStop(0, '#ff0000');
gradient.addColorStop(1, '#0000ff');
ctx.fillStyle = gradient;
ctx.fillRect(0, 200, 400, 50);
SVG describes 2D graphics using XML markup. Elements are part of the DOM and can be styled with CSS and manipulated with JavaScript.
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
<rect x="10" y="10" width="80" height="80" fill="#3b82f6" rx="8" />
<circle cx="150" cy="50" r="40" fill="#22c55e" />
<polygon points="100,150 50,190 150,190" fill="#eab308" />
</svg>
<svg width="300" height="200" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(20, 20)">
<rect width="100" height="60" fill="#f59e0b" />
<text x="50" y="35" text-anchor="middle" fill="white">Group</text>
</g>
<g transform="rotate(45, 200, 80)">
<rect x="150" y="40" width="80" height="80" fill="#ef4444" />
</g>
</svg>
const data = [30, 85, 55, 70, 45];
const barWidth = 50;
const gap = 20;
ctx.fillStyle = '#3b82f6';
data.forEach((val, i) => {
const x = 30 + i * (barWidth + gap);
const h = val * 2;
ctx.fillRect(x, 250 - h, barWidth, h);
});
// Face
ctx.beginPath();
ctx.arc(200, 150, 80, 0, Math.PI * 2);
ctx.fillStyle = '#fef9c3';
ctx.fill();
ctx.stroke();
// Eyes
ctx.fillStyle = '#1e293b';
ctx.beginPath(); ctx.arc(170, 130, 8, 0, Math.PI * 2); ctx.fill();
ctx.beginPath(); ctx.arc(230, 130, 8, 0, Math.PI * 2); ctx.fill();
// Smile
ctx.beginPath();
ctx.arc(200, 150, 50, 0.1 * Math.PI, 0.9 * Math.PI);
ctx.stroke();
function drawClock() {
const now = new Date();
const sec = now.getSeconds() * (Math.PI / 30);
const min = now.getMinutes() * (Math.PI / 30);
const hr = now.getHours() * (Math.PI / 6);
ctx.clearRect(0, 0, 400, 400);
ctx.beginPath();
ctx.arc(200, 200, 150, 0, Math.PI * 2);
ctx.stroke();
// Hour hand, minute hand, second hand
ctx.beginPath(); ctx.moveTo(200, 200); ctx.lineTo(200 + 80 * Math.sin(hr), 200 - 80 * Math.cos(hr)); ctx.stroke();
ctx.beginPath(); ctx.moveTo(200, 200); ctx.lineTo(200 + 120 * Math.sin(min), 200 - 120 * Math.cos(min)); ctx.stroke();
ctx.beginPath(); ctx.moveTo(200, 200); ctx.lineTo(200 + 140 * Math.sin(sec), 200 - 140 * Math.cos(sec)); ctx.stroke();
}
| Aspect | Canvas | SVG |
|---|---|---|
| Rendering | Pixel-based | Vector-based |
| DOM integration | None | Full DOM tree |
| Performance | Fast for many elements | Best for fewer, interactive elements |
| Accessibility | Not accessible | Accessible via ARIA |
| Use case | Games, image processing | Diagrams, icons, charts |
Use the Canvas API to create a bouncing ball animation. The ball should start at the top-left corner and bounce off the edges of the canvas. Use requestAnimationFrame() for smooth animation. Add a second ball with a different colour and speed.