mirror of
https://github.com/Patiun/com.gregkilmer.www.git
synced 2026-11-08 04:08:24 +00:00
Animation Updates
This commit is contained in:
@@ -127,17 +127,19 @@ export default function AnimatedBackground({
|
||||
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
||||
|
||||
// Dense field tuned for ~40% constellation coverage on any slice. Stars
|
||||
// live in a sky disk larger than the viewport so rotation never reveals
|
||||
// an empty edge. Radius = distance to the far viewport corner.
|
||||
const cx = width / 2;
|
||||
const cy = height / 2;
|
||||
const maxR = Math.sqrt(cx * cx + cy * cy) + 40;
|
||||
// live in a sky disk large enough that rotation never reveals an empty
|
||||
// edge. The disk is centered on the PIVOT (the top-right corner) so the
|
||||
// whole field rotates around that corner like a star chart turning about
|
||||
// its corner mount; maxR reaches the far (bottom-left) corner.
|
||||
const cx = width;
|
||||
const cy = 0;
|
||||
const maxR = Math.sqrt(cx * cx + height * height) + 40;
|
||||
|
||||
// One star per ~4000 px^2 of the disk, capped for perf (~12% anchors).
|
||||
// One star per ~3200 px^2 of the disk, capped for perf (~14% anchors).
|
||||
const diskArea = Math.PI * maxR * maxR;
|
||||
const count = Math.min(420, Math.floor(diskArea / 4000));
|
||||
const count = Math.min(520, Math.floor(diskArea / 3200));
|
||||
stars = Array.from({ length: count }, (_, i) => {
|
||||
const anchor = i % 8 === 0; // ~12% anchors -> denser constellation backbone
|
||||
const anchor = i % 7 === 0; // ~14% 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;
|
||||
@@ -178,8 +180,9 @@ export default function AnimatedBackground({
|
||||
angle += ROT_SPEED * dt; // whole sky rotates together
|
||||
ctx.clearRect(0, 0, width, height);
|
||||
|
||||
const cx = width / 2;
|
||||
const cy = height / 2;
|
||||
// Pivot = top-right corner (matches the disk center used in resize()).
|
||||
const cx = width;
|
||||
const cy = 0;
|
||||
const cosA = Math.cos(angle);
|
||||
const sinA = Math.sin(angle);
|
||||
|
||||
|
||||
@@ -94,14 +94,16 @@ export default function ConstellationField({
|
||||
canvas.height = Math.floor(height * dpr);
|
||||
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
||||
|
||||
const cx = width / 2;
|
||||
const cy = height / 2;
|
||||
const maxR = Math.sqrt(cx * cx + cy * cy) + 40;
|
||||
// Tuned for ~40% constellation coverage. One star per ~6500 px^2, scaled
|
||||
// by density; ~14% anchors for a rich constellation backbone.
|
||||
// Pivot = top-right corner. The disk is centered there so the field
|
||||
// rotates around that corner; maxR reaches the far (bottom-left) corner.
|
||||
const cx = width;
|
||||
const cy = 0;
|
||||
const maxR = Math.sqrt(cx * cx + height * height) + 40;
|
||||
// Denser field for richer constellations. One star per ~4500 px^2, scaled
|
||||
// by density; ~15% anchors for a dense constellation backbone.
|
||||
const count = Math.min(
|
||||
260,
|
||||
Math.floor(((Math.PI * maxR * maxR) / 6500) * density),
|
||||
360,
|
||||
Math.floor(((Math.PI * maxR * maxR) / 4500) * density),
|
||||
);
|
||||
stars = Array.from({ length: count }, (_, i) => {
|
||||
const anchor = i % 7 === 0;
|
||||
@@ -143,8 +145,9 @@ export default function ConstellationField({
|
||||
angle += ROT_SPEED * dt;
|
||||
ctx.clearRect(0, 0, width, height);
|
||||
|
||||
const cx = width / 2;
|
||||
const cy = height / 2;
|
||||
// Pivot = top-right corner (matches the disk center used in resize()).
|
||||
const cx = width;
|
||||
const cy = 0;
|
||||
const cosA = Math.cos(angle);
|
||||
const sinA = Math.sin(angle);
|
||||
const project = (rx: number, ry: number): [number, number] => [
|
||||
|
||||
@@ -18,12 +18,21 @@ import { navGroups, siteIdentity } from '@lib/site';
|
||||
const path = Astro.url.pathname;
|
||||
const isActive = (href: string) =>
|
||||
href === '/' ? path === '/' : path === href || path.startsWith(href + '/');
|
||||
|
||||
interface Props {
|
||||
/** True on the Home page. When false, the nav carries the hero-sky transition
|
||||
* name so the Home hero can morph into / out of it (expand/collapse). */
|
||||
isHome?: boolean;
|
||||
}
|
||||
const { isHome = false } = Astro.props;
|
||||
// On non-Home pages the NavBar is the morph target for the Home hero.
|
||||
const heroSkyClass = isHome ? '' : 'vt-hero-sky';
|
||||
---
|
||||
|
||||
<header
|
||||
id="site-nav"
|
||||
data-nav
|
||||
class="fixed inset-x-0 top-0 z-50 transition-[background,box-shadow,border-color] duration-300"
|
||||
class:list={['fixed inset-x-0 top-0 z-50 transition-[background,box-shadow,border-color] duration-300', heroSkyClass]}
|
||||
>
|
||||
<div class="border-b border-transparent transition-colors duration-300" data-nav-inner>
|
||||
<nav
|
||||
|
||||
Reference in New Issue
Block a user