Canvas Animation Lanjutan — Web Animation

Canvas Animation Lanjutan Canvas 2D API memberikan kontrol piksel penuh untuk animasi — cocok untuk game, data visualisasi, efek partikel, dan animasi yang tida

Canvas Animation Lanjutan

Canvas 2D API memberikan kontrol piksel penuh untuk animasi — cocok untuk game, data visualisasi, efek partikel, dan animasi yang tidak mungkin dilakukan hanya dengan DOM/CSS.

Konsep Dasar Canvas Loop

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

// Pastikan resolusi tajam di layar Retina
const dpr = window.devicePixelRatio || 1;
canvas.width = canvas.offsetWidth * dpr;
canvas.height = canvas.offsetHeight * dpr;
ctx.scale(dpr, dpr);

let animationId;

function animate(timestamp) {
  // 1. Bersihkan frame sebelumnya
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  // 2. Update state
  update(timestamp);

  // 3. Gambar semua objek
  draw();

  // 4. Minta frame berikutnya
  animationId = requestAnimationFrame(animate);
}

// Mulai loop
animationId = requestAnimationFrame(animate);

// Bersihkan saat komponen unmount
function stop() {
  cancelAnimationFrame(animationId);
}

Sistem Partikel

class Particle {
  constructor(x, y) {
    this.x = x;
    this.y = y;
    this.vx = (Math.random() - 0.5) * 4; // kecepatan horizontal
    this.vy = (Math.random() - 0.5) * 4; // kecepatan vertikal
    this.life = 1;                         // opacity (1 = penuh)
    this.decay = Math.random() * 0.02 + 0.005;
    this.radius = Math.random() * 4 + 2;
    this.color = \`hsl(${Math.random() * 60 + 20}, 90%, 60%)\`;
  }

  update() {
    this.x += this.vx;
    this.y += this.vy;
    this.vy += 0.1; // gravitasi
    this.life -= this.decay;
  }

  draw(ctx) {
    ctx.save();
    ctx.globalAlpha = this.life;
    ctx.fillStyle = this.color;
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
    ctx.fill();
    ctx.restore();
  }

  isAlive() { return this.life > 0; }
}

// Sistem partikel
const particles = [];

function update() {
  // Spawn partikel baru
  if (Math.random() < 0.3) {
    particles.push(new Particle(canvas.width / 2, canvas.height / 2));
  }

  // Update & hapus partikel yang sudah mati
  for (let i = particles.length - 1; i >= 0; i--) {
    particles[i].update();
    if (!particles[i].isAlive()) particles.splice(i, 1);
  }
}

function draw() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  particles.forEach(p => p.draw(ctx));
}

Teknik Optimasi Canvas

// 1. Offscreen canvas — render di background, blit ke layar
const offscreen = document.createElement('canvas');
const offCtx = offscreen.getContext('2d');

// Render heavy graphics ke offscreen
offCtx.drawImage(complexShape, 0, 0);

// Blit ke main canvas (sangat cepat)
ctx.drawImage(offscreen, 0, 0);

// 2. Batching draw calls
// BURUK: ganti style setiap objek
objects.forEach(obj => {
  ctx.fillStyle = obj.color; // state change tiap iterasi
  ctx.fillRect(obj.x, obj.y, obj.w, obj.h);
});

// BAIK: kelompokkan berdasarkan style
const byColor = groupBy(objects, 'color');
for (const [color, group] of Object.entries(byColor)) {
  ctx.fillStyle = color; // state change sekali per warna
  ctx.beginPath();
  group.forEach(obj => ctx.rect(obj.x, obj.y, obj.w, obj.h));
  ctx.fill();
}

// 3. Caching path kompleks
const cachedPath = new Path2D();
cachedPath.arc(0, 0, 50, 0, Math.PI * 2);
// Reuse path di setiap frame
ctx.fill(cachedPath);

Efek Visual Canvas

// Trail effect — jangan clearRect sepenuhnya
ctx.fillStyle = 'rgba(0, 0, 0, 0.1)'; // semi-transparent overlay
ctx.fillRect(0, 0, canvas.width, canvas.height);

// Glow effect dengan shadow
ctx.shadowColor = '#3b82f6';
ctx.shadowBlur = 20;
ctx.fillStyle = '#60a5fa';
ctx.beginPath();
ctx.arc(x, y, 5, 0, Math.PI * 2);
ctx.fill();
ctx.shadowBlur = 0; // reset setelahnya

// Gradient animasi
const gradient = ctx.createRadialGradient(x, y, 0, x, y, 100);
gradient.addColorStop(0, 'rgba(59, 130, 246, 0.8)');
gradient.addColorStop(1, 'rgba(59, 130, 246, 0)');
ctx.fillStyle = gradient;
ctx.fillRect(x - 100, y - 100, 200, 200);

Canvas memberikan kebebasan total untuk animasi — dari simulasi fisika hingga efek visual yang tidak mungkin dilakukan dengan DOM. Kuncinya adalah optimasi loop dan batching draw calls.