Mountain: pause on click + figure 3x bigger
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
db7d7530f4
commit
badba0a9f7
1 changed files with 30 additions and 21 deletions
|
|
@ -59,6 +59,7 @@ const CARD_H = 128;
|
|||
|
||||
export default function MountainClimb() {
|
||||
const [step, setStep] = useState(-1);
|
||||
const [paused, setPaused] = useState(false);
|
||||
const sectionRef = useRef<HTMLDivElement>(null);
|
||||
const started = useRef(false);
|
||||
|
||||
|
|
@ -79,12 +80,12 @@ export default function MountainClimb() {
|
|||
return () => obs.disconnect();
|
||||
}, []);
|
||||
|
||||
// Advance one step every 1.6 s
|
||||
// Advance one step every 1.6 s — paused when user clicked
|
||||
useEffect(() => {
|
||||
if (step < 0 || step >= STEPS.length - 1) return;
|
||||
if (step < 0 || step >= STEPS.length - 1 || paused) return;
|
||||
const t = setTimeout(() => setStep((s) => s + 1), 1600);
|
||||
return () => clearTimeout(t);
|
||||
}, [step]);
|
||||
}, [step, paused]);
|
||||
|
||||
const atSummit = step === STEPS.length - 1;
|
||||
const wp = step >= 0 ? WP[step] : WP[0];
|
||||
|
|
@ -92,8 +93,8 @@ export default function MountainClimb() {
|
|||
// Card x: centred on person, clamped inside viewBox
|
||||
const rawCX = wp.x - CARD_W / 2;
|
||||
const cardX = Math.min(Math.max(rawCX, 8), VW - CARD_W - 8);
|
||||
// Card y: above figure head, clamped to top of viewBox
|
||||
const cardY = Math.max(wp.y - CARD_H - 58, 4);
|
||||
// Card y: above figure head (figure is 3× scaled → head at ~87 SVG units above foot)
|
||||
const cardY = Math.max(wp.y - CARD_H - 110, 4);
|
||||
|
||||
const replay = () => {
|
||||
started.current = true;
|
||||
|
|
@ -115,7 +116,12 @@ export default function MountainClimb() {
|
|||
</div>
|
||||
|
||||
{/* ── Mountain animation (md+) ── */}
|
||||
<div className="hidden md:block">
|
||||
<div
|
||||
className="hidden md:block"
|
||||
onClick={() => !atSummit && setPaused((p) => !p)}
|
||||
style={{ cursor: atSummit ? "default" : "pointer" }}
|
||||
title={paused ? "Klicken um fortzusetzen" : "Klicken zum Pausieren"}
|
||||
>
|
||||
<svg
|
||||
viewBox={`0 0 ${VW} ${VH}`}
|
||||
className="w-full"
|
||||
|
|
@ -152,27 +158,23 @@ export default function MountainClimb() {
|
|||
transform={`translate(${wp.x}, ${wp.y}) rotate(${wp.lean})`}
|
||||
style={{ transition: "transform 0.75s cubic-bezier(0.4,0.2,0.2,1)" }}
|
||||
>
|
||||
{/* Inner group — receives bounce animation at summit */}
|
||||
{/* Inner group — 3× scale + bounce at summit */}
|
||||
<g
|
||||
transform="scale(3)"
|
||||
className={atSummit ? "mc-bounce" : ""}
|
||||
style={{ transformBox: "fill-box", transformOrigin: "50% 100%" }}
|
||||
>
|
||||
{/* Head */}
|
||||
<circle cx="0" cy="-29" r="7.5" fill="none" stroke="#4f46e5" strokeWidth="1.5" />
|
||||
{/* Body */}
|
||||
<line x1="0" y1="-21" x2="0" y2="-3" stroke="#4f46e5" strokeWidth="1.5" strokeLinecap="round" />
|
||||
{/* Left arm (down, holding mountain) */}
|
||||
<line x1="0" y1="-16" x2="-10" y2="-8" stroke="#4f46e5" strokeWidth="1.5" strokeLinecap="round" />
|
||||
{/* Right arm (raised) */}
|
||||
<line x1="0" y1="-16" x2="10" y2="-24" stroke="#4f46e5" strokeWidth="1.5" strokeLinecap="round" />
|
||||
{/* Legs */}
|
||||
<line x1="0" y1="-3" x2="-7" y2="10" stroke="#4f46e5" strokeWidth="1.5" strokeLinecap="round" />
|
||||
<line x1="0" y1="-3" x2="7" y2="10" stroke="#4f46e5" strokeWidth="1.5" strokeLinecap="round" />
|
||||
{/* strokeWidth 0.5 = visually 1.5 after scale(3) */}
|
||||
<circle cx="0" cy="-29" r="7.5" fill="none" stroke="#4f46e5" strokeWidth="0.5" />
|
||||
<line x1="0" y1="-21" x2="0" y2="-3" stroke="#4f46e5" strokeWidth="0.5" strokeLinecap="round" />
|
||||
<line x1="0" y1="-16" x2="-10" y2="-8" stroke="#4f46e5" strokeWidth="0.5" strokeLinecap="round" />
|
||||
<line x1="0" y1="-16" x2="10" y2="-24" stroke="#4f46e5" strokeWidth="0.5" strokeLinecap="round" />
|
||||
<line x1="0" y1="-3" x2="-7" y2="10" stroke="#4f46e5" strokeWidth="0.5" strokeLinecap="round" />
|
||||
<line x1="0" y1="-3" x2="7" y2="10" stroke="#4f46e5" strokeWidth="0.5" strokeLinecap="round" />
|
||||
|
||||
{/* Flag — appears at summit, attached to raised right arm */}
|
||||
{atSummit && (
|
||||
<g className="mc-fade-in" transform="translate(9, -25)">
|
||||
<line x1="0" y1="0" x2="0" y2="-22" stroke="#6366f1" strokeWidth="1.5" strokeLinecap="round" />
|
||||
<line x1="0" y1="0" x2="0" y2="-22" stroke="#6366f1" strokeWidth="0.5" strokeLinecap="round" />
|
||||
<polygon points="0,-22 18,-15 0,-8" fill="#6366f1" />
|
||||
</g>
|
||||
)}
|
||||
|
|
@ -188,7 +190,7 @@ export default function MountainClimb() {
|
|||
x1={cardX + CARD_W / 2}
|
||||
y1={cardY + CARD_H}
|
||||
x2={wp.x}
|
||||
y2={wp.y - 37}
|
||||
y2={wp.y - 90}
|
||||
stroke="#c7d2fe"
|
||||
strokeWidth="1"
|
||||
strokeDasharray="4 3"
|
||||
|
|
@ -236,6 +238,13 @@ export default function MountainClimb() {
|
|||
)}
|
||||
</svg>
|
||||
|
||||
{/* Pause hint */}
|
||||
{step >= 0 && !atSummit && (
|
||||
<p className="text-center text-xs text-slate-400 mt-2 select-none">
|
||||
{paused ? "▶ Klicken zum Fortsetzen" : "⏸ Klicken zum Pausieren"}
|
||||
</p>
|
||||
)}
|
||||
|
||||
{/* Replay button */}
|
||||
{atSummit && (
|
||||
<div className="text-center mt-4">
|
||||
|
|
|
|||
Reference in a new issue