Nahorniak Templates
База референсів шаблонів і компонентів
Назад до шаблону · Davies - Personal Portfolio HTML Template
c104

canvas-cursor-trail

Курсор·Шаблон: Davies - Personal Portfolio HTML Template·Складність анімації: medium·Адаптивний: Так
canvas-cursor-trail

Файли-джерела

  • index.htmlcanvas#trail.cursor-trail

Бібліотеки

jquery

Summary

A full-viewport <canvas> rendered behind interactive content. On pointermove it pushes a new sample to a trail buffer and draws connecting line segments with a slowly cycling HSL stroke. Each frame fills the canvas with low-alpha black so old segments fade out smoothly. Gated to xl viewports (≥1200px) — mobile gets nothing.

HTML structure (minimal)

<canvas class="cursor-trail d-none d-xl-block" id="trail"></canvas>

Key SCSS tokens

.cursor-trail {
  position: fixed;
  inset: 0;
  z-index: 9999;
  pointer-events: none;
  width: 100%;
  height: 100%;
}

Animation logic

// assets/js/main.js — cursorTrail()
var canvas = document.getElementById('trail');
var ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

var points = [];
var hue = 140;

window.addEventListener('pointermove', (e) => {
  points.push({ x: e.clientX, y: e.clientY });
  if (points.length > 25) points.shift();
});

function draw() {
  ctx.fillStyle = 'rgba(0, 0, 0, 0.18)';
  ctx.fillRect(0, 0, canvas.width, canvas.height);

  ctx.strokeStyle = 'hsl(' + hue + ', 90%, 60%)';
  ctx.lineWidth = 2;
  ctx.lineCap = 'round';
  ctx.beginPath();
  for (var i = 1; i < points.length; i++) {
    ctx.moveTo(points[i - 1].x, points[i - 1].y);
    ctx.lineTo(points[i].x, points[i].y);
  }
  ctx.stroke();

  hue = (hue + 0.5) % 360;
  requestAnimationFrame(draw);
}
draw();
window.addEventListener('resize', () => {
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;
});

Notable details

  • Trail length is capped at ~25 points — older points are shifted out before drawing, so memory stays flat.
  • fillRect with rgba alpha 0.18 each frame creates the fade-out without needing per-pixel manipulation; the lower the alpha the longer the trail persists.
  • HSL hue cycles slowly (0.5° per frame) so the trail subtly shifts colour the longer the cursor moves — matches the "design-craft" tone of the template.
  • Bootstrap utility classes (d-none d-xl-block) gate the canvas at the markup level — JS doesn't even touch it on mobile.

Use when

  • Portfolios / showreel sites where you want a signature cursor effect without coupling it to GSAP or react-spring.
  • When the page background is dark — the rgba(0,0,0,0.18) fade only works on dark themes.

Caveats

  • The fade-out is hard-coded to black — on light backgrounds the trail won't fade visibly without changing fillStyle to white rgba.
  • pointermove events on touch devices fire too — if you re-enable below xl, expect unwanted trails on tap.
  • Canvas covers the full viewport with pointer-events: none; double-check that no descendant CSS bumps pointer-events back on by accident.