mirror of
https://github.com/Patiun/com.gregkilmer.www.git
synced 2026-11-08 04:08:24 +00:00
header pass
This commit is contained in:
@@ -23,22 +23,21 @@ import { useEffect, useRef } from 'react';
|
||||
interface Props {
|
||||
/** Show the canvas star field. Off on interest pages for a calmer feel. */
|
||||
particles?: boolean;
|
||||
/** Tailwind/className passthrough for the root. */
|
||||
className?: string;
|
||||
/**
|
||||
* Opt-in View Transition name. Unset by default. The View Transitions API
|
||||
* requires this name to be UNIQUE within a page snapshot, so the page must
|
||||
* opt in on AT MOST ONE field (typically the hero). Applied via the `.vt-sky`
|
||||
* CSS class rather than React's inline style to avoid an SSR/hydration
|
||||
* attribute mismatch.
|
||||
* Tailwind/className passthrough for the root. The CALL SITE (in .astro) is
|
||||
* responsible for including `vt-sky` here when this element should carry the
|
||||
* `view-transition-name: sky` morph. We intentionally do NOT compute the
|
||||
* transition class inside this React component: any conditional className
|
||||
* interpolation causes a server/client hydration attribute mismatch under
|
||||
* Astro's client:idle. Passing a static, fully-formed string guarantees the
|
||||
* server-rendered and hydrated class attributes are byte-identical.
|
||||
*/
|
||||
transitionName?: 'sky';
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export default function AnimatedBackground({
|
||||
particles = true,
|
||||
className = '',
|
||||
transitionName,
|
||||
}: Props) {
|
||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||
|
||||
@@ -135,11 +134,12 @@ export default function AnimatedBackground({
|
||||
const cy = 0;
|
||||
const maxR = Math.sqrt(cx * cx + height * height) + 40;
|
||||
|
||||
// One star per ~3200 px^2 of the disk, capped for perf (~14% anchors).
|
||||
// Dense starfield: ~3x the previous density for a richly star-packed sky.
|
||||
// One star per ~1100 px^2 of the disk, capped for perf (~15% anchors).
|
||||
const diskArea = Math.PI * maxR * maxR;
|
||||
const count = Math.min(520, Math.floor(diskArea / 3200));
|
||||
const count = Math.min(1500, Math.floor(diskArea / 1100));
|
||||
stars = Array.from({ length: count }, (_, i) => {
|
||||
const anchor = i % 7 === 0; // ~14% anchors -> dense constellation backbone
|
||||
const anchor = i % 7 === 0; // ~15% anchors -> dense constellation backbone
|
||||
// Uniform-ish distribution across the disk via sqrt on radius.
|
||||
const rr = maxR * Math.sqrt(Math.random());
|
||||
const a = Math.random() * Math.PI * 2;
|
||||
@@ -321,11 +321,9 @@ export default function AnimatedBackground({
|
||||
};
|
||||
}, [particles]);
|
||||
|
||||
const skyClass = transitionName === 'sky' ? 'vt-sky' : '';
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`pointer-events-none absolute inset-0 -z-10 overflow-hidden ${skyClass} ${className}`}
|
||||
className={`pointer-events-none absolute inset-0 -z-10 overflow-hidden ${className}`}
|
||||
aria-hidden="true"
|
||||
>
|
||||
{/* Layer 1: night-sky gradient — deep blue, darker at top, lighter toward
|
||||
|
||||
Reference in New Issue
Block a user