Initialisieren
This commit is contained in:
74
components/coin-3d.tsx
Normal file
74
components/coin-3d.tsx
Normal file
@@ -0,0 +1,74 @@
|
||||
"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;
|
||||
Reference in New Issue
Block a user