// Renders a 6-sided die inside #dice and rolls a random value on click.
|
|
(() => {
|
|
const dice = document.getElementById('dice');
|
|
if (!dice) return;
|
|
|
|
// The 7 standard pip positions of a die face.
|
|
const positions = ['tl', 'tr', 'ml', 'c', 'mr', 'bl', 'br'];
|
|
|
|
const face = document.createElement('span');
|
|
face.className = 'dice__face';
|
|
face.innerHTML = positions
|
|
.map((p) => `<span class="pip pip--${p}"></span>`)
|
|
.join('');
|
|
dice.appendChild(face);
|
|
|
|
const SPIN_MS = 400; // keep in sync with the dice-roll animation duration
|
|
|
|
const showValue = () => {
|
|
const value = Math.floor(Math.random() * 6) + 1;
|
|
face.dataset.value = value;
|
|
dice.setAttribute('aria-label', `Dice showing ${value}. Click to roll.`);
|
|
};
|
|
|
|
const roll = (animate = true) => {
|
|
if (!animate) {
|
|
showValue();
|
|
return;
|
|
}
|
|
|
|
// Restart the roll animation on every click.
|
|
dice.classList.remove('is-rolling');
|
|
void dice.offsetWidth; // force reflow so the animation can replay
|
|
dice.classList.add('is-rolling');
|
|
|
|
// Reveal the new value once the spin is halfway through.
|
|
setTimeout(showValue, SPIN_MS / 2);
|
|
};
|
|
|
|
dice.addEventListener('click', () => roll());
|
|
dice.addEventListener('animationend', () => dice.classList.remove('is-rolling'));
|
|
|
|
roll(false); // show a starting value without animating
|
|
})();
|