Canvas API for graphics and animations

Alex Chang Feb 2026
1 tab
// Get canvas and context
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');

// 1. Basic shapes
// Rectangle (filled)
ctx.fillStyle = '#4285f4';
ctx.fillRect(10, 10, 100, 80); // x, y, width, height

// Rectangle (outline)
ctx.strokeStyle = '#ea4335';
ctx.lineWidth = 3;
ctx.strokeRect(130, 10, 100, 80);

// Clear rectangle
ctx.clearRect(15, 15, 90, 70);

// 2. Paths
ctx.beginPath();
ctx.moveTo(250, 50);
ctx.lineTo(300, 100);
ctx.lineTo(250, 150);
ctx.closePath();
ctx.fillStyle = '#34a853';
ctx.fill();

// 3. Circles and arcs
ctx.beginPath();
ctx.arc(380, 80, 40, 0, Math.PI * 2); // x, y, radius, startAngle, endAngle
ctx.fillStyle = '#fbbc04';
ctx.fill();

// Arc (partial circle)
ctx.beginPath();
ctx.arc(480, 80, 40, 0, Math.PI); // Half circle
ctx.strokeStyle = '#ea4335';
ctx.lineWidth = 2;
ctx.stroke();

// 4. Text
ctx.font = '24px Arial';
ctx.fillStyle = '#000';
ctx.fillText('Hello Canvas!', 10, 200);

ctx.strokeText('Outlined Text', 10, 240);

// Text alignment
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText('Centered', canvas.width / 2, canvas.height / 2);

// 5. Gradients
// Linear gradient
const linearGrad = ctx.createLinearGradient(0, 0, 200, 0);
linearGrad.addColorStop(0, '#4285f4');
linearGrad.addColorStop(1, '#34a853');

ctx.fillStyle = linearGrad;
ctx.fillRect(10, 300, 200, 100);

// Radial gradient
const radialGrad = ctx.createRadialGradient(330, 350, 10, 330, 350, 50);
radialGrad.addColorStop(0, '#fff');
radialGrad.addColorStop(1, '#4285f4');

ctx.fillStyle = radialGrad;
ctx.beginPath();
ctx.arc(330, 350, 50, 0, Math.PI * 2);
ctx.fill();

// 6. Images
const img = new Image();
img.onload = () => {
  // Draw image
  ctx.drawImage(img, 10, 450);

  // Scale image
  ctx.drawImage(img, 210, 450, 100, 100);

  // Crop and scale
  ctx.drawImage(
    img,
    0, 0, 100, 100, // source x, y, width, height
    410, 450, 80, 80 // dest x, y, width, height
  );
};
img.src = '/path/to/image.jpg';

// 7. Transformations
ctx.save(); // Save current state

ctx.translate(100, 100);
ctx.rotate(Math.PI / 4); // 45 degrees
ctx.scale(1.5, 1.5);

ctx.fillStyle = '#ea4335';
ctx.fillRect(0, 0, 50, 50);

ctx.restore(); // Restore saved state

// 8. Compositing
ctx.globalAlpha = 0.5; // Transparency
ctx.globalCompositeOperation = 'multiply';

// 9. Shadows
ctx.shadowColor = 'rgba(0, 0, 0, 0.5)';
ctx.shadowBlur = 10;
ctx.shadowOffsetX = 5;
ctx.shadowOffsetY = 5;

ctx.fillStyle = '#4285f4';
ctx.fillRect(500, 300, 100, 80);

// Reset shadows
ctx.shadowColor = 'transparent';

// 10. Animation with requestAnimationFrame
let x = 0;
const ballRadius = 20;
const ballColor = '#4285f4';

function animate() {
  // Clear canvas
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  // Draw ball
  ctx.beginPath();
  ctx.arc(x, canvas.height - 100, ballRadius, 0, Math.PI * 2);
  ctx.fillStyle = ballColor;
  ctx.fill();

  // Update position
  x += 2;
  if (x > canvas.width + ballRadius) {
    x = -ballRadius;
  }

  requestAnimationFrame(animate);
}

animate();

// 11. Interactive canvas
canvas.addEventListener('click', (e) => {
  const rect = canvas.getBoundingClientRect();
  const x = e.clientX - rect.left;
  const y = e.clientY - rect.top;

  // Draw circle at click position
  ctx.beginPath();
  ctx.arc(x, y, 10, 0, Math.PI * 2);
  ctx.fillStyle = '#ea4335';
  ctx.fill();
});

// 12. Particle system
class Particle {
  constructor(x, y) {
    this.x = x;
    this.y = y;
    this.vx = (Math.random() - 0.5) * 4;
    this.vy = (Math.random() - 0.5) * 4;
    this.radius = Math.random() * 3 + 1;
    this.alpha = 1;
  }

  update() {
    this.x += this.vx;
    this.y += this.vy;
    this.alpha -= 0.01;
  }

  draw(ctx) {
    ctx.save();
    ctx.globalAlpha = this.alpha;
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
    ctx.fillStyle = '#4285f4';
    ctx.fill();
    ctx.restore();
  }

  isDead() {
    return this.alpha <= 0;
  }
}

const particles = [];

canvas.addEventListener('mousemove', (e) => {
  const rect = canvas.getBoundingClientRect();
  const x = e.clientX - rect.left;
  const y = e.clientY - rect.top;

  for (let i = 0; i < 3; i++) {
    particles.push(new Particle(x, y));
  }
});

function animateParticles() {
  ctx.fillStyle = 'rgba(255, 255, 255, 0.1)';
  ctx.fillRect(0, 0, canvas.width, canvas.height);

  for (let i = particles.length - 1; i >= 0; i--) {
    const particle = particles[i];
    particle.update();
    particle.draw(ctx);

    if (particle.isDead()) {
      particles.splice(i, 1);
    }
  }

  requestAnimationFrame(animateParticles);
}

animateParticles();
1 file · javascript Explain with highlit

The Canvas API provides a drawable bitmap surface for graphics. I use <canvas> elements with 2D rendering context via getContext('2d'). Drawing methods include fillRect(), strokeRect(), arc(), and lineTo(). The save() and restore() methods manage drawing state. Transformations like translate(), rotate(), and scale() modify coordinates. The requestAnimationFrame() function creates smooth animations. Image manipulation uses drawImage() and getImageData(). Canvas excels at games, charts, and dynamic graphics. Understanding canvas enables rich visual experiences.