HTML Canvas
Explore HTML5 Canvas for creating dynamic graphics, animations, data visualizations, and interactive digital art using JavaScript.
Introduction to HTML5 Canvas
The HTML5 <canvas>
element provides a powerful drawing surface for creating dynamic graphics, animations, games, and data visualizations directly in the browser. Unlike static images, canvas content is generated programmatically using JavaScript, enabling interactive and responsive graphics.
Canvas operates as a bitmap that can be manipulated pixel by pixel, making it ideal for complex graphics operations, image processing, and real-time visual effects that would be impossible with traditional HTML and CSS alone.
🎨 Key Concept
Canvas is like a digital drawing board that JavaScript can paint on, creating everything from simple shapes to complex interactive graphics and animations.
Canvas Element Basics
Setting up and accessing the canvas drawing context:
<!-- HTML Canvas element --> <canvas id="myCanvas" width="600" height="400" style="border: 1px solid #ccc;"> Your browser does not support the HTML5 Canvas element. </canvas> <script> // Get canvas element and 2D rendering context const canvas = document.getElementById('myCanvas'); const ctx = canvas.getContext('2d'); // Check if Canvas is supported if (ctx) { // Canvas is supported, start drawing ctx.fillStyle = '#007bff'; ctx.fillRect(50, 50, 200, 100); } else { // Canvas not supported console.log('Canvas is not supported'); } </script>
- Set
width
andheight
attributes in HTML, not CSS - CSS sizing stretches the canvas like an image
- Always provide fallback content for unsupported browsers
- Use
getContext('2d')
for 2D graphics - Check context availability before drawing
Drawing Shapes and Paths
<canvas id="shapes" width="500" height="400"></canvas> <script> const canvas = document.getElementById('shapes'); const ctx = canvas.getContext('2d'); // Rectangle methods ctx.fillStyle = '#ff6b6b'; ctx.fillRect(20, 20, 100, 80); // Filled rectangle ctx.strokeStyle = '#4ecdc4'; ctx.lineWidth = 3; ctx.strokeRect(140, 20, 100, 80); // Rectangle outline ctx.clearRect(260, 20, 100, 80); // Clear rectangle area // Drawing paths ctx.beginPath(); ctx.moveTo(50, 150); // Start point ctx.lineTo(150, 150); // Line to ctx.lineTo(100, 200); // Line to ctx.closePath(); // Close path ctx.fillStyle = '#45b7d1'; ctx.fill(); // Fill the triangle // Circles and arcs ctx.beginPath(); ctx.arc(300, 175, 40, 0, 2 * Math.PI); // Full circle ctx.fillStyle = '#f7b731'; ctx.fill(); ctx.strokeStyle = '#333'; ctx.stroke(); // Arc (partial circle) ctx.beginPath(); ctx.arc(400, 175, 30, 0, Math.PI); // Half circle ctx.fillStyle = '#5f27cd'; ctx.fill(); // Bezier curves ctx.beginPath(); ctx.moveTo(50, 270); ctx.quadraticCurveTo(100, 220, 150, 270); // Quadratic curve ctx.strokeStyle = '#ff9ff3'; ctx.lineWidth = 4; ctx.stroke(); // Cubic Bezier curve ctx.beginPath(); ctx.moveTo(200, 270); ctx.bezierCurveTo(220, 220, 280, 220, 300, 270); ctx.strokeStyle = '#54a0ff'; ctx.stroke(); </script>
Text and Styling
<canvas id="text" width="600" height="300"></canvas> <script> const canvas = document.getElementById('text'); const ctx = canvas.getContext('2d'); // Text styling ctx.font = '30px Arial'; ctx.fillStyle = '#333'; ctx.textAlign = 'center'; // left, right, center, start, end ctx.textBaseline = 'middle'; // top, bottom, middle, alphabetic // Filled text ctx.fillText('HTML5 Canvas', 300, 60); // Outlined text ctx.strokeStyle = '#007bff'; ctx.lineWidth = 2; ctx.strokeText('Outlined Text', 300, 120); // Combined fill and stroke ctx.fillStyle = '#ff6b6b'; ctx.fillText('Combined Style', 300, 180); ctx.strokeText('Combined Style', 300, 180); // Measure text dimensions const textMetrics = ctx.measureText('Measured Text'); console.log('Text width:', textMetrics.width); // Gradients and patterns const gradient = ctx.createLinearGradient(200, 240, 400, 240); gradient.addColorStop(0, '#ff6b6b'); gradient.addColorStop(0.5, '#4ecdc4'); gradient.addColorStop(1, '#45b7d1'); ctx.fillStyle = gradient; ctx.font = '25px bold Arial'; ctx.fillText('Gradient Text', 300, 240); </script>
Images and Transformations
<canvas id="images" width="600" height="400"></canvas> <img id="sourceImage" src="logo.png" style="display: none;"> <script> const canvas = document.getElementById('images'); const ctx = canvas.getContext('2d'); const img = document.getElementById('sourceImage'); img.onload = function() { // Draw image at original size ctx.drawImage(img, 50, 50); // Draw image with custom size ctx.drawImage(img, 200, 50, 100, 80); // Draw part of image (source clipping) ctx.drawImage( img, 0, 0, 50, 50, // source rectangle 350, 50, 100, 100 // destination rectangle ); // Transformations ctx.save(); // Save current state // Translation ctx.translate(150, 200); ctx.fillStyle = '#ff6b6b'; ctx.fillRect(0, 0, 50, 50); // Rotation (around translated origin) ctx.rotate(Math.PI / 4); // 45 degrees ctx.fillStyle = '#4ecdc4'; ctx.fillRect(60, 0, 50, 50); // Scale ctx.scale(1.5, 0.5); // Width 1.5x, height 0.5x ctx.fillStyle = '#45b7d1'; ctx.fillRect(80, 20, 50, 50); ctx.restore(); // Restore previous state // Matrix transformation ctx.setTransform(1, 0.2, 0.3, 1, 400, 200); ctx.fillStyle = '#f7b731'; ctx.fillRect(0, 0, 80, 60); // Reset transformation ctx.setTransform(1, 0, 0, 1, 0, 0); }; </script>
Animation Example
<canvas id="animation" width="600" height="300"></canvas> <button onclick="startAnimation()">Start Animation</button> <button onclick="stopAnimation()">Stop Animation</button> <script> const canvas = document.getElementById('animation'); const ctx = canvas.getContext('2d'); let animationId; let balls = []; // Ball object constructor function Ball(x, y, dx, dy, radius, color) { this.x = x; this.y = y; this.dx = dx; // velocity x this.dy = dy; // velocity y this.radius = radius; this.color = color; this.draw = function() { ctx.beginPath(); ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI); ctx.fillStyle = this.color; ctx.fill(); }; this.update = function() { // Bounce off walls if (this.x + this.radius > canvas.width || this.x - this.radius < 0) { this.dx = -this.dx; } if (this.y + this.radius > canvas.height || this.y - this.radius < 0) { this.dy = -this.dy; } // Update position this.x += this.dx; this.y += this.dy; this.draw(); }; } // Create balls function initBalls() { balls = []; const colors = ['#ff6b6b', '#4ecdc4', '#45b7d1', '#f7b731', '#5f27cd']; for (let i = 0; i < 5; i++) { const radius = Math.random() * 20 + 10; const x = Math.random() * (canvas.width - radius * 2) + radius; const y = Math.random() * (canvas.height - radius * 2) + radius; const dx = (Math.random() - 0.5) * 4; const dy = (Math.random() - 0.5) * 4; const color = colors[Math.floor(Math.random() * colors.length)]; balls.push(new Ball(x, y, dx, dy, radius, color)); } } // Animation loop function animate() { // Clear canvas ctx.clearRect(0, 0, canvas.width, canvas.height); // Update and draw balls balls.forEach(ball => ball.update()); // Continue animation animationId = requestAnimationFrame(animate); } function startAnimation() { initBalls(); animate(); } function stopAnimation() { cancelAnimationFrame(animationId); } </script>
Canvas Applications
Graphics & Art
- Digital painting applications
- Interactive drawing tools
- Image filters and effects
- Photo editing interfaces
- Generative art and patterns
Data Visualization
- Custom charts and graphs
- Interactive dashboards
- Real-time data displays
- Network diagrams
- Scientific visualizations
Games & Animation
- 2D games and sprites
- Particle systems
- Physics simulations
- Interactive animations
- Game UI elements
Utilities & Tools
- Image processing
- QR code generators
- Digital signatures
- Color pickers
- Drawing tablets integration
Best Practices
✅ Do
- Set canvas size in HTML attributes
- Use requestAnimationFrame for smooth animations
- Save and restore context state when needed
- Optimize drawing operations for performance
- Provide fallback content for accessibility
- Use off-screen canvas for complex compositions
❌ Avoid
- Excessive redrawing in animations
- Drawing outside the canvas bounds
- Ignoring high-DPI display scaling
- Complex operations in animation loops
- Memory leaks from event listeners
- Blocking the main thread with heavy operations