Playground

SVG Cursor

Thu, 18 Apr 2024

HTML
1<svg class="trail">
2  <path
3    fill="none"
4    stroke="black"
5    stroke-width="8"
6    stroke-linecap="round"
7    stroke-linejoin="round"
8  />
9</svg>
CSS
1* {
2  cursor: none;
3}
4
5.trail {
6  position: fixed;
7  inset: 0;
8}
JavaScript
1const PARAMS = {
2  segments: 100,
3  stiffness: 0.1,
4};
5
6const svg = document.querySelector("svg.trail");
7const path = svg?.querySelector("path");
8
9let points = [];
10let mouse = {};
11
12const move = (event) => {
13  const x = event.clientX;
14  const y = event.clientY;
15
16  mouse.x = x;
17  mouse.y = y;
18
19  if (points.length === 0) {
20    for (let i = 0; i < PARAMS.segments; i++) {
21      points.push({
22        x: mouse.x,
23        y: mouse.y,
24      });
25    }
26  }
27};
28
29const loop = () => {
30  let px = mouse.x;
31  let py = mouse.y;
32
33  points.forEach((p, index) => {
34    p.x = px;
35    p.y = py;
36
37    let n = points[index + 1];
38
39    if (n) {
40      px = px - (p.x - n.x) * PARAMS.stiffness;
41      py = py - (p.y - n.y) * PARAMS.stiffness;
42    }
43  });
44
45  points.length &&
46    path?.setAttribute(
47      "d",
48      `M ${points.map((p) => `${p.x} ${p.y}`).join(` L `)} M ${mouse.x} ${mouse.y}`,
49    );
50
51  requestAnimationFrame(loop);
52};
53
54const resize = () => {
55  const ww = window.innerWidth;
56  const wh = window.innerHeight;
57
58  svg.style.width = ww + "px";
59  svg.style.height = wh + "px";
60  svg.setAttribute("viewBox", `0 0 ${ww} ${wh}`);
61};
62
63document.addEventListener("mousemove", move);
64window.addEventListener("resize", resize);
65
66loop();
67resize();

Vittorio Retrivi

Overview
Let’s Get In Touch-Let’s Get In Touch-Let’s Get In Touch-Let’s Get In Touch-Let’s Get In Touch-Let’s Get In Touch-Let’s Get In Touch-Let’s Get In Touch-Let’s Get In Touch-Let’s Get In Touch-Let’s Get In Touch-Let’s Get In Touch-