loot-spin-bonanza / script.js
ProjectGenesis's picture
<!DOCTYPE html>
0b2de52 verified
raw
history blame
5.15 kB
document.addEventListener('DOMContentLoaded', () => {
// DOM Elements
const lootTrack = document.getElementById('lootTrack');
const lootWrapper = document.getElementById('lootWrapper');
const multiTrack = document.getElementById('multiTrack');
const multiWrapper = document.getElementById('multiWrapper');
const spinBtn = document.getElementById('spinBtn');
const popupBackdrop = document.getElementById('popupBackdrop');
const popupTotal = document.getElementById('popupTotal');
const popupBase = document.getElementById('popupBase');
const popupMulti = document.getElementById('popupMulti');
const popupClose = document.getElementById('popupClose');
// Loot Box Data
const lootBoxesData = [
{ prize: 10, rarity: 'green' },
{ prize: 15, rarity: 'blue' },
{ prize: 20, rarity: 'blue' },
{ prize: 25, rarity: 'green' },
{ prize: 30, rarity: 'purple' },
{ prize: 35, rarity: 'purple' },
{ prize: 40, rarity: 'green' },
{ prize: 45, rarity: 'blue' },
{ prize: 50, rarity: 'purple' },
{ prize: 100, rarity: 'gold' }
];
// Multiplier Data
const multipliers = [1, 1.25, 1.5, 2, 3, 5, 1, 1.25, 1.5, 2, 3, 5];
// Initialize tracks
function initializeTracks() {
// Create loot boxes
lootBoxesData.forEach(box => {
const boxElement = document.createElement('div');
boxElement.className = 'loot-box';
boxElement.dataset.prize = box.prize;
boxElement.dataset.rarity = box.rarity;
const inner = document.createElement('div');
inner.className = 'loot-box-inner';
boxElement.appendChild(inner);
lootTrack.appendChild(boxElement);
});
// Create multiplier pills
multipliers.forEach(m => {
const pill = document.createElement('div');
pill.className = 'multi-pill';
pill.dataset.m = m;
pill.textContent = ${m}`;
multiTrack.appendChild(pill);
});
}
// Spin animation function
async function spinTrack(track, items, wrapper, extraMinSteps, extraMaxSteps, duration) {
return new Promise(resolve => {
// Reset classes
items.forEach(el => {
el.classList.remove('selected', 'motion-blur');
});
const targetIndex = Math.floor(Math.random() * items.length);
const wrapperRect = wrapper.getBoundingClientRect();
const centerX = wrapperRect.left + wrapperRect.width / 2;
const targetRect = items[targetIndex].getBoundingClientRect();
const targetCenter = targetRect.left + targetRect.width / 2;
const deltaToCenter = centerX - targetCenter;
// Calculate step size
let step = 0;
if (items.length > 1) {
const r0 = items[0].getBoundingClientRect();
const r1 = items[1].getBoundingClientRect();
step = Math.abs((r1.left + r1.width / 2) - (r0.left + r0.width / 2));
} else {
step = targetRect.width + 18;
}
const extraSteps = extraMinSteps + Math.floor(Math.random() * (extraMaxSteps - extraMinSteps + 1));
const direction = Math.random() > 0.5 ? 1 : -1;
const extraDistance = extraSteps * step * direction;
const currentTranslate = parseFloat(track.style.transform?.replace('translateX(', '').replace('px)', '') || '0');
const finalTranslate = currentTranslate + deltaToCenter + extraDistance;
// Apply motion blur
items.forEach((el, i) => {
if (i !== targetIndex) el.classList.add('motion-blur');
});
// Start animation
track.style.transition = `transform ${duration}ms cubic-bezier(0.1, 0.9, 0.24, 1)`;
track.style.transform = `translateX(${finalTranslate}px)`;
setTimeout(() => {
track.style.transition = '';
items.forEach(el => el.classList.remove('motion-blur'));
items[targetIndex].classList.add('selected');
resolve({ index: targetIndex, element: items[targetIndex] });
}, duration + 40);
});
}
// Handle spin button click
async function handleSpin() {
if (spinBtn.disabled) return;
spinBtn.disabled = true;
// Spin loot boxes
const lootResult = await spinTrack(lootTrack, [...lootTrack.children], lootWrapper, 3, 6, 1100);
const basePrize = parseFloat(lootResult.element.dataset.prize);
// Spin multiplier
const multiResult = await spinTrack(multiTrack, [...multiTrack.children], multiWrapper, 4, 7, 1000);
const multiplier = parseFloat(multiResult.element.dataset.m);
// Calculate total
const total = Math.round(basePrize * multiplier * 100) / 100;
// Show result
popupTotal.textContent = `${total} SC`;
popupBase.textContent = `Base: ${basePrize} SC`;
popupMulti.textContent = `Multiplier: ×${multiplier}`;
popupBackdrop.classList.remove('hidden');
spinBtn.disabled = false;
}
// Event listeners
spinBtn.addEventListener('click', handleSpin);
popupClose.addEventListener('click', () => {
popupBackdrop.classList.add('hidden');
});
popupBackdrop.addEventListener('click', (e) => {
if (e.target === popupBackdrop) {
popupBackdrop.classList.add('hidden');
}
});
// Initialize
initializeTracks();
});