Skip to content

Commit

Permalink
refactor: DotGrid gesture logic using use-gesture library
Browse files Browse the repository at this point in the history
  • Loading branch information
hmerritt committed May 31, 2024
1 parent 580653c commit 95516b6
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 48 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"@tanstack/react-store": "^0.4.1",
"@tanstack/router-devtools": "^1.34.7",
"@tanstack/router-vite-plugin": "^1.34.8",
"@use-gesture/react": "^10.3.1",
"dayjs": "^1.11.11",
"lodash-es": "^4.17.21",
"plausible-tracker": "^0.3.9",
Expand Down
2 changes: 1 addition & 1 deletion scripts/bootstrap/version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import * as core from "./core";
/**
* Internal adrift version.
*/
export const adriftVersion = "0.11.502";
export const adriftVersion = "0.11.503";

/**
* Bumps the adrift `patch` version number using the total commit count.
Expand Down
79 changes: 32 additions & 47 deletions src/view/components/experimental/DotGrid.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { css } from "@linaria/atomic";
import { cx } from "@linaria/core";
import { RefObject, useCallback, useEffect, useRef } from "react";
import { useMove } from "@use-gesture/react";
import { RefObject, useCallback, useEffect, useRef, useState } from "react";

export type DotGridProps = JSX.IntrinsicElements["canvas"] & {
/** Container position. Use `fixed` for background usage */
Expand Down Expand Up @@ -41,8 +42,23 @@ export const DotGrid: React.FC<DotGridProps> = ({
...canvasProps
}) => {
const $canvas = useRef<HTMLCanvasElement>(null);
const mousePosition = useRef({ x: -1000, y: -1000 });
const animationFrameHandle = useRef(-1);
const mousePosition = useRef({ x: -1000, y: -1000 });

const getTargetToBind = () =>
refForMousePosition === "window"
? window
: refForMousePosition?.current || $canvas.current;
const [targetToBind, setTargetToBind] = useState(getTargetToBind());
const bind = useMove(
(state) => {
mousePosition.current.x = state?.xy?.[0];
mousePosition.current.y = state?.xy?.[1];
},
{
target: targetToBind
}
);

const resetAnimationFrame = () => {
if (animationFrameHandle.current !== -1) {
Expand Down Expand Up @@ -143,66 +159,35 @@ export const DotGrid: React.FC<DotGridProps> = ({
useEffect(() => {
if (!$canvas.current) return;

const trackMousePosition = (e: MouseEvent | TouchEvent) => {
if (!$canvas.current) return;

let x = mousePosition.current.x;
let y = mousePosition.current.y;

if (e.type === "mousemove") {
const native = e as MouseEvent;
x = native?.offsetX;
y = native?.offsetY;
if (refForMousePosition === "window") {
x = native?.clientX;
y = native?.clientY;
}
} else if (e.type === "touchmove") {
const native = e as TouchEvent;
const bcr = $canvas.current.getBoundingClientRect();
const touch = native?.touches?.[0] ?? native?.targetTouches?.[0];
x = touch.clientX - bcr.x;
y = touch.clientY - bcr.y;
if (refForMousePosition === "window") {
x = touch.clientX;
y = touch.clientY;
}
} else if (e.type === "mouseout" || e.type === "touchend") {
x = -1000;
y = -1000;
}

mousePosition.current.x = x;
mousePosition.current.y = y;
};
const $elForMousePosition =
refForMousePosition === "window"
? window
: refForMousePosition?.current || $canvas.current;
$elForMousePosition.addEventListener("mousemove", trackMousePosition);
$elForMousePosition.addEventListener("mouseout", trackMousePosition);
$elForMousePosition.addEventListener("touchmove", trackMousePosition);
$elForMousePosition.addEventListener("touchend", trackMousePosition);

setTargetToBind(getTargetToBind());
drawDotGrid();

if (reactToWindowResize) {
window.addEventListener("resize", drawDotGrid);
}

// Reset mouse position when off-screen
const resetMousePosition = () => {
setTimeout(() => {
mousePosition.current.x = -1000;
mousePosition.current.y = -1000;
}, 400);
};
window.addEventListener("touchend", resetMousePosition);
document.addEventListener("mouseleave", resetMousePosition);

return () => {
resetAnimationFrame();
window.removeEventListener("resize", drawDotGrid);
$elForMousePosition?.removeEventListener("mousemove", trackMousePosition);
$elForMousePosition?.removeEventListener("mouseout", trackMousePosition);
$elForMousePosition?.removeEventListener("touchmove", trackMousePosition);
$elForMousePosition?.removeEventListener("touchend", trackMousePosition);
window.removeEventListener("touchend", resetMousePosition);
document.removeEventListener("mouseleave", resetMousePosition);
};
}, [drawDotGrid, reactToWindowResize]);

return (
<canvas
{...canvasProps}
{...bind}
ref={$canvas}
className={cx(dotGrid, position === "fixed" && dotGridFixed)}
/>
Expand Down
19 changes: 19 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3680,6 +3680,24 @@ __metadata:
languageName: node
linkType: hard

"@use-gesture/core@npm:10.3.1":
version: 10.3.1
resolution: "@use-gesture/core@npm:10.3.1"
checksum: 6d1a00dcb39a28fb6aeb816e0bbf94a5cf8e466b912f4f6f35c2658f9b27a00ee7f0f488d736e6a54675deb8073bccdc3cb12a08b72a490a37a9f48fc4d86b2e
languageName: node
linkType: hard

"@use-gesture/react@npm:^10.3.1":
version: 10.3.1
resolution: "@use-gesture/react@npm:10.3.1"
dependencies:
"@use-gesture/core": 10.3.1
peerDependencies:
react: ">= 16.8.0"
checksum: 763ef5fe5e91715a20beac0d430b0ffd815f1ab761ffdd8a0c8352fa680411123b3855815a77b4e2d1018878ba515424f9daa863ea797c3dd089032fb539ec22
languageName: node
linkType: hard

"@vitejs/plugin-react@npm:^4.2.1":
version: 4.2.1
resolution: "@vitejs/plugin-react@npm:4.2.1"
Expand Down Expand Up @@ -3921,6 +3939,7 @@ __metadata:
"@types/node": ^20.12.13
"@types/react": ^18.3.3
"@types/react-dom": ^18.3.0
"@use-gesture/react": ^10.3.1
"@vitejs/plugin-react": ^4.3.0
"@vitest/coverage-v8": ^1.6.0
"@vitest/ui": ^1.6.0
Expand Down

0 comments on commit 95516b6

Please sign in to comment.