dobokocka mukodik :O
This commit is contained in:
@@ -1,74 +1,103 @@
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import React, { useState, useEffect, useRef } from "react"
|
||||
import { dotPositions } from "./diceDotPositions"
|
||||
|
||||
const Dice = ({ onRoll, selectedValue }) => {
|
||||
const [diceValue, setDiceValue] = useState(1)
|
||||
const [isRolling, setIsRolling] = useState(false)
|
||||
const animationRef = useRef(null)
|
||||
const rollTimeoutRef = useRef(null)
|
||||
|
||||
const Dice = ({ onRoll }) => {
|
||||
const [diceValue, setDiceValue] = useState(1);
|
||||
const [isRolling, setIsRolling] = useState(false);
|
||||
const animationRef = useRef(null);
|
||||
const rollTimeoutRef = useRef(null);
|
||||
|
||||
const diceFaces = [
|
||||
[<div key="center" className="dice-dot"></div>],
|
||||
[<div key="top-left" className="dice-dot"></div>, <div key="bottom-right" className="dice-dot"></div>],
|
||||
[<div key="top-left" className="dice-dot"></div>, <div key="center" className="dice-dot"></div>, <div key="bottom-right" className="dice-dot"></div>],
|
||||
[<div key="top-left" className="dice-dot"></div>, <div key="top-right" className="dice-dot"></div>,
|
||||
<div key="bottom-left" className="dice-dot"></div>, <div key="bottom-right" className="dice-dot"></div>],
|
||||
[<div key="top-left" className="dice-dot"></div>, <div key="top-right" className="dice-dot"></div>,
|
||||
<div key="center" className="dice-dot"></div>,
|
||||
<div key="bottom-left" className="dice-dot"></div>, <div key="bottom-right" className="dice-dot"></div>],
|
||||
[<div key="top-left" className="dice-dot"></div>, <div key="top-right" className="dice-dot"></div>,
|
||||
<div key="middle-left" className="dice-dot"></div>, <div key="middle-right" className="dice-dot"></div>,
|
||||
<div key="bottom-left" className="dice-dot"></div>, <div key="bottom-right" className="dice-dot"></div>]
|
||||
];
|
||||
|
||||
[<div key="center" className="dice-dot" style={dotPositions.center}></div>],
|
||||
[
|
||||
<div key="top-left" className="dice-dot" style={dotPositions.topLeft}></div>,
|
||||
<div key="bottom-right" className="dice-dot" style={dotPositions.bottomRight}></div>,
|
||||
],
|
||||
[
|
||||
<div key="top-left" className="dice-dot" style={dotPositions.topLeft}></div>,
|
||||
<div key="center" className="dice-dot" style={dotPositions.center}></div>,
|
||||
<div key="bottom-right" className="dice-dot" style={dotPositions.bottomRight}></div>,
|
||||
],
|
||||
[
|
||||
<div key="top-left" className="dice-dot" style={dotPositions.topLeft}></div>,
|
||||
<div key="top-right" className="dice-dot" style={dotPositions.topRight}></div>,
|
||||
<div key="bottom-left" className="dice-dot" style={dotPositions.bottomLeft}></div>,
|
||||
<div key="bottom-right" className="dice-dot" style={dotPositions.bottomRight}></div>,
|
||||
],
|
||||
[
|
||||
<div key="top-left" className="dice-dot" style={dotPositions.topLeft}></div>,
|
||||
<div key="top-right" className="dice-dot" style={dotPositions.topRight}></div>,
|
||||
<div key="center" className="dice-dot" style={dotPositions.center}></div>,
|
||||
<div key="bottom-left" className="dice-dot" style={dotPositions.bottomLeft}></div>,
|
||||
<div key="bottom-right" className="dice-dot" style={dotPositions.bottomRight}></div>,
|
||||
],
|
||||
[
|
||||
<div key="top-left" className="dice-dot" style={dotPositions.topLeft}></div>,
|
||||
<div key="top-right" className="dice-dot" style={dotPositions.topRight}></div>,
|
||||
<div key="middle-left" className="dice-dot" style={dotPositions.middleLeft}></div>,
|
||||
<div key="middle-right" className="dice-dot" style={dotPositions.middleRight}></div>,
|
||||
<div key="bottom-left" className="dice-dot" style={dotPositions.bottomLeft}></div>,
|
||||
<div key="bottom-right" className="dice-dot" style={dotPositions.bottomRight}></div>,
|
||||
],
|
||||
]
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (animationRef.current) cancelAnimationFrame(animationRef.current);
|
||||
if (rollTimeoutRef.current) clearTimeout(rollTimeoutRef.current);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const rollDice = () => {
|
||||
if (isRolling) return;
|
||||
|
||||
setIsRolling(true);
|
||||
|
||||
let duration = 0;
|
||||
const rollInterval = 80; // ms between dice face changes
|
||||
const maxDuration = 1500; // total animation time
|
||||
|
||||
if (animationRef.current) cancelAnimationFrame(animationRef.current)
|
||||
if (rollTimeoutRef.current) clearTimeout(rollTimeoutRef.current)
|
||||
}
|
||||
}, [])
|
||||
|
||||
// Helper that starts the rolling animation and finishes with targetValue if provided
|
||||
const startRoll = (targetValue = null) => {
|
||||
if (isRolling) return
|
||||
|
||||
setIsRolling(true)
|
||||
|
||||
let duration = 0
|
||||
const rollInterval = 80 // ms between dice face changes
|
||||
const maxDuration = 1500 // total animation time
|
||||
|
||||
const rollAnimation = () => {
|
||||
const randomValue = Math.floor(Math.random() * 6) + 1;
|
||||
setDiceValue(randomValue);
|
||||
|
||||
duration += rollInterval;
|
||||
|
||||
const randomValue = Math.floor(Math.random() * 6) + 1
|
||||
setDiceValue(randomValue)
|
||||
|
||||
duration += rollInterval
|
||||
|
||||
if (duration < maxDuration) {
|
||||
// Speed effect: slow down towards the end
|
||||
const nextInterval = rollInterval * (1 + (duration / maxDuration) * 2);
|
||||
const nextInterval = rollInterval * (1 + (duration / maxDuration) * 2)
|
||||
rollTimeoutRef.current = setTimeout(() => {
|
||||
animationRef.current = requestAnimationFrame(rollAnimation);
|
||||
}, nextInterval);
|
||||
animationRef.current = requestAnimationFrame(rollAnimation)
|
||||
}, nextInterval)
|
||||
} else {
|
||||
// Final roll
|
||||
const finalValue = Math.floor(Math.random() * 6) + 1;
|
||||
setDiceValue(finalValue);
|
||||
setIsRolling(false);
|
||||
|
||||
if (onRoll) onRoll(finalValue);
|
||||
// Final roll (use targetValue if provided)
|
||||
const finalValue = targetValue != null ? Number(targetValue) : Math.floor(Math.random() * 6) + 1
|
||||
setDiceValue(finalValue)
|
||||
setIsRolling(false)
|
||||
|
||||
if (onRoll) onRoll(finalValue)
|
||||
}
|
||||
};
|
||||
|
||||
animationRef.current = requestAnimationFrame(rollAnimation);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
animationRef.current = requestAnimationFrame(rollAnimation)
|
||||
}
|
||||
|
||||
// Click to roll randomly
|
||||
const rollDice = () => {
|
||||
startRoll(null)
|
||||
}
|
||||
|
||||
// If parent provides a selectedValue, animate to that value
|
||||
useEffect(() => {
|
||||
if (selectedValue != null) {
|
||||
startRoll(Number(selectedValue))
|
||||
}
|
||||
}, [selectedValue])
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`dice-container ${isRolling ? 'rolling' : ''}`}
|
||||
onClick={rollDice}
|
||||
>
|
||||
<div className="dice">
|
||||
{diceFaces[diceValue - 1]}
|
||||
</div>
|
||||
<div className={`dice-container ${isRolling ? "rolling" : ""}`} onClick={rollDice}>
|
||||
<div className="dice">{diceFaces[diceValue - 1]}</div>
|
||||
<style jsx>{`
|
||||
.dice-container {
|
||||
width: 80px;
|
||||
@@ -78,15 +107,15 @@ const Dice = ({ onRoll }) => {
|
||||
margin: 0 auto;
|
||||
transition: transform 0.2s;
|
||||
}
|
||||
|
||||
|
||||
.dice-container:hover {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
|
||||
.dice-container:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
|
||||
.dice {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -98,42 +127,45 @@ const Dice = ({ onRoll }) => {
|
||||
justify-content: center;
|
||||
background-color: #e63946;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 0 10px rgba(0,0,0,0.3);
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
|
||||
.rolling .dice {
|
||||
animation: roll 0.5s infinite linear;
|
||||
}
|
||||
|
||||
|
||||
@keyframes roll {
|
||||
0% { transform: rotateX(0deg) rotateY(0deg); }
|
||||
25% { transform: rotateX(90deg) rotateY(45deg); }
|
||||
50% { transform: rotateX(180deg) rotateY(90deg); }
|
||||
75% { transform: rotateX(270deg) rotateY(135deg); }
|
||||
100% { transform: rotateX(360deg) rotateY(180deg); }
|
||||
0% {
|
||||
transform: rotateX(0deg) rotateY(0deg);
|
||||
}
|
||||
25% {
|
||||
transform: rotateX(90deg) rotateY(45deg);
|
||||
}
|
||||
50% {
|
||||
transform: rotateX(180deg) rotateY(90deg);
|
||||
}
|
||||
75% {
|
||||
transform: rotateX(270deg) rotateY(135deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotateX(360deg) rotateY(180deg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.dice-dot {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border-radius: 50%;
|
||||
background-color: white;
|
||||
position: absolute;
|
||||
box-shadow: inset 0 0 3px rgba(0,0,0,0.3);
|
||||
box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
/* Positioning dots */
|
||||
.dice-dot:nth-child(1) { top: 50%; left: 50%; transform: translate(-50%, -50%); } /* Center */
|
||||
.dice-dot:nth-child(2) { top: 20%; left: 20%; } /* Top-left */
|
||||
.dice-dot:nth-child(3) { bottom: 20%; right: 20%; } /* Bottom-right */
|
||||
.dice-dot:nth-child(4) { top: 20%; right: 20%; } /* Top-right */
|
||||
.dice-dot:nth-child(5) { bottom: 20%; left: 20%; } /* Bottom-left */
|
||||
.dice-dot:nth-child(6) { top: 50%; left: 20%; transform: translateY(-50%); } /* Middle-left */
|
||||
.dice-dot:nth-child(7) { top: 50%; right: 20%; transform: translateY(-50%); } /* Middle-right */
|
||||
|
||||
/* removed :nth-child positioning — positions are provided inline from diceDotPositions.js */
|
||||
`}</style>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default Dice;
|
||||
export default Dice
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
export const dotPositions = {
|
||||
center: { top: "50%", left: "50%", transform: "translate(-50%, -50%)" },
|
||||
topLeft: { top: "20%", left: "20%" },
|
||||
bottomRight: { bottom: "20%", right: "20%" },
|
||||
topRight: { top: "20%", right: "20%" },
|
||||
bottomLeft: { bottom: "20%", left: "20%" },
|
||||
middleLeft: { top: "50%", left: "20%", transform: "translateY(-50%)" },
|
||||
middleRight: { top: "50%", right: "20%", transform: "translateY(-50%)" },
|
||||
}
|
||||
Reference in New Issue
Block a user