javascript 217 lines · 1 tab

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.


Related snips

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Semantic HTML Example</title>

Semantic HTML5 elements and accessibility best practices

html html5 semantics
by Alex Chang 2 tabs
javascript
// Creating a Promise
const myPromise = new Promise((resolve, reject) => {
  const success = true;

  setTimeout(() => {
    if (success) {

Promises and async/await patterns for asynchronous JavaScript

javascript promises async-await
by Alex Chang 1 tab
javascript
import { Controller } from "@hotwired/stimulus"
import Mousetrap from "mousetrap"

export default class extends Controller {
  connect() {
    // Global shortcuts

Keyboard shortcuts with Stimulus and Mousetrap

stimulus javascript ux
by Jordan Lee 2 tabs
javascript
// Basic event listener
const button = document.getElementById('myButton');

button.addEventListener('click', function(event) {
  console.log('Button clicked!');
  console.log('Event type:', event.type);

Event handling and event delegation patterns in JavaScript

javascript events event-delegation
by Alex Chang 1 tab
javascript
// Basic GET request
fetch('https://api.example.com/users')
  .then(response => {
    console.log('Status:', response.status);
    console.log('OK:', response.ok);
    return response.json();

Fetch API for HTTP requests and AJAX communication

javascript fetch api
by Alex Chang 1 tab
erb
<turbo-stream action="set_title">
  <template><%= "Inbox (#{@unread_count})" %></template>
</turbo-stream>

Turbo Streams: update document title with a custom action

rails hotwire turbo
by Henry Kim 2 tabs

Share this code

Here's the card — post it anywhere.

Canvas API for graphics and animations — share card
Link copied