From 7c0a0bbec29a4e98a2bd89b2ac972650100d2627 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sun, 25 Jan 2026 01:37:50 +0000 Subject: [PATCH] perf(FancyCursor): optimize mousemove handler with ticking pattern - Replaces the `cancelAnimationFrame` pattern with a boolean ticking flag to reduce function allocation and RAF overhead on high-frequency mousemove events. - Uses closure variables for coordinates to ensure the latest position is used in the animation frame. - Improves performance of the custom cursor on high-refresh-rate input devices. --- .jules/bolt.md | 3 +++ src/components/layout/FancyCursor.tsx | 32 ++++++++++++++++++--------- 2 files changed, 25 insertions(+), 10 deletions(-) create mode 100644 .jules/bolt.md diff --git a/.jules/bolt.md b/.jules/bolt.md new file mode 100644 index 0000000..a7efe75 --- /dev/null +++ b/.jules/bolt.md @@ -0,0 +1,3 @@ +## 2024-05-22 - Missing Scripts and Environment +**Learning:** The project lacks `lint` script in `package.json`. Running `pnpm lint` might invoke system tools (like Android Lint?) instead of failing or doing nothing useful. Always check `package.json` scripts first. +**Action:** Use specific commands like `pnpm exec tsc --noEmit` or `npx vitest` as discovered/documented, rather than assuming standard scripts exist. diff --git a/src/components/layout/FancyCursor.tsx b/src/components/layout/FancyCursor.tsx index 501d293..b839076 100644 --- a/src/components/layout/FancyCursor.tsx +++ b/src/components/layout/FancyCursor.tsx @@ -39,17 +39,29 @@ export const FancyCursor = memo(() => { updateCursorState(e.target as Element); }; - // The mouse move handler is throttled with requestAnimationFrame to ensure - // the animation is smooth and doesn't cause performance issues. + // Optimization: Use a ticking flag and closure variables to prevent + // excessive object creation and RAF churn during high-frequency events. + let ticking = false; + let clientX = 0; + let clientY = 0; + + const updateCursor = () => { + // The offset issue was caused by positioning the cursor's top-left corner + // at the mouse coordinates. To fix this, `translate(-50%, -50%)` is added. + // This shifts the cursor element by half its own width and height, + // which effectively centers it on the pointer without affecting the visuals. + cursor.style.transform = `translate3d(${clientX}px, ${clientY}px, 0) translate(-50%, -50%)`; + ticking = false; + }; + const handleMouseMove = (e: MouseEvent) => { - cancelAnimationFrame(animationFrameId); - animationFrameId = requestAnimationFrame(() => { - // The offset issue was caused by positioning the cursor's top-left corner - // at the mouse coordinates. To fix this, `translate(-50%, -50%)` is added. - // This shifts the cursor element by half its own width and height, - // which effectively centers it on the pointer without affecting the visuals. - cursor.style.transform = `translate3d(${e.clientX}px, ${e.clientY}px, 0) translate(-50%, -50%)`; - }); + clientX = e.clientX; + clientY = e.clientY; + + if (!ticking) { + animationFrameId = requestAnimationFrame(updateCursor); + ticking = true; + } }; // Using a passive event listener can improve scrolling performance.