HTML+JS老虎机效果实现
发布时间:2025-11-07
热度:
设计思路
使用CSS 3D变换创建真实的滚轮旋转效果
实现随机停止机制
添加动态灯光和音效增强体验
设计复古风格界面
下面是完整的实现代码:
html
<!DOCTYPE html><html lang="zh-CN"><head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>老虎机游戏</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Arial Rounded MT Bold', 'Arial', sans-serif;
}
body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: linear-gradient(135deg, #1a2a6c, #b21f1f, #fdbb2d);
padding: 20px;
}
.slot-machine {
width: 800px;
max-width: 95%;
background: linear-gradient(145deg, #2c3e50, #34495e);
border-radius: 20px;
padding: 30px;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.5);
border: 8px solid #e74c3c;
position: relative;
overflow: hidden;
}
.slot-machine::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 15px;
background: linear-gradient(90deg,
#e74c3c, #f39c12, #e74c3c, #f39c12, #e74c3c);
z-index: 10;
}
.slot-machine::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 15px;
background: linear-gradient(90deg,
#e74c3c, #f39c12, #e74c3c, #f39c12, #e74c3c);
z-index: 10;
}
.title {
text-align: center;
color: #f1c40f;
font-size: 2.8rem;
margin-bottom: 20px;
text-shadow: 0 0 10px #f39c12, 0 0 20px #e74c3c;
letter-spacing: 3px;
}
.reels-container {
display: flex;
justify-content: space-between;
margin: 30px 0;
background: #1a2530;
padding: 20px;
border-radius: 15px;
box-shadow: inset 0 0 20px rgba(0, 0, 0, 0.8);
position: relative;
border: 5px solid #7f8c8d;
}
.reel {
width: 30%;
height: 300px;
perspective: 1000px;
position: relative;
overflow: hidden;
border-radius: 10px;
background: #2c3e50;
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.7);
}
.reel-inner {
width: 100%;
height: 100%;
position: relative;
transform-style: preserve-3d;
transition: transform 0.1s;
}
.reel-item {
position: absolute;
width: 100%;
height: 100px;
display: flex;
justify-content: center;
align-items: center;
font-size: 3.5rem;
font-weight: bold;
backface-visibility: hidden;
border-bottom: 2px solid rgba(255, 255, 255, 0.1);
}
.reel-item:nth-child(1) { transform: translateZ(0) translateY(-200px); background: #e74c3c; color: white; }
.reel-item:nth-child(2) { transform: translateZ(0) translateY(-100px); background: #3498db; color: white; }
.reel-item:nth-child(3) { transform: translateZ(0) translateY(0); background: #2ecc71; color: white; }
.reel-item:nth-child(4) { transform: translateZ(0) translateY(100px); background: #f1c40f; color: #2c3e50; }
.reel-item:nth-child(5) { transform: translateZ(0) translateY(200px); background: #9b59b6; color: white; }
.win-line {
position: absolute;
left: 5%;
right: 5%;
height: 100px;
border-top: 4px dashed #f1c40f;
border-bottom: 4px dashed #f1c40f;
top: 50%;
transform: translateY(-50%);
z-index: 5;
box-shadow: 0 0 15px #f1c40f;
}
.controls {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 30px;
}
.spin-btn {
padding: 15px 40px;
font-size: 1.5rem;
font-weight: bold;
background: linear-gradient(to bottom, #e74c3c, #c0392b);
color: white;
border: none;
border-radius: 50px;
cursor: pointer;
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.3);
transition: all 0.3s;
text-transform: uppercase;
letter-spacing: 2px;
}
.spin-btn:hover {
transform: translateY(-5px);
box-shadow: 0 15px 25px rgba(0, 0, 0, 0.4);
background: linear-gradient(to bottom, #ff6b6b, #e74c3c);
}
.spin-btn:active {
transform: translateY(0);
}
.spin-btn:disabled {
background: #7f8c8d;
cursor: not-allowed;
transform: none;
box-shadow: none;
}
.info-panel {
display: flex;
flex-direction: column;
align-items: flex-end;
color: white;
}
.balance, .win {
font-size: 1.5rem;
margin-bottom: 10px;
text-shadow: 0 0 5px rgba(255, 255, 255, 0.5);
}
.win {
color: #f1c40f;
font-weight: bold;
}
.lights {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
pointer-events: none;
z-index: 1;
}
.light {
position: absolute;
width: 50px;
height: 50px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.7);
filter: blur(10px);
animation: lightPulse 2s infinite alternate;
}
.light:nth-child(1) { top: 10%; left: 10%; animation-delay: 0s; }
.light:nth-child(2) { top: 10%; right: 10%; animation-delay: 0.5s; }
.light:nth-child(3) { bottom: 10%; left: 10%; animation-delay: 1s; }
.light:nth-child(4) { bottom: 10%; right: 10%; animation-delay: 1.5s; }
@keyframes lightPulse {
0% { opacity: 0.3; transform: scale(0.8); }
100% { opacity: 0.8; transform: scale(1.2); }
}
.result {
text-align: center;
margin-top: 20px;
font-size: 2rem;
font-weight: bold;
height: 60px;
display: flex;
align-items: center;
justify-content: center;
color: #f1c40f;
text-shadow: 0 0 10px rgba(241, 196, 15, 0.7);
transition: all 0.5s;
}
.jackpot {
animation: jackpot 0.5s infinite alternate;
}
@keyframes jackpot {
0% { color: #f1c40f; transform: scale(1); }
100% { color: #e74c3c; transform: scale(1.1); }
}
@media (max-width: 600px) {
.reel {
height: 200px;
}
.reel-item {
height: 66.66px;
font-size: 2.5rem;
}
.title {
font-size: 2rem;
}
.spin-btn {
padding: 12px 25px;
font-size: 1.2rem;
}
} </style></head><body>
<div class="slot-machine">
<div class="lights">
<div class="light"></div>
<div class="light"></div>
<div class="light"></div>
<div class="light"></div>
</div>
<h1 class="title">幸运老虎机</h1>
<div class="reels-container">
<div class="win-line"></div>
<div class="reel" id="reel1">
<div class="reel-inner">
<div class="reel-item">🍒</div>
<div class="reel-item">🍋</div>
<div class="reel-item">🍊</div>
<div class="reel-item">⭐</div>
<div class="reel-item">7️⃣</div>
</div>
</div>
<div class="reel" id="reel2">
<div class="reel-inner">
<div class="reel-item">🍒</div>
<div class="reel-item">🍋</div>
<div class="reel-item">🍊</div>
<div class="reel-item">⭐</div>
<div class="reel-item">7️⃣</div>
</div>
</div>
<div class="reel" id="reel3">
<div class="reel-inner">
<div class="reel-item">🍒</div>
<div class="reel-item">🍋</div>
<div class="reel-item">🍊</div>
<div class="reel-item">⭐</div>
<div class="reel-item">7️⃣</div>
</div>
</div>
</div>
<div class="result" id="result">祝您好运!</div>
<div class="controls">
<button class="spin-btn" id="spinBtn">开始旋转</button>
<div class="info-panel">
<div class="balance">余额: <span id="balance">100</span> 金币</div>
<div class="win">赢取: <span id="winAmount">0</span> 金币</div>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const spinBtn = document.getElementById('spinBtn');
const reels = [
document.getElementById('reel1').querySelector('.reel-inner'),
document.getElementById('reel2').querySelector('.reel-inner'),
document.getElementById('reel3').querySelector('.reel-inner')
];
const resultDisplay = document.getElementById('result');
const balanceDisplay = document.getElementById('balance');
const winAmountDisplay = document.getElementById('winAmount');
let balance = 100;
let winAmount = 0;
let isSpinning = false;
// 符号及其对应的值
const symbols = ['🍒', '🍋', '🍊', '⭐', '7️⃣'];
const symbolValues = {
'🍒': 10,
'🍋': 20,
'🍊': 30,
'⭐': 40,
'7️⃣': 100
};
// 旋转动画函数
function spinReel(reel, duration) {
return new Promise(resolve => {
const startTime = Date.now();
const startPosition = 0;
const targetPosition = 1000 + Math.floor(Math.random() * 5) * 100; // 随机停止位置
function animate() {
const currentTime = Date.now();
const elapsed = currentTime - startTime;
if (elapsed < duration) {
// 缓动函数,开始快,结束慢
const progress = 1 - Math.pow(1 - elapsed / duration, 3);
const currentPosition = startPosition + (targetPosition - startPosition) * progress;
reel.style.transform = `translateY(${currentPosition}px)`;
requestAnimationFrame(animate);
} else {
reel.style.transform = `translateY(${targetPosition}px)`;
resolve();
}
}
animate();
});
}
// 获取当前显示的符号
function getVisibleSymbols() {
const visibleSymbols = [];
reels.forEach(reel => {
const transform = reel.style.transform;
const yPos = parseInt(transform.match(/translateY\(([^)]+)px\)/)[1]) || 0;
// 计算当前显示的符号索引
const symbolIndex = (5 - Math.floor((yPos % 500) / 100)) % 5;
visibleSymbols.push(symbols[symbolIndex]);
});
return visibleSymbols;
}
// 检查获胜
function checkWin(symbols) {
// 如果三个符号相同
if (symbols[0] === symbols[1] && symbols[1] === symbols[2]) {
return symbolValues[symbols[0]] * 3;
}
// 如果前两个符号相同
if (symbols[0] === symbols[1]) {
return symbolValues[symbols[0]];
}
return 0;
}
// 旋转所有滚轮
async function spinAll() {
if (isSpinning) return;
isSpinning = true;
spinBtn.disabled = true;
resultDisplay.textContent = "旋转中...";
resultDisplay.classList.remove('jackpot');
// 每次旋转花费10金币
balance -= 10;
balanceDisplay.textContent = balance;
// 为每个滚轮设置不同的持续时间,增加真实感
const spinPromises = [
spinReel(reels[0], 2000 + Math.random() * 1000),
spinReel(reels[1], 2500 + Math.random() * 1000),
spinReel(reels[2], 3000 + Math.random() * 1000)
];
// 等待所有滚轮停止
await Promise.all(spinPromises);
// 获取结果
const resultSymbols = getVisibleSymbols();
winAmount = checkWin(resultSymbols);
// 更新显示
if (winAmount > 0) {
resultDisplay.textContent = `恭喜!赢得 ${winAmount} 金币!`;
if (winAmount >= 100) {
resultDisplay.classList.add('jackpot');
resultDisplay.textContent = `🎉 头奖!赢得 ${winAmount} 金币! 🎉`;
}
balance += winAmount;
balanceDisplay.textContent = balance;
} else {
resultDisplay.textContent = "再试一次!";
}
winAmountDisplay.textContent = winAmount;
isSpinning = false;
spinBtn.disabled = false;
// 如果余额不足,禁用按钮
if (balance < 10) {
spinBtn.disabled = true;
resultDisplay.textContent = "余额不足!";
}
}
// 添加点击事件
spinBtn.addEventListener('click', spinAll);
}); </script></body></html>功能特点
逼真的滚轮旋转效果:使用CSS 3D变换和JavaScript动画实现
随机停止机制:每个滚轮随机停止在不同位置
获胜判定系统:
三个相同符号:获得3倍奖励
前两个相同符号:获得基础奖励
余额管理系统:每次旋转消耗金币,获胜增加金币
视觉反馈:
动态灯光效果
获胜时的特殊动画
复古风格界面设计
使用说明
点击"开始旋转"按钮启动老虎机
每次旋转消耗10金币
如果三个符号相同,获得3倍奖励
如果前两个符号相同,获得基础奖励
当余额不足时,游戏自动停止
这个老虎机效果完全使用HTML、CSS和JavaScript实现,无需任何外部库,可以直接复制代码到HTML文件中运行。












冀公网安备