ホバー
Canvas

Canvas Trail Hover

ホバーでマウスの軌跡がキャンバス上に光の線として残るエフェクト。

HTML
<div class="cth-wrap" id="cth-wrap">
  <canvas id="cth-canvas" width="280" height="160"></canvas>
  <div class="cth-content"><h3>Trail Effect</h3></div>
</div>
CSS
.cth-wrap {
  position: relative;
  width: 280px;
  height: 160px;
  border-radius: 16px;
  overflow: hidden;
  background: #0a0a0a;
  cursor: pointer;
}
#cth-canvas {
  position: absolute;
  inset: 0;
}
.cth-content {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: #a5b4fc;
}
.cth-content h3 { margin: 0; font-size: 18px; }
JavaScript
const wrap = document.getElementById('cth-wrap');
const canvas = document.getElementById('cth-canvas');
const ctx = canvas.getContext('2d');
let points = [];
wrap.addEventListener('mousemove', function(e) {
  const rect = wrap.getBoundingClientRect();
  points.push({ x: e.clientX - rect.left, y: e.clientY - rect.top, alpha: 1 });
  if (points.length > 50) points.shift();
});
function draw() {
  ctx.clearRect(0, 0, 280, 160);
  for (let i = 1; i < points.length; i++) {
    ctx.beginPath();
    ctx.moveTo(points[i-1].x, points[i-1].y);
    ctx.lineTo(points[i].x, points[i].y);
    ctx.strokeStyle = 'rgba(99,102,241,' + points[i].alpha + ')';
    ctx.lineWidth = 2;
    ctx.stroke();
    points[i].alpha -= 0.015;
  }
  points = points.filter(function(p) { return p.alpha > 0; });
  requestAnimationFrame(draw);
}
draw();