Lebensuhr clock: show the matching time under each age, plus 00/06/12/18 ring markers

The clock face only had age numbers — no way to tell which time on
the dial each one corresponded to. Added the matching time as a
second line under each age, and hour markers at 00/06/12/18 on the
ring itself so the dial reads as an actual 24h clock, not just an
abstract circle.
This commit is contained in:
Marco
2026-08-26 15:44:24 +00:00
parent af5956848b
commit 76d59a5682
+42 -27
View File
@@ -198,44 +198,58 @@ export default function LebensuhrPage() {
{/* Decorative companion to the table below, not a replacement for
it (a version that tried to carry the actual Alter/Uhrzeit
pairs on its own read ambiguous — see the table's own
comment) — just the 8 ages plotted at their proportional
clock position, so the "24 Stunden" framing above has an
actual clock to look at. Coordinates are hand-computed
(evenly spaced every 40°, since age/90 and time/24 are the
same proportion), not derived from lebensuhrRows — if the
rows above ever change, these need updating too. */}
comment) — the 8 ages plotted at their proportional clock
position, each labeled with its matching time too (age alone
didn't make the time connection obvious), plus 00/06/12/18
markers on the ring itself so it reads as an actual 24h
clock. Coordinates are hand-computed (evenly spaced every
40°/2h, since age/90, time/24 and tick/12 are all the same
proportion, with -90° so age/hour 0 sits at the top), not
derived from lebensuhrRows — if the rows above ever change,
these need updating too. */}
<div className="flex justify-center py-2">
<svg viewBox="0 0 250 250" className="w-full max-w-[16rem] h-auto" aria-hidden="true">
<svg viewBox="0 0 250 250" className="w-full max-w-[17rem] h-auto" aria-hidden="true">
<circle cx="125" cy="125" r="100" stroke="var(--color-border)" strokeWidth="1.5" fill="none" />
{[0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330].map((deg) => {
{[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11].map((h) => {
const deg = (h / 12) * 360 - 90;
const rad = (deg * Math.PI) / 180;
const x1 = 125 + 92 * Math.cos(rad), y1 = 125 + 92 * Math.sin(rad);
const major = h % 3 === 0;
const rIn = major ? 88 : 92;
const x1 = 125 + rIn * Math.cos(rad), y1 = 125 + rIn * Math.sin(rad);
const x2 = 125 + 100 * Math.cos(rad), y2 = 125 + 100 * Math.sin(rad);
return <line key={deg} x1={x1} y1={y1} x2={x2} y2={y2} stroke="var(--color-border)" strokeWidth="1.5" />;
return <line key={h} x1={x1} y1={y1} x2={x2} y2={y2} stroke="var(--color-border)" strokeWidth={major ? 2 : 1.5} />;
})}
{/* 00/06/12/18 — the ring's own hour markers, so the age
labels below have a time scale to read against. */}
{([
[10, 175.1, 65.2, 200.8, 34.6, "start"],
[20, 201.8, 111.5, 241.2, 104.5, "start"],
[30, 192.5, 164.0, 227.2, 184.0, "start"],
[40, 151.7, 198.3, 165.4, 235.9, "start"],
[50, 98.3, 198.3, 84.6, 235.9, "end"],
[60, 57.5, 164.0, 22.8, 184.0, "end"],
[70, 48.2, 111.5, 8.8, 104.5, "end"],
[80, 74.9, 65.2, 49.2, 34.6, "end"],
] as [number, number, number, number, number, "start" | "end"][]).map(([age, dx, dy, lx, ly, anchor]) => (
[0, "00", 125, 12, "middle"],
[3, "06", 238, 125, "start"],
[6, "12", 125, 238, "middle"],
[9, "18", 12, 125, "end"],
] as [number, string, number, number, "start" | "middle" | "end"][]).map(([h, label, x, y, anchor]) => (
<text key={h} x={x} y={y} textAnchor={anchor} dominantBaseline="middle" className="fill-text-muted" style={{ fontSize: 10 }}>
{label}
</text>
))}
{([
[10, "02:40", 175.1, 65.2, 200.8, 34.6, "start"],
[20, "05:20", 201.8, 111.5, 241.2, 104.5, "start"],
[30, "08:00", 192.5, 164.0, 227.2, 184.0, "start"],
[40, "10:40", 151.7, 198.3, 165.4, 235.9, "start"],
[50, "13:20", 98.3, 198.3, 84.6, 235.9, "end"],
[60, "16:00", 57.5, 164.0, 22.8, 184.0, "end"],
[70, "18:40", 48.2, 111.5, 8.8, 104.5, "end"],
[80, "21:20", 74.9, 65.2, 49.2, 34.6, "end"],
] as [number, string, number, number, number, number, "start" | "end"][]).map(([age, time, dx, dy, lx, ly, anchor]) => (
<g key={age}>
<line x1={dx} y1={dy} x2={lx} y2={ly} stroke="var(--color-border)" strokeWidth="1" />
<circle cx={dx} cy={dy} r="4" fill="var(--color-brand)" />
<text
x={lx}
y={ly}
textAnchor={anchor}
dominantBaseline="middle"
className="fill-text-muted"
style={{ fontSize: 12, fontWeight: 600 }}
>
<text x={lx} y={ly} textAnchor={anchor} dominantBaseline="middle" className="fill-text-primary" style={{ fontSize: 12, fontWeight: 700 }}>
{age}
</text>
<text x={lx} y={ly + 13} textAnchor={anchor} dominantBaseline="middle" className="fill-text-muted" style={{ fontSize: 9.5 }}>
{time}
</text>
</g>
))}
<text x="125" y="118" textAnchor="middle" className="fill-text-primary" style={{ fontFamily: "var(--font-caveat)", fontSize: 24 }}>
@@ -246,6 +260,7 @@ export default function LebensuhrPage() {
</text>
</svg>
</div>
<p className="text-center text-body-sm text-text-muted -mt-1">Alter (fett) und die passende Uhrzeit darunter.</p>
{/* Still a real table (explicit "Alter"/"Uhrzeit" headers — a
dot-on-a-line version tried here first read ambiguous