Persist dice state with localStorage and improve rendering layering.
Added functionality to save and load dice state (d1, d2, special) using localStorage for better user experience. Adjusted component styles to improve layering, ensure proper z-index for elements, and enhance 3D dice rendering.
This commit is contained in:
@@ -544,11 +544,29 @@ export default function App() {
|
|||||||
// ✅ 3 Würfel: 2x d6 + 1x Spezial (Häuser + Hilfkarte + Dunkles Deck)
|
// ✅ 3 Würfel: 2x d6 + 1x Spezial (Häuser + Hilfkarte + Dunkles Deck)
|
||||||
|
|
||||||
const DicePanel = ({ onRoll }) => {
|
const DicePanel = ({ onRoll }) => {
|
||||||
|
const LS_KEY = "hp_cluedo_dice_v1";
|
||||||
const [d1, setD1] = useState(4);
|
const [d1, setD1] = useState(4);
|
||||||
const [d2, setD2] = useState(2);
|
const [d2, setD2] = useState(2);
|
||||||
const [special, setSpecial] = useState("gryffindor");
|
const [special, setSpecial] = useState("gryffindor");
|
||||||
const [rolling, setRolling] = useState(false);
|
const [rolling, setRolling] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
try {
|
||||||
|
const raw = localStorage.getItem(LS_KEY);
|
||||||
|
if (!raw) return;
|
||||||
|
const parsed = JSON.parse(raw);
|
||||||
|
if (parsed?.d1) setD1(parsed.d1);
|
||||||
|
if (parsed?.d2) setD2(parsed.d2);
|
||||||
|
if (parsed?.special) setSpecial(parsed.special);
|
||||||
|
} catch {}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
try {
|
||||||
|
localStorage.setItem(LS_KEY, JSON.stringify({ d1, d2, special }));
|
||||||
|
} catch {}
|
||||||
|
}, [d1, d2, special]);
|
||||||
|
|
||||||
const specialFaces = ["gryffindor", "slytherin", "ravenclaw", "hufflepuff", "help", "dark"];
|
const specialFaces = ["gryffindor", "slytherin", "ravenclaw", "hufflepuff", "help", "dark"];
|
||||||
const randInt = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
|
const randInt = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
|
||||||
|
|
||||||
@@ -650,7 +668,7 @@ export default function App() {
|
|||||||
"radial-gradient(120% 120% at 20% 10%, rgba(255,255,255,0.12), rgba(0,0,0,0.35) 55%, rgba(0,0,0,0.62))",
|
"radial-gradient(120% 120% at 20% 10%, rgba(255,255,255,0.12), rgba(0,0,0,0.35) 55%, rgba(0,0,0,0.62))",
|
||||||
boxShadow: "0 18px 50px rgba(0,0,0,0.55), inset 0 0 0 1px rgba(255,255,255,0.06)",
|
boxShadow: "0 18px 50px rgba(0,0,0,0.55), inset 0 0 0 1px rgba(255,255,255,0.06)",
|
||||||
position: "relative",
|
position: "relative",
|
||||||
overflow: "hidden",
|
overflow: "visible", // ✅ WICHTIG für Fix 4
|
||||||
display: "grid",
|
display: "grid",
|
||||||
placeItems: "center",
|
placeItems: "center",
|
||||||
cursor: rolling ? "default" : "pointer",
|
cursor: rolling ? "default" : "pointer",
|
||||||
@@ -659,7 +677,6 @@ export default function App() {
|
|||||||
outline: "none",
|
outline: "none",
|
||||||
}}
|
}}
|
||||||
disabled={rolling}
|
disabled={rolling}
|
||||||
title={rolling ? "Rolling…" : "Roll"}
|
|
||||||
>
|
>
|
||||||
{/* inner ring */}
|
{/* inner ring */}
|
||||||
<div
|
<div
|
||||||
@@ -670,6 +687,7 @@ export default function App() {
|
|||||||
border: `1px solid ${ringColor}`,
|
border: `1px solid ${ringColor}`,
|
||||||
opacity: 0.85,
|
opacity: 0.85,
|
||||||
pointerEvents: "none",
|
pointerEvents: "none",
|
||||||
|
zIndex: 1,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -683,6 +701,7 @@ export default function App() {
|
|||||||
opacity: 0.9,
|
opacity: 0.9,
|
||||||
pointerEvents: "none",
|
pointerEvents: "none",
|
||||||
mixBlendMode: "screen",
|
mixBlendMode: "screen",
|
||||||
|
zIndex: 1,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -695,14 +714,19 @@ export default function App() {
|
|||||||
"linear-gradient(120deg, rgba(255,255,255,0.10) 0%, transparent 38%, transparent 70%, rgba(255,255,255,0.06) 100%)",
|
"linear-gradient(120deg, rgba(255,255,255,0.10) 0%, transparent 38%, transparent 70%, rgba(255,255,255,0.06) 100%)",
|
||||||
opacity: 0.8,
|
opacity: 0.8,
|
||||||
pointerEvents: "none",
|
pointerEvents: "none",
|
||||||
|
zIndex: 1,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{children}
|
{/* 👇 Cube kommt IMMER darüber */}
|
||||||
|
<div style={{ position: "relative", zIndex: 2 }}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* map value->cube rotation so that value face is FRONT
|
/* map value->cube rotation so that value face is FRONT
|
||||||
Face layout:
|
Face layout:
|
||||||
front=1, back=6, top=2, bottom=5, right=3, left=4
|
front=1, back=6, top=2, bottom=5, right=3, left=4
|
||||||
@@ -755,7 +779,7 @@ export default function App() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<DieShell ringColor="rgba(242,210,122,0.18)" rolling={rolling} onClick={onClick}>
|
<DieShell ringColor="rgba(242,210,122,0.18)" rolling={rolling} onClick={onClick}>
|
||||||
<div className="dieCubeWrap">
|
<div className="dieCubeWrap" style={{ zIndex: 2 }}>
|
||||||
<div
|
<div
|
||||||
className={`dieCube ${rolling ? "rolling" : ""}`}
|
className={`dieCube ${rolling ? "rolling" : ""}`}
|
||||||
style={{ "--rx": rot.rx, "--ry": rot.ry }}
|
style={{ "--rx": rot.rx, "--ry": rot.ry }}
|
||||||
|
|||||||
@@ -79,10 +79,11 @@ body {
|
|||||||
/* Dice overlay: under board slightly right */
|
/* Dice overlay: under board slightly right */
|
||||||
.diceOverlay {
|
.diceOverlay {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
overflow: visible;
|
||||||
bottom: 14px;
|
bottom: 14px;
|
||||||
right: 18px;
|
right: 18px;
|
||||||
width: 220px;
|
width: 220px;
|
||||||
pointer-events: none;
|
pointer-events: auto;
|
||||||
opacity: 0.98;
|
opacity: 0.98;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,6 +187,10 @@ body {
|
|||||||
transform: translateY(-3px) rotateX(8deg) rotateY(-10deg);
|
transform: translateY(-3px) rotateX(8deg) rotateY(-10deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.diceRow3d {
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
/* Cube container inside the button */
|
/* Cube container inside the button */
|
||||||
.dieCubeWrap {
|
.dieCubeWrap {
|
||||||
width: 44px;
|
width: 44px;
|
||||||
@@ -209,9 +214,10 @@ body {
|
|||||||
@keyframes cubeRoll {
|
@keyframes cubeRoll {
|
||||||
0% { transform: rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg)); }
|
0% { transform: rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg)); }
|
||||||
100% {
|
100% {
|
||||||
|
/* WICHTIG: NUR Vielfache von 360°, damit Ende = gleiche Orientierung */
|
||||||
transform:
|
transform:
|
||||||
rotateX(calc(var(--rx, 0deg) + 720deg))
|
rotateX(calc(var(--rx, 0deg) + 720deg))
|
||||||
rotateY(calc(var(--ry, 0deg) + 540deg));
|
rotateY(calc(var(--ry, 0deg) + 720deg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user