Skip to content

Commit 8af99c9

Browse files
committed
refactor(docs): refine homepage canvas motion
1 parent 7ee569d commit 8af99c9

4 files changed

Lines changed: 107 additions & 275 deletions

File tree

website/theme/components/CanvasGridEffect.tsx

Lines changed: 12 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ type CanvasGridEffectProps = {
44
cellSize?: number;
55
className?: string;
66
intensity?: number;
7+
interactionScope?: 'host' | 'page';
78
};
89

910
type GridWave = {
@@ -15,7 +16,6 @@ type GridWave = {
1516

1617
const GRID_TINT = [125, 182, 255] as const;
1718
const WAVE_LIFETIME = 1_650;
18-
const AMBIENT_WAVE_INTERVAL = 3_800;
1919

2020
function clamp(value: number, minimum: number, maximum: number) {
2121
return Math.min(Math.max(value, minimum), maximum);
@@ -32,6 +32,7 @@ export function CanvasGridEffect({
3232
cellSize = 34,
3333
className,
3434
intensity = 1,
35+
interactionScope = 'host',
3536
}: CanvasGridEffectProps) {
3637
const canvasRef = useRef<HTMLCanvasElement>(null);
3738

@@ -41,6 +42,10 @@ export function CanvasGridEffect({
4142
const context = canvas?.getContext('2d');
4243
if (!canvas || !host || !context) return undefined;
4344
const drawingContext = context;
45+
const interactionTarget =
46+
interactionScope === 'page'
47+
? (canvas.closest<HTMLElement>('.a3s-home') ?? host)
48+
: host;
4449

4550
const motionPreference = window.matchMedia(
4651
'(prefers-reduced-motion: reduce)',
@@ -53,7 +58,6 @@ export function CanvasGridEffect({
5358
let previousPointer = { x: -cellSize, y: -cellSize };
5459
let pointer = { x: -cellSize * 4, y: -cellSize * 4 };
5560
let waves: GridWave[] = [];
56-
let ambientWaveIndex = 0;
5761
let width = 1;
5862
let height = 1;
5963
let pixelRatio = 1;
@@ -160,20 +164,8 @@ export function CanvasGridEffect({
160164
scheduleDraw();
161165
};
162166

163-
const addAmbientWave = () => {
164-
if (reducedMotion || !isVisible || isPointerInside) return;
165-
const positions = [
166-
[0.72, 0.3],
167-
[0.28, 0.62],
168-
[0.58, 0.78],
169-
] as const;
170-
const [xRatio, yRatio] = positions[ambientWaveIndex % positions.length];
171-
ambientWaveIndex += 1;
172-
addWave(width * xRatio, height * yRatio, performance.now(), 0.58);
173-
};
174-
175167
const handlePointerMove = (event: PointerEvent) => {
176-
if (reducedMotion) return;
168+
if (reducedMotion || event.pointerType === 'touch') return;
177169
const bounds = host.getBoundingClientRect();
178170
const x = event.clientX - bounds.left;
179171
const y = event.clientY - bounds.top;
@@ -209,27 +201,22 @@ export function CanvasGridEffect({
209201
});
210202
intersectionObserver.observe(host);
211203
motionPreference.addEventListener('change', handleMotionChange);
212-
host.addEventListener('pointermove', handlePointerMove);
213-
host.addEventListener('pointerleave', handlePointerLeave);
204+
interactionTarget.addEventListener('pointermove', handlePointerMove);
205+
interactionTarget.addEventListener('pointerleave', handlePointerLeave);
214206
resize();
215207
if (!reducedMotion) {
216208
addWave(width * 0.72, height * 0.32, performance.now(), 0.62);
217209
}
218-
const ambientWaveTimer = window.setInterval(
219-
addAmbientWave,
220-
AMBIENT_WAVE_INTERVAL,
221-
);
222210

223211
return () => {
224212
window.cancelAnimationFrame(frame);
225-
window.clearInterval(ambientWaveTimer);
226213
resizeObserver.disconnect();
227214
intersectionObserver.disconnect();
228215
motionPreference.removeEventListener('change', handleMotionChange);
229-
host.removeEventListener('pointermove', handlePointerMove);
230-
host.removeEventListener('pointerleave', handlePointerLeave);
216+
interactionTarget.removeEventListener('pointermove', handlePointerMove);
217+
interactionTarget.removeEventListener('pointerleave', handlePointerLeave);
231218
};
232-
}, [cellSize, intensity]);
219+
}, [cellSize, intensity, interactionScope]);
233220

234221
return <canvas aria-hidden="true" className={className} ref={canvasRef} />;
235222
}

website/theme/components/HomeLayout.tsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1397,6 +1397,14 @@ export function HomeLayout() {
13971397
return (
13981398
<main className="a3s-home">
13991399
<PremiumInteractions />
1400+
<div className="a3s-global-grid" aria-hidden="true">
1401+
<CanvasGridEffect
1402+
cellSize={54}
1403+
className="a3s-global-grid-canvas"
1404+
intensity={0.68}
1405+
interactionScope="page"
1406+
/>
1407+
</div>
14001408
<section className="a3s-hero">
14011409
<div className="a3s-hero-copy">
14021410
<div className="a3s-eyebrow">
@@ -1428,11 +1436,6 @@ export function HomeLayout() {
14281436
<InstallSwitcher labels={labels} />
14291437
</div>
14301438
<div className="a3s-hero-visual">
1431-
<CanvasGridEffect
1432-
cellSize={42}
1433-
className="a3s-hero-canvas"
1434-
intensity={0.9}
1435-
/>
14361439
<RuntimeExecutionFlow labels={labels} />
14371440
</div>
14381441
</section>

website/theme/components/PremiumInteractions.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ export function PremiumInteractions() {
7070
clearActiveSurface();
7171
}
7272

73-
if (hero) {
73+
if (hero && target && hero.contains(target)) {
7474
const bounds = hero.getBoundingClientRect();
7575
const x = ((pointer.clientX - bounds.left) / bounds.width) * 100;
7676
const y = ((pointer.clientY - bounds.top) / bounds.height) * 100;
@@ -82,6 +82,9 @@ export function PremiumInteractions() {
8282
'--a3s-hero-y',
8383
`${Math.max(0, Math.min(y, 100))}%`,
8484
);
85+
} else {
86+
hero?.style.removeProperty('--a3s-hero-x');
87+
hero?.style.removeProperty('--a3s-hero-y');
8588
}
8689
};
8790

0 commit comments

Comments
 (0)