75 lines
2.0 KiB
TypeScript
75 lines
2.0 KiB
TypeScript
"use client";
|
|
|
|
import { forwardRef } from "react";
|
|
|
|
type Coin3DProps = {
|
|
frontLabel: string;
|
|
backLabel: string;
|
|
/** Kantenlänge in px */
|
|
size?: number;
|
|
/** Endlos-Idle-Drehung (Hero) */
|
|
spin?: boolean;
|
|
/**
|
|
* Achse, um die die Münze rotiert. Bestimmt, wie die Rückseite
|
|
* vorgedreht wird, damit ihr Text lesbar bleibt.
|
|
* "x" = Flip um die X-Achse (Tool), "y" = Drehung um die Y-Achse (Hero).
|
|
*/
|
|
spinAxis?: "x" | "y";
|
|
className?: string;
|
|
};
|
|
|
|
/** Gestapelte Kreisscheiben erzeugen die Münzdicke. */
|
|
const EDGE_LAYERS = [-3, -2, -1, 0, 1, 2, 3];
|
|
|
|
/**
|
|
* Echte 3D-CSS-Münze. Der forwarded ref zeigt auf das rotierende
|
|
* Innen-Element, damit GSAP `rotationX` flippen kann.
|
|
*/
|
|
const Coin3D = forwardRef<HTMLDivElement, Coin3DProps>(function Coin3D(
|
|
{ frontLabel, backLabel, size = 168, spin = false, spinAxis = "x", className = "" },
|
|
ref,
|
|
) {
|
|
return (
|
|
<div
|
|
ref={ref}
|
|
className={`coin ${spin ? "animate-coin-spin" : ""} ${className}`}
|
|
style={{ width: size, height: size }}
|
|
>
|
|
{EDGE_LAYERS.map((z) => (
|
|
<div
|
|
key={z}
|
|
aria-hidden
|
|
className="coin-edge"
|
|
style={{ transform: `translateZ(${z}px)` }}
|
|
/>
|
|
))}
|
|
|
|
<div className="coin-face coin-face--front">
|
|
<div className="coin-engraving" aria-hidden />
|
|
<div className="coin-engraving coin-engraving--inner" aria-hidden />
|
|
<span className="coin-label" style={{ fontSize: size * 0.1 }}>
|
|
{frontLabel}
|
|
</span>
|
|
</div>
|
|
|
|
<div
|
|
className="coin-face coin-face--back"
|
|
style={{
|
|
transform:
|
|
spinAxis === "y"
|
|
? "rotateY(180deg) translateZ(4px)"
|
|
: "rotateX(180deg) translateZ(4px)",
|
|
}}
|
|
>
|
|
<div className="coin-engraving" aria-hidden />
|
|
<div className="coin-engraving coin-engraving--inner" aria-hidden />
|
|
<span className="coin-label" style={{ fontSize: size * 0.1 }}>
|
|
{backLabel}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
);
|
|
});
|
|
|
|
export default Coin3D;
|