repos
/ orchard main

orchard

mirror

Every site I host, in one repo, along with the Cloudflare Tunnel and Caddy that front them. It's all Go, Vite, and SQLite, and it runs on a desktop at home with nothing listening on an inbound port.

blogbuncaddycloudflare-tunneldockergogolanghomelabhtml-templatemonorepoself-hostedseosqlitestatic-sitetypstuptime-monitoringviteweb-analytics

1.2 KB · 44 lines · JavaScript Raw History
 1// The custom cursor, a dot tracking the pointer and a ring that grows over
 2// anything interactive. Positions are written in a requestAnimationFrame loop
 3// rather than in the mousemove handler, so a burst costs one layout per frame.
 4
 5export const initCursor = () => {
 6  const dot = document.querySelector(".cursor");
 7  const circle = document.querySelector(".cursor-circle");
 8  if (!dot || !circle) return;
 9
10  const pos = { x: 0, y: 0 };
11
12  document.addEventListener(
13    "mousemove",
14    (e) => {
15      pos.x = e.clientX;
16      pos.y = e.clientY;
17    },
18    { passive: true }
19  );
20
21  document.addEventListener(
22    "mouseover",
23    (e) => {
24      const target = e.target;
25      const interactive =
26        target.tagName === "BUTTON" ||
27        target.tagName === "A" ||
28        !!target.closest("a, button") ||
29        (target.classList && target.classList.contains("mouse-activate"));
30      circle.classList.toggle("is-active", interactive);
31    },
32    { passive: true }
33  );
34
35  const animate = () => {
36    const transform = `translate3d(${pos.x}px, ${pos.y}px, 0)`;
37    dot.style.transform = transform;
38    circle.style.transform = transform;
39    window.requestAnimationFrame(animate);
40  };
41
42  window.requestAnimationFrame(animate);
43};