纯前端实现 篮球计分板 Demo
可以模拟数据测试效果,直接上图
样式1

index-modern.html
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>篮球计分板 - Basketball Scoreboard</title><link rel="stylesheet" href="styles.css"><link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&family=Roboto:wght@300;400;500;700&display=swap" rel="stylesheet">
</head>
<body><div class="scoreboard-container"><!-- 顶部标题栏 --><header class="header"><h1 class="title">篮球计分板</h1><div class="game-info"><span class="quarter">第 <span id="quarter">1</span> 节</span><span class="game-status" id="gameStatus">比赛进行中</span></div></header><!-- 主计分板 --><main class="scoreboard"><!-- 主队 --><div class="team home-team"><div class="team-info"><h2 class="team-name" id="homeTeamName">主队</h2><div class="team-logo">🏀</div></div><div class="score-display"><span class="score" id="homeScore">0</span></div><div class="team-stats"><div class="stat"><span class="stat-label">犯规</span><span class="stat-value" id="homeFouls">0</span></div><div class="stat"><span class="stat-label">暂停</span><span class="stat-value" id="homeTimeouts">7</span></div></div></div><!-- 中央时间区域 --><div class="center-panel"><div class="game-clock"><div class="time-display" id="gameTime">12:00</div><div class="time-label">比赛时间</div></div><div class="shot-clock-container"><div class="shot-clock" id="shotClock">24</div><div class="shot-clock-label">进攻时间</div></div><div class="controls"><button class="control-btn" id="startBtn">开始</button><button class="control-btn" id="pauseBtn">暂停</button><button class="control-btn" id="resetBtn">重置</button><button class="control-btn simulate-btn" id="simulateBtn">模拟比赛</button></div></div><!-- 客队 --><div class="team away-team"><div class="team-info"><h2 class="team-name" id="awayTeamName">客队</h2><div class="team-logo">🏀</div></div><div class="score-display"><span class="score" id="awayScore">0</span></div><div class="team-stats"><div class="stat"><span class="stat-label">犯规</span><span class="stat-value" id="awayFouls">0</span></div><div class="stat"><span class="stat-label">暂停</span><span class="stat-value" id="awayTimeouts">7</span></div></div></div></main><!-- 底部信息栏 --><footer class="footer"><div class="game-events"><h3>比赛事件</h3><div class="events-list" id="eventsList"><div class="event">比赛即将开始...</div></div></div><div class="quarter-scores"><h3>分节比分</h3><table class="quarter-table"><thead><tr><th>队伍</th><th>1节</th><th>2节</th><th>3节</th><th>4节</th><th>总分</th></tr></thead><tbody><tr class="home-row"><td id="homeTeamNameTable">主队</td><td id="homeQ1">0</td><td id="homeQ2">0</td><td id="homeQ3">0</td><td id="homeQ4">0</td><td id="homeTotal">0</td></tr><tr class="away-row"><td id="awayTeamNameTable">客队</td><td id="awayQ1">0</td><td id="awayQ2">0</td><td id="awayQ3">0</td><td id="awayQ4">0</td><td id="awayTotal">0</td></tr></tbody></table></div></footer></div><script src="script.js"></script>
</body>
</html>
script-modern.js
class BasketballScoreboard {constructor() {this.gameState = {homeScore: 0,awayScore: 0,quarter: 1,gameTime: 12 * 60, // 12分钟,以秒为单位shotClock: 24,homeFouls: 0,awayFouls: 0,homeTimeouts: 7,awayTimeouts: 7,isRunning: false,isPaused: false,isGameEnded: false,quarterScores: {home: [0, 0, 0, 0],away: [0, 0, 0, 0]}};this.gameTimer = null;this.shotClockTimer = null;this.simulationTimer = null;this.isSimulating = false;this.teamNames = {home: ['湖人队', '勇士队', '公牛队', '凯尔特人队', '热火队', '马刺队'],away: ['快船队', '火箭队', '骑士队', '雷霆队', '76人队', '篮网队']};this.events = [];this.maxEvents = 10;this.initializeElements();this.bindEvents();this.updateDisplay();this.generateRandomTeamNames();}initializeElements() {// 获取所有DOM元素this.elements = {homeScore: document.getElementById('homeScore'),awayScore: document.getElementById('awayScore'),gameTime: document.getElementById('gameTime'),shotClock: document.getElementById('shotClock'),quarter: document.getElementById('quarter'),gameStatus: document.getElementById('gameStatus'),homeFouls: document.getElementById('homeFouls'),awayFouls: document.getElementById('awayFouls'),homeTimeouts: document.getElementById('homeTimeouts'),awayTimeouts: document.getElementById('awayTimeouts'),homeTeamName: document.getElementById('homeTeamName'),awayTeamName: document.getElementById('awayTeamName'),homeTeamNameTable: document.getElementById('homeTeamNameTable'),awayTeamNameTable: document.getElementById('awayTeamNameTable'),eventsList: document.getElementById('eventsList'),startBtn: document.getElementById('startBtn'),pauseBtn: document.getElementById('pauseBtn'),resetBtn: document.getElementById('resetBtn'),simulateBtn: document.getElementById('simulateBtn'),// 分节比分homeQ1: document.getElementById('homeQ1'),homeQ2: document.getElementById('homeQ2'),homeQ3: document.getElementById('homeQ3'),homeQ4: document.getElementById('homeQ4'),homeTotal: document.getElementById('homeTotal'),awayQ1: document.getElementById('awayQ1'),awayQ2: document.getElementById('awayQ2'),awayQ3: document.getElementById('awayQ3'),awayQ4: document.getElementById('awayQ4'),awayTotal: document.getElementById('awayTotal')};}bindEvents() {this.elements.startBtn.addEventListener('click', () => this.startGame());this.elements.pauseBtn.addEventListener('click', () => this.pauseGame());this.elements.resetBtn.addEventListener('click', () => this.resetGame());this.elements.simulateBtn.addEventListener('click', () => this.toggleSimulation());}generateRandomTeamNames() {const homeTeam = this.teamNames.home[Math.floor(Math.random() * this.teamNames.home.length)];const awayTeam = this.teamNames.away[Math.floor(Math.random() * this.teamNames.away.length)];this.elements.homeTeamName.textContent = homeTeam;this.elements.awayTeamName.textContent = awayTeam;this.elements.homeTeamNameTable.textContent = homeTeam;this.elements.awayTeamNameTable.textContent = awayTeam;}startGame() {if (this.gameState.isGameEnded) {this.addEvent('比赛已结束,请重置后开始新比赛');return;}this.gameState.isRunning = true;this.gameState.isPaused = false;this.startGameTimer();this.startShotClockTimer();this.elements.startBtn.disabled = true;this.elements.pauseBtn.disabled = false;this.updateGameStatus();this.addEvent('比赛开始!');}pauseGame() {this.gameState.isRunning = false;this.gameState.isPaused = true;this.stopTimers();this.elements.startBtn.disabled = false;this.elements.pauseBtn.disabled = true;this.updateGameStatus();this.addEvent('比赛暂停');}resetGame() {this.stopTimers();this.stopSimulation();this.gameState = {homeScore: 0,awayScore: 0,quarter: 1,gameTime: 12 * 60,shotClock: 24,homeFouls: 0,awayFouls: 0,homeTimeouts: 7,awayTimeouts: 7,isRunning: false,isPaused: false,isGameEnded: false,quarterScores: {home: [0, 0, 0, 0],away: [0, 0, 0, 0]}};this.events = [];this.elements.startBtn.disabled = false;this.elements.pauseBtn.disabled = true;this.updateDisplay();this.generateRandomTeamNames();this.addEvent('比赛重置,准备开始新比赛');}toggleSimulation() {if (this.isSimulating) {this.stopSimulation();} else {this.startSimulation();}}startSimulation() {if (!this.gameState.isRunning) {this.startGame();}this.isSimulating = true;this.elements.simulateBtn.textContent = '停止模拟';this.elements.simulateBtn.classList.add('active');this.simulationTimer = setInterval(() => {this.simulateGameEvent();}, 2000 + Math.random() * 3000); // 2-5秒随机间隔this.addEvent('开始自动模拟比赛');}stopSimulation() {this.isSimulating = false;if (this.simulationTimer) {clearInterval(this.simulationTimer);this.simulationTimer = null;}this.elements.simulateBtn.textContent = '模拟比赛';this.elements.simulateBtn.classList.remove('active');this.addEvent('停止自动模拟');}simulateGameEvent() {if (!this.gameState.isRunning || this.gameState.isGameEnded) {this.stopSimulation();return;}const events = [{ type: 'score', weight: 40 },{ type: 'foul', weight: 15 },{ type: 'timeout', weight: 5 },{ type: 'shotClockViolation', weight: 8 },{ type: 'steal', weight: 12 },{ type: 'block', weight: 10 },{ type: 'rebound', weight: 10 }];const totalWeight = events.reduce((sum, event) => sum + event.weight, 0);let random = Math.random() * totalWeight;for (const event of events) {random -= event.weight;if (random <= 0) {this.executeSimulatedEvent(event.type);break;}}}executeSimulatedEvent(eventType) {const isHomeTeam = Math.random() < 0.5;const homeTeam = this.elements.homeTeamName.textContent;const awayTeam = this.elements.awayTeamName.textContent;const team = isHomeTeam ? homeTeam : awayTeam;switch (eventType) {case 'score':const scoreType = Math.random();let points;let scoreDesc;if (scoreType < 0.1) { // 10% 三分球points = 3;scoreDesc = '三分球命中';} else if (scoreType < 0.3) { // 20% 罚球points = Math.random() < 0.8 ? 1 : 2; // 80%命中率scoreDesc = points === 1 ? '罚球命中' : '两罚全中';} else { // 70% 两分球points = 2;scoreDesc = '两分球命中';}if (isHomeTeam) {this.gameState.homeScore += points;this.gameState.quarterScores.home[this.gameState.quarter - 1] += points;} else {this.gameState.awayScore += points;this.gameState.quarterScores.away[this.gameState.quarter - 1] += points;}this.addEvent(`${team} ${scoreDesc} +${points}分`);this.resetShotClock();break;case 'foul':if (isHomeTeam) {this.gameState.homeFouls++;} else {this.gameState.awayFouls++;}this.addEvent(`${team} 犯规`);break;case 'timeout':if (isHomeTeam && this.gameState.homeTimeouts > 0) {this.gameState.homeTimeouts--;this.addEvent(`${team} 请求暂停`);} else if (!isHomeTeam && this.gameState.awayTimeouts > 0) {this.gameState.awayTimeouts--;this.addEvent(`${team} 请求暂停`);}break;case 'shotClockViolation':this.addEvent(`${team} 24秒违例`);this.resetShotClock();break;case 'steal':this.addEvent(`${team} 抢断成功`);this.resetShotClock();break;case 'block':this.addEvent(`${team} 盖帽成功`);break;case 'rebound':const reboundType = Math.random() < 0.6 ? '防守' : '进攻';this.addEvent(`${team} ${reboundType}篮板`);if (reboundType === '进攻') {this.gameState.shotClock = Math.max(14, this.gameState.shotClock);} else {this.resetShotClock();}break;}this.updateDisplay();}startGameTimer() {this.gameTimer = setInterval(() => {if (this.gameState.gameTime > 0) {this.gameState.gameTime--;this.updateDisplay();// 时间警告效果if (this.gameState.gameTime <= 60) {this.elements.gameTime.classList.add('clock-warning');} else {this.elements.gameTime.classList.remove('clock-warning');}} else {this.endQuarter();}}, 1000);}startShotClockTimer() {this.shotClockTimer = setInterval(() => {if (this.gameState.shotClock > 0) {this.gameState.shotClock--;this.updateShotClockDisplay();// 进攻时间警告if (this.gameState.shotClock <= 5) {this.elements.shotClock.classList.add('warning');} else {this.elements.shotClock.classList.remove('warning');}} else {this.addEvent('24秒违例!');this.resetShotClock();}}, 1000);}stopTimers() {if (this.gameTimer) {clearInterval(this.gameTimer);this.gameTimer = null;}if (this.shotClockTimer) {clearInterval(this.shotClockTimer);this.shotClockTimer = null;}}resetShotClock() {this.gameState.shotClock = 24;this.elements.shotClock.classList.remove('warning');this.updateShotClockDisplay();}endQuarter() {this.stopTimers();if (this.gameState.quarter < 4) {this.gameState.quarter++;this.gameState.gameTime = 12 * 60;this.resetShotClock();this.addEvent(`第${this.gameState.quarter - 1}节结束`);this.addEvent(`第${this.gameState.quarter}节开始`);// 自动开始下一节setTimeout(() => {if (this.isSimulating) {this.startGame();}}, 2000);} else {this.endGame();}this.updateDisplay();}endGame() {this.gameState.isGameEnded = true;this.gameState.isRunning = false;this.stopTimers();this.stopSimulation();this.elements.startBtn.disabled = true;this.elements.pauseBtn.disabled = true;const homeTeam = this.elements.homeTeamName.textContent;const awayTeam = this.elements.awayTeamName.textContent;if (this.gameState.homeScore > this.gameState.awayScore) {this.addEvent(`比赛结束!${homeTeam} 获胜!`);document.querySelector('.home-team').classList.add('leading-team');} else if (this.gameState.awayScore > this.gameState.homeScore) {this.addEvent(`比赛结束!${awayTeam} 获胜!`);document.querySelector('.away-team').classList.add('leading-team');} else {this.addEvent('比赛结束!双方打成平局!');}this.updateGameStatus();}updateDisplay() {// 更新分数this.elements.homeScore.textContent = this.gameState.homeScore;this.elements.awayScore.textContent = this.gameState.awayScore;// 更新时间this.updateTimeDisplay();this.updateShotClockDisplay();// 更新节数this.elements.quarter.textContent = this.gameState.quarter;// 更新统计this.elements.homeFouls.textContent = this.gameState.homeFouls;this.elements.awayFouls.textContent = this.gameState.awayFouls;this.elements.homeTimeouts.textContent = this.gameState.homeTimeouts;this.elements.awayTimeouts.textContent = this.gameState.awayTimeouts;// 更新分节比分this.updateQuarterScores();// 更新游戏状态this.updateGameStatus();// 更新领先队伍高亮this.updateLeadingTeam();}updateTimeDisplay() {const minutes = Math.floor(this.gameState.gameTime / 60);const seconds = this.gameState.gameTime % 60;this.elements.gameTime.textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`;}updateShotClockDisplay() {this.elements.shotClock.textContent = this.gameState.shotClock;}updateQuarterScores() {const quarters = ['Q1', 'Q2', 'Q3', 'Q4'];quarters.forEach((q, index) => {this.elements[`home${q}`].textContent = this.gameState.quarterScores.home[index];this.elements[`away${q}`].textContent = this.gameState.quarterScores.away[index];});this.elements.homeTotal.textContent = this.gameState.homeScore;this.elements.awayTotal.textContent = this.gameState.awayScore;}updateGameStatus() {if (this.gameState.isGameEnded) {this.elements.gameStatus.textContent = '比赛结束';this.elements.gameStatus.style.color = '#ef4444';} else if (this.gameState.isPaused) {this.elements.gameStatus.textContent = '比赛暂停';this.elements.gameStatus.style.color = '#fbbf24';} else if (this.gameState.isRunning) {this.elements.gameStatus.textContent = '比赛进行中';this.elements.gameStatus.style.color = '#4ade80';} else {this.elements.gameStatus.textContent = '等待开始';this.elements.gameStatus.style.color = '#94a3b8';}}updateLeadingTeam() {const homeTeamElement = document.querySelector('.home-team');const awayTeamElement = document.querySelector('.away-team');homeTeamElement.classList.remove('leading-team');awayTeamElement.classList.remove('leading-team');if (!this.gameState.isGameEnded) {if (this.gameState.homeScore > this.gameState.awayScore) {homeTeamElement.classList.add('leading-team');} else if (this.gameState.awayScore > this.gameState.homeScore) {awayTeamElement.classList.add('leading-team');}}}addEvent(eventText) {const now = new Date();const timeStr = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}`;this.events.unshift(`[${timeStr}] ${eventText}`);if (this.events.length > this.maxEvents) {this.events = this.events.slice(0, this.maxEvents);}this.updateEventsDisplay();}updateEventsDisplay() {this.elements.eventsList.innerHTML = this.events.map(event => `<div class="event">${event}</div>`).join('');}
}// 初始化计分板
document.addEventListener('DOMContentLoaded', () => {new BasketballScoreboard();
});
styles-modern.css
/* 全局样式重置 */
* {margin: 0;padding: 0;box-sizing: border-box;
}body {font-family: 'Roboto', sans-serif;background: linear-gradient(135deg, #1e3c72 0%, #2a5298 100%);min-height: 100vh;color: white;overflow-x: auto;
}/* 主容器 */
.scoreboard-container {max-width: 1400px;margin: 0 auto;padding: 20px;min-height: 100vh;display: flex;flex-direction: column;
}/* 顶部标题栏 */
.header {background: rgba(0, 0, 0, 0.3);border-radius: 15px;padding: 20px;margin-bottom: 20px;display: flex;justify-content: space-between;align-items: center;backdrop-filter: blur(10px);border: 1px solid rgba(255, 255, 255, 0.1);
}.title {font-size: 2.5rem;font-weight: 700;background: linear-gradient(45deg, #ff6b35, #f7931e);-webkit-background-clip: text;-webkit-text-fill-color: transparent;background-clip: text;
}.game-info {display: flex;flex-direction: column;align-items: flex-end;gap: 5px;
}.quarter {font-size: 1.2rem;font-weight: 500;color: #ffd700;
}.game-status {font-size: 1rem;color: #4ade80;font-weight: 400;
}/* 主计分板 */
.scoreboard {display: grid;grid-template-columns: 1fr auto 1fr;gap: 30px;margin-bottom: 30px;flex: 1;align-items: center;
}/* 队伍样式 */
.team {background: rgba(0, 0, 0, 0.4);border-radius: 20px;padding: 30px;text-align: center;backdrop-filter: blur(15px);border: 2px solid rgba(255, 255, 255, 0.1);transition: all 0.3s ease;position: relative;overflow: hidden;
}.team::before {content: '';position: absolute;top: 0;left: -100%;width: 100%;height: 100%;background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent);transition: left 0.5s;
}.team:hover::before {left: 100%;
}.home-team {border-left: 4px solid #ff6b35;
}.away-team {border-right: 4px solid #4ade80;
}.team-info {margin-bottom: 20px;
}.team-name {font-size: 1.8rem;font-weight: 700;margin-bottom: 10px;text-transform: uppercase;letter-spacing: 2px;
}.team-logo {font-size: 3rem;margin: 10px 0;filter: drop-shadow(0 0 10px rgba(255, 255, 255, 0.3));
}.score-display {margin: 30px 0;
}.score {font-family: 'Orbitron', monospace;font-size: 5rem;font-weight: 900;color: #ffd700;text-shadow: 0 0 20px rgba(255, 215, 0, 0.5);display: block;line-height: 1;
}.team-stats {display: flex;justify-content: space-around;margin-top: 20px;
}.stat {text-align: center;
}.stat-label {display: block;font-size: 0.9rem;color: #94a3b8;margin-bottom: 5px;
}.stat-value {font-family: 'Orbitron', monospace;font-size: 1.5rem;font-weight: 700;color: #e2e8f0;
}/* 中央面板 */
.center-panel {display: flex;flex-direction: column;align-items: center;gap: 25px;background: rgba(0, 0, 0, 0.5);border-radius: 25px;padding: 40px 30px;backdrop-filter: blur(20px);border: 2px solid rgba(255, 255, 255, 0.15);min-width: 300px;
}.game-clock {text-align: center;
}.time-display {font-family: 'Orbitron', monospace;font-size: 4rem;font-weight: 900;color: #ff6b35;text-shadow: 0 0 30px rgba(255, 107, 53, 0.6);margin-bottom: 10px;
}.time-label {font-size: 1rem;color: #94a3b8;text-transform: uppercase;letter-spacing: 1px;
}.shot-clock-container {text-align: center;margin: 20px 0;
}.shot-clock {font-family: 'Orbitron', monospace;font-size: 2.5rem;font-weight: 700;color: #4ade80;background: rgba(74, 222, 128, 0.1);border: 2px solid #4ade80;border-radius: 50%;width: 80px;height: 80px;display: flex;align-items: center;justify-content: center;margin: 0 auto 10px;text-shadow: 0 0 15px rgba(74, 222, 128, 0.5);
}.shot-clock-label {font-size: 0.9rem;color: #94a3b8;text-transform: uppercase;letter-spacing: 1px;
}.controls {display: flex;flex-wrap: wrap;gap: 10px;justify-content: center;
}.control-btn {background: linear-gradient(45deg, #667eea 0%, #764ba2 100%);border: none;border-radius: 25px;padding: 12px 24px;color: white;font-weight: 600;cursor: pointer;transition: all 0.3s ease;text-transform: uppercase;letter-spacing: 1px;font-size: 0.9rem;box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3);
}.control-btn:hover {transform: translateY(-2px);box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
}.control-btn:active {transform: translateY(0);
}.simulate-btn {background: linear-gradient(45deg, #ff6b35 0%, #f7931e 100%);box-shadow: 0 4px 15px rgba(255, 107, 53, 0.3);
}.simulate-btn:hover {box-shadow: 0 6px 20px rgba(255, 107, 53, 0.4);
}/* 底部信息栏 */
.footer {display: grid;grid-template-columns: 1fr 1fr;gap: 30px;margin-top: auto;
}.game-events, .quarter-scores {background: rgba(0, 0, 0, 0.4);border-radius: 15px;padding: 25px;backdrop-filter: blur(10px);border: 1px solid rgba(255, 255, 255, 0.1);
}.game-events h3, .quarter-scores h3 {font-size: 1.3rem;margin-bottom: 15px;color: #ffd700;text-transform: uppercase;letter-spacing: 1px;
}.events-list {max-height: 150px;overflow-y: auto;scrollbar-width: thin;scrollbar-color: rgba(255, 255, 255, 0.3) transparent;
}.events-list::-webkit-scrollbar {width: 6px;
}.events-list::-webkit-scrollbar-track {background: transparent;
}.events-list::-webkit-scrollbar-thumb {background: rgba(255, 255, 255, 0.3);border-radius: 3px;
}.event {padding: 8px 0;border-bottom: 1px solid rgba(255, 255, 255, 0.1);font-size: 0.9rem;color: #e2e8f0;
}.event:last-child {border-bottom: none;
}.quarter-table {width: 100%;border-collapse: collapse;
}.quarter-table th,
.quarter-table td {padding: 10px;text-align: center;border: 1px solid rgba(255, 255, 255, 0.2);
}.quarter-table th {background: rgba(255, 255, 255, 0.1);font-weight: 600;color: #ffd700;text-transform: uppercase;font-size: 0.9rem;letter-spacing: 1px;
}.quarter-table td {font-family: 'Orbitron', monospace;font-weight: 600;color: #e2e8f0;
}.home-row td:first-child {color: #ff6b35;font-family: 'Roboto', sans-serif;font-weight: 700;
}.away-row td:first-child {color: #4ade80;font-family: 'Roboto', sans-serif;font-weight: 700;
}/* 响应式设计 */
@media (max-width: 1200px) {.scoreboard {grid-template-columns: 1fr;gap: 20px;}.center-panel {order: -1;}.footer {grid-template-columns: 1fr;}
}@media (max-width: 768px) {.header {flex-direction: column;text-align: center;gap: 15px;}.title {font-size: 2rem;}.score {font-size: 3.5rem;}.time-display {font-size: 3rem;}.team {padding: 20px;}.center-panel {padding: 25px 20px;}.controls {flex-direction: column;width: 100%;}.control-btn {width: 100%;}
}/* 动画效果 */
@keyframes scoreUpdate {0% { transform: scale(1); }50% { transform: scale(1.1); }100% { transform: scale(1); }
}.score-animation {animation: scoreUpdate 0.5s ease-in-out;
}@keyframes clockTick {0% { color: #ff6b35; }50% { color: #ff4444; }100% { color: #ff6b35; }
}.clock-warning {animation: clockTick 1s infinite;
}/* 特殊状态样式 */
.game-paused .time-display {color: #fbbf24;
}.game-ended .time-display {color: #ef4444;
}.leading-team {box-shadow: 0 0 30px rgba(255, 215, 0, 0.3);
}.shot-clock.warning {color: #ef4444;border-color: #ef4444;animation: clockTick 0.5s infinite;
}
样式2 复古风

index-crt.html
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>复古篮球计分板 - Retro Basketball Scoreboard</title><link rel="stylesheet" href="styles.css"><link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&family=Share+Tech+Mono&display=swap" rel="stylesheet">
</head>
<body><div class="crt-container"><!-- CRT 显示器外壳 --><div class="crt-frame"><div class="crt-screen"><!-- 扫描线效果 --><div class="scanlines"></div><!-- 主计分板内容 --><div class="scoreboard-content"><!-- 顶部标题 --><header class="header"><div class="title-display"><div class="dot-matrix-text" data-text="BASKETBALL SCOREBOARD"><span class="matrix-char">B</span><span class="matrix-char">A</span><span class="matrix-char">S</span><span class="matrix-char">K</span><span class="matrix-char">E</span><span class="matrix-char">T</span><span class="matrix-char">B</span><span class="matrix-char">A</span><span class="matrix-char">L</span><span class="matrix-char">L</span><br><span class="matrix-char">S</span><span class="matrix-char">C</span><span class="matrix-char">O</span><span class="matrix-char">R</span><span class="matrix-char">E</span><span class="matrix-char">B</span><span class="matrix-char">O</span><span class="matrix-char">A</span><span class="matrix-char">R</span><span class="matrix-char">D</span></div></div><div class="status-indicators"><div class="indicator quarter-indicator"><span class="label">QUARTER</span><span class="digital-display" id="quarter">1</span></div><div class="indicator status-indicator"><span class="label">STATUS</span><span class="status-text" id="gameStatus">READY</span></div></div></header><!-- 主显示区域 --><main class="main-display"><!-- 主队 --><div class="team-section home-team"><div class="team-header"><div class="team-name-display"><span class="team-label">HOME</span><div class="team-name" id="homeTeamName">LAKERS</div></div></div><div class="score-section"><div class="main-score"><div class="digital-score" id="homeScore"><span class="digit">0</span><span class="digit">0</span><span class="digit">0</span></div></div></div><div class="team-stats"><div class="stat-item"><span class="stat-label">FOULS</span><span class="stat-value digital-small" id="homeFouls">00</span></div><div class="stat-item"><span class="stat-label">T.OUT</span><span class="stat-value digital-small" id="homeTimeouts">07</span></div></div></div><!-- 中央时钟区域 --><div class="center-clock"><div class="game-clock-section"><div class="clock-label">GAME TIME</div><div class="main-clock"><div class="digital-clock" id="gameTime"><span class="time-digit">1</span><span class="time-digit">2</span><span class="time-colon">:</span><span class="time-digit">0</span><span class="time-digit">0</span></div></div></div><div class="shot-clock-section"><div class="clock-label">SHOT CLOCK</div><div class="shot-clock-display"><div class="digital-shot-clock" id="shotClock"><span class="shot-digit">2</span><span class="shot-digit">4</span></div></div></div><div class="control-panel"><button class="retro-btn" id="startBtn">START</button><button class="retro-btn" id="pauseBtn">PAUSE</button><button class="retro-btn" id="resetBtn">RESET</button><button class="retro-btn simulate-btn" id="simulateBtn">SIMULATE</button></div></div><!-- 客队 --><div class="team-section away-team"><div class="team-header"><div class="team-name-display"><span class="team-label">AWAY</span><div class="team-name" id="awayTeamName">CELTICS</div></div></div><div class="score-section"><div class="main-score"><div class="digital-score" id="awayScore"><span class="digit">0</span><span class="digit">0</span><span class="digit">0</span></div></div></div><div class="team-stats"><div class="stat-item"><span class="stat-label">FOULS</span><span class="stat-value digital-small" id="awayFouls">00</span></div><div class="stat-item"><span class="stat-label">T.OUT</span><span class="stat-value digital-small" id="awayTimeouts">07</span></div></div></div></main><!-- 底部信息区域 --><footer class="bottom-section"><!-- 分节比分 --><div class="quarter-scores-section"><div class="section-title">QUARTER SCORES</div><div class="quarter-grid"><div class="quarter-header"><span class="qh-team">TEAM</span><span class="qh-q">Q1</span><span class="qh-q">Q2</span><span class="qh-q">Q3</span><span class="qh-q">Q4</span><span class="qh-total">TOTAL</span></div><div class="quarter-row home-row"><span class="qr-team" id="homeTeamNameTable">HOME</span><span class="qr-score digital-mini" id="homeQ1">00</span><span class="qr-score digital-mini" id="homeQ2">00</span><span class="qr-score digital-mini" id="homeQ3">00</span><span class="qr-score digital-mini" id="homeQ4">00</span><span class="qr-total digital-mini" id="homeTotal">000</span></div><div class="quarter-row away-row"><span class="qr-team" id="awayTeamNameTable">AWAY</span><span class="qr-score digital-mini" id="awayQ1">00</span><span class="qr-score digital-mini" id="awayQ2">00</span><span class="qr-score digital-mini" id="awayQ3">00</span><span class="qr-score digital-mini" id="awayQ4">00</span><span class="qr-total digital-mini" id="awayTotal">000</span></div></div></div><!-- 事件日志 --><div class="events-section"><div class="section-title">GAME EVENTS</div><div class="events-display"><div class="events-list" id="eventsList"><div class="event-line">GAME READY TO START...</div></div></div></div></footer></div><!-- CRT 效果层 --><div class="crt-effects"><div class="screen-flicker"></div><div class="screen-curve"></div></div></div><!-- CRT 边框装饰 --><div class="crt-bezel"><div class="power-indicator"></div><div class="brand-label">RETRO SPORTS</div></div></div></div><script src="script.js"></script>
</body>
</html>
script-crt.js
class RetroBasketballScoreboard {constructor() {this.gameState = {homeScore: 0,awayScore: 0,quarter: 1,gameTime: 12 * 60, // 12分钟,以秒为单位shotClock: 24,homeFouls: 0,awayFouls: 0,homeTimeouts: 7,awayTimeouts: 7,isRunning: false,isPaused: false,isGameEnded: false,quarterScores: {home: [0, 0, 0, 0],away: [0, 0, 0, 0]}};this.gameTimer = null;this.shotClockTimer = null;this.simulationTimer = null;this.isSimulating = false;this.teamNames = {home: ['LAKERS', 'WARRIORS', 'BULLS', 'CELTICS', 'HEAT', 'SPURS'],away: ['CLIPPERS', 'ROCKETS', 'CAVS', 'THUNDER', 'SIXERS', 'NETS']};this.events = [];this.maxEvents = 8;this.initializeElements();this.bindEvents();this.updateDisplay();this.generateRandomTeamNames();this.startCRTEffects();}initializeElements() {// 获取所有DOM元素this.elements = {homeScore: document.getElementById('homeScore'),awayScore: document.getElementById('awayScore'),gameTime: document.getElementById('gameTime'),shotClock: document.getElementById('shotClock'),quarter: document.getElementById('quarter'),gameStatus: document.getElementById('gameStatus'),homeFouls: document.getElementById('homeFouls'),awayFouls: document.getElementById('awayFouls'),homeTimeouts: document.getElementById('homeTimeouts'),awayTimeouts: document.getElementById('awayTimeouts'),homeTeamName: document.getElementById('homeTeamName'),awayTeamName: document.getElementById('awayTeamName'),homeTeamNameTable: document.getElementById('homeTeamNameTable'),awayTeamNameTable: document.getElementById('awayTeamNameTable'),eventsList: document.getElementById('eventsList'),startBtn: document.getElementById('startBtn'),pauseBtn: document.getElementById('pauseBtn'),resetBtn: document.getElementById('resetBtn'),simulateBtn: document.getElementById('simulateBtn'),// 分节比分homeQ1: document.getElementById('homeQ1'),homeQ2: document.getElementById('homeQ2'),homeQ3: document.getElementById('homeQ3'),homeQ4: document.getElementById('homeQ4'),homeTotal: document.getElementById('homeTotal'),awayQ1: document.getElementById('awayQ1'),awayQ2: document.getElementById('awayQ2'),awayQ3: document.getElementById('awayQ3'),awayQ4: document.getElementById('awayQ4'),awayTotal: document.getElementById('awayTotal')};}bindEvents() {this.elements.startBtn.addEventListener('click', () => this.startGame());this.elements.pauseBtn.addEventListener('click', () => this.pauseGame());this.elements.resetBtn.addEventListener('click', () => this.resetGame());this.elements.simulateBtn.addEventListener('click', () => this.toggleSimulation());}generateRandomTeamNames() {const homeTeam = this.teamNames.home[Math.floor(Math.random() * this.teamNames.home.length)];const awayTeam = this.teamNames.away[Math.floor(Math.random() * this.teamNames.away.length)];this.elements.homeTeamName.textContent = homeTeam;this.elements.awayTeamName.textContent = awayTeam;this.elements.homeTeamNameTable.textContent = homeTeam;this.elements.awayTeamNameTable.textContent = awayTeam;}startCRTEffects() {// 添加随机的CRT闪烁效果setInterval(() => {if (Math.random() < 0.1) { // 10%概率闪烁const screen = document.querySelector('.crt-screen');screen.style.filter = 'brightness(1.1)';setTimeout(() => {screen.style.filter = 'brightness(1)';}, 50);}}, 1000);// 添加随机的数字闪烁效果setInterval(() => {if (Math.random() < 0.05) { // 5%概率数字闪烁const digits = document.querySelectorAll('.digit, .time-digit, .shot-digit');const randomDigit = digits[Math.floor(Math.random() * digits.length)];if (randomDigit) {randomDigit.style.textShadow = '0 0 30px currentColor';setTimeout(() => {randomDigit.style.textShadow = '';}, 100);}}}, 2000);}startGame() {if (this.gameState.isGameEnded) {this.addEvent('GAME ENDED - RESET TO START NEW GAME');return;}this.gameState.isRunning = true;this.gameState.isPaused = false;this.startGameTimer();this.startShotClockTimer();this.elements.startBtn.disabled = true;this.elements.pauseBtn.disabled = false;this.updateGameStatus();this.addEvent('GAME STARTED!');}pauseGame() {this.gameState.isRunning = false;this.gameState.isPaused = true;this.stopTimers();this.elements.startBtn.disabled = false;this.elements.pauseBtn.disabled = true;this.updateGameStatus();this.addEvent('GAME PAUSED');}resetGame() {this.stopTimers();this.stopSimulation();this.gameState = {homeScore: 0,awayScore: 0,quarter: 1,gameTime: 12 * 60,shotClock: 24,homeFouls: 0,awayFouls: 0,homeTimeouts: 7,awayTimeouts: 7,isRunning: false,isPaused: false,isGameEnded: false,quarterScores: {home: [0, 0, 0, 0],away: [0, 0, 0, 0]}};this.events = [];this.elements.startBtn.disabled = false;this.elements.pauseBtn.disabled = true;// 移除特殊状态样式document.body.classList.remove('game-paused', 'game-ended');document.querySelectorAll('.leading-team').forEach(el => {el.classList.remove('leading-team');});this.updateDisplay();this.generateRandomTeamNames();this.addEvent('SYSTEM RESET - READY TO START');}toggleSimulation() {if (this.isSimulating) {this.stopSimulation();} else {this.startSimulation();}}startSimulation() {if (!this.gameState.isRunning) {this.startGame();}this.isSimulating = true;this.elements.simulateBtn.textContent = 'STOP SIM';this.elements.simulateBtn.style.color = '#ff0000';this.elements.simulateBtn.style.borderColor = '#ff0000';this.simulationTimer = setInterval(() => {this.simulateGameEvent();}, 1500 + Math.random() * 2500); // 1.5-4秒随机间隔this.addEvent('AUTO SIMULATION STARTED');}stopSimulation() {this.isSimulating = false;if (this.simulationTimer) {clearInterval(this.simulationTimer);this.simulationTimer = null;}this.elements.simulateBtn.textContent = 'SIMULATE';this.elements.simulateBtn.style.color = '#ffff00';this.elements.simulateBtn.style.borderColor = '#ffff00';this.addEvent('AUTO SIMULATION STOPPED');}simulateGameEvent() {if (!this.gameState.isRunning || this.gameState.isGameEnded) {this.stopSimulation();return;}const events = [{ type: 'score', weight: 40 },{ type: 'foul', weight: 15 },{ type: 'timeout', weight: 5 },{ type: 'shotClockViolation', weight: 8 },{ type: 'steal', weight: 12 },{ type: 'block', weight: 10 },{ type: 'rebound', weight: 10 }];const totalWeight = events.reduce((sum, event) => sum + event.weight, 0);let random = Math.random() * totalWeight;for (const event of events) {random -= event.weight;if (random <= 0) {this.executeSimulatedEvent(event.type);break;}}}executeSimulatedEvent(eventType) {const isHomeTeam = Math.random() < 0.5;const homeTeam = this.elements.homeTeamName.textContent;const awayTeam = this.elements.awayTeamName.textContent;const team = isHomeTeam ? homeTeam : awayTeam;switch (eventType) {case 'score':const scoreType = Math.random();let points;let scoreDesc;if (scoreType < 0.1) { // 10% 三分球points = 3;scoreDesc = '3-POINTER';} else if (scoreType < 0.3) { // 20% 罚球points = Math.random() < 0.8 ? 1 : 2; // 80%命中率scoreDesc = points === 1 ? 'FREE THROW' : '2 FREE THROWS';} else { // 70% 两分球points = 2;scoreDesc = 'FIELD GOAL';}if (isHomeTeam) {this.gameState.homeScore += points;this.gameState.quarterScores.home[this.gameState.quarter - 1] += points;} else {this.gameState.awayScore += points;this.gameState.quarterScores.away[this.gameState.quarter - 1] += points;}this.addEvent(`${team} ${scoreDesc} +${points}PTS`);this.resetShotClock();this.animateScoreUpdate(isHomeTeam);break;case 'foul':if (isHomeTeam) {this.gameState.homeFouls++;} else {this.gameState.awayFouls++;}this.addEvent(`${team} PERSONAL FOUL`);break;case 'timeout':if (isHomeTeam && this.gameState.homeTimeouts > 0) {this.gameState.homeTimeouts--;this.addEvent(`${team} TIMEOUT`);} else if (!isHomeTeam && this.gameState.awayTimeouts > 0) {this.gameState.awayTimeouts--;this.addEvent(`${team} TIMEOUT`);}break;case 'shotClockViolation':this.addEvent(`${team} 24-SEC VIOLATION`);this.resetShotClock();break;case 'steal':this.addEvent(`${team} STEAL`);this.resetShotClock();break;case 'block':this.addEvent(`${team} BLOCK`);break;case 'rebound':const reboundType = Math.random() < 0.6 ? 'DEF' : 'OFF';this.addEvent(`${team} ${reboundType} REBOUND`);if (reboundType === 'OFF') {this.gameState.shotClock = Math.max(14, this.gameState.shotClock);} else {this.resetShotClock();}break;}this.updateDisplay();}animateScoreUpdate(isHomeTeam) {const scoreElement = isHomeTeam ? this.elements.homeScore : this.elements.awayScore;scoreElement.style.transform = 'scale(1.1)';scoreElement.style.textShadow = '0 0 50px currentColor';setTimeout(() => {scoreElement.style.transform = 'scale(1)';scoreElement.style.textShadow = '';}, 300);}startGameTimer() {this.gameTimer = setInterval(() => {if (this.gameState.gameTime > 0) {this.gameState.gameTime--;this.updateTimeDisplay();// 时间警告效果if (this.gameState.gameTime <= 60) {document.body.classList.add('clock-warning');} else {document.body.classList.remove('clock-warning');}} else {this.endQuarter();}}, 1000);}startShotClockTimer() {this.shotClockTimer = setInterval(() => {if (this.gameState.shotClock > 0) {this.gameState.shotClock--;this.updateShotClockDisplay();// 进攻时间警告if (this.gameState.shotClock <= 5) {const shotDigits = document.querySelectorAll('.shot-digit');shotDigits.forEach(digit => digit.classList.add('warning'));} else {const shotDigits = document.querySelectorAll('.shot-digit');shotDigits.forEach(digit => digit.classList.remove('warning'));}} else {this.addEvent('24-SECOND VIOLATION!');this.resetShotClock();}}, 1000);}stopTimers() {if (this.gameTimer) {clearInterval(this.gameTimer);this.gameTimer = null;}if (this.shotClockTimer) {clearInterval(this.shotClockTimer);this.shotClockTimer = null;}}resetShotClock() {this.gameState.shotClock = 24;const shotDigits = document.querySelectorAll('.shot-digit');shotDigits.forEach(digit => digit.classList.remove('warning'));this.updateShotClockDisplay();}endQuarter() {this.stopTimers();if (this.gameState.quarter < 4) {this.gameState.quarter++;this.gameState.gameTime = 12 * 60;this.resetShotClock();this.addEvent(`QUARTER ${this.gameState.quarter - 1} ENDED`);this.addEvent(`QUARTER ${this.gameState.quarter} STARTING`);// 自动开始下一节setTimeout(() => {if (this.isSimulating) {this.startGame();}}, 2000);} else {this.endGame();}this.updateDisplay();}endGame() {this.gameState.isGameEnded = true;this.gameState.isRunning = false;this.stopTimers();this.stopSimulation();this.elements.startBtn.disabled = true;this.elements.pauseBtn.disabled = true;document.body.classList.add('game-ended');const homeTeam = this.elements.homeTeamName.textContent;const awayTeam = this.elements.awayTeamName.textContent;if (this.gameState.homeScore > this.gameState.awayScore) {this.addEvent(`GAME OVER! ${homeTeam} WINS!`);document.querySelector('.home-team').classList.add('leading-team');} else if (this.gameState.awayScore > this.gameState.homeScore) {this.addEvent(`GAME OVER! ${awayTeam} WINS!`);document.querySelector('.away-team').classList.add('leading-team');} else {this.addEvent('GAME OVER! TIE GAME!');}this.updateGameStatus();}updateDisplay() {// 更新分数 - 数字显示this.updateDigitalScore(this.elements.homeScore, this.gameState.homeScore);this.updateDigitalScore(this.elements.awayScore, this.gameState.awayScore);// 更新时间this.updateTimeDisplay();this.updateShotClockDisplay();// 更新节数this.elements.quarter.textContent = this.gameState.quarter;// 更新统计this.updateDigitalStat(this.elements.homeFouls, this.gameState.homeFouls);this.updateDigitalStat(this.elements.awayFouls, this.gameState.awayFouls);this.updateDigitalStat(this.elements.homeTimeouts, this.gameState.homeTimeouts);this.updateDigitalStat(this.elements.awayTimeouts, this.gameState.awayTimeouts);// 更新分节比分this.updateQuarterScores();// 更新游戏状态this.updateGameStatus();// 更新领先队伍高亮this.updateLeadingTeam();}updateDigitalScore(element, score) {const scoreStr = score.toString().padStart(3, '0');const digits = element.querySelectorAll('.digit');for (let i = 0; i < 3; i++) {if (digits[i]) {digits[i].textContent = scoreStr[i];}}}updateDigitalStat(element, value) {const valueStr = value.toString().padStart(2, '0');element.textContent = valueStr;}updateTimeDisplay() {const minutes = Math.floor(this.gameState.gameTime / 60);const seconds = this.gameState.gameTime % 60;const timeDigits = this.elements.gameTime.querySelectorAll('.time-digit');const minutesStr = minutes.toString().padStart(2, '0');const secondsStr = seconds.toString().padStart(2, '0');if (timeDigits[0]) timeDigits[0].textContent = minutesStr[0];if (timeDigits[1]) timeDigits[1].textContent = minutesStr[1];if (timeDigits[2]) timeDigits[2].textContent = secondsStr[0];if (timeDigits[3]) timeDigits[3].textContent = secondsStr[1];}updateShotClockDisplay() {const shotStr = this.gameState.shotClock.toString().padStart(2, '0');const shotDigits = this.elements.shotClock.querySelectorAll('.shot-digit');if (shotDigits[0]) shotDigits[0].textContent = shotStr[0];if (shotDigits[1]) shotDigits[1].textContent = shotStr[1];}updateQuarterScores() {const quarters = ['Q1', 'Q2', 'Q3', 'Q4'];quarters.forEach((q, index) => {const homeScore = this.gameState.quarterScores.home[index].toString().padStart(2, '0');const awayScore = this.gameState.quarterScores.away[index].toString().padStart(2, '0');this.elements[`home${q}`].textContent = homeScore;this.elements[`away${q}`].textContent = awayScore;});this.elements.homeTotal.textContent = this.gameState.homeScore.toString().padStart(3, '0');this.elements.awayTotal.textContent = this.gameState.awayScore.toString().padStart(3, '0');}updateGameStatus() {if (this.gameState.isGameEnded) {this.elements.gameStatus.textContent = 'FINAL';this.elements.gameStatus.style.color = '#ff0000';} else if (this.gameState.isPaused) {this.elements.gameStatus.textContent = 'PAUSED';this.elements.gameStatus.style.color = '#ffff00';} else if (this.gameState.isRunning) {this.elements.gameStatus.textContent = 'LIVE';this.elements.gameStatus.style.color = '#00ff00';} else {this.elements.gameStatus.textContent = 'READY';this.elements.gameStatus.style.color = '#00ffff';}}updateLeadingTeam() {const homeTeamElement = document.querySelector('.home-team');const awayTeamElement = document.querySelector('.away-team');homeTeamElement.classList.remove('leading-team');awayTeamElement.classList.remove('leading-team');if (!this.gameState.isGameEnded) {if (this.gameState.homeScore > this.gameState.awayScore) {homeTeamElement.classList.add('leading-team');} else if (this.gameState.awayScore > this.gameState.homeScore) {awayTeamElement.classList.add('leading-team');}}}addEvent(eventText) {const now = new Date();const timeStr = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}`;this.events.unshift(`[${timeStr}] ${eventText}`);if (this.events.length > this.maxEvents) {this.events = this.events.slice(0, this.maxEvents);}this.updateEventsDisplay();}updateEventsDisplay() {this.elements.eventsList.innerHTML = this.events.map(event => `<div class="event-line">${event}</div>`).join('');}
}// 初始化复古计分板
document.addEventListener('DOMContentLoaded', () => {new RetroBasketballScoreboard();
});
styles-crt.css
/* 全局重置和基础样式 */
* {margin: 0;padding: 0;box-sizing: border-box;
}body {font-family: 'Share Tech Mono', monospace;background: #0a0a0a;color: #00ff00;overflow: hidden;height: 100vh;display: flex;justify-content: center;align-items: center;
}/* CRT 容器 */
.crt-container {width: 95vw;height: 95vh;max-width: 1400px;max-height: 900px;position: relative;
}/* CRT 显示器外框 */
.crt-frame {width: 100%;height: 100%;background: linear-gradient(145deg, #2a2a2a, #1a1a1a);border-radius: 20px;padding: 40px;box-shadow: inset 0 0 50px rgba(0, 0, 0, 0.8),0 0 100px rgba(0, 0, 0, 0.9);position: relative;
}/* CRT 屏幕 */
.crt-screen {width: 100%;height: 100%;background: #000;border-radius: 10px;position: relative;overflow: hidden;border: 3px solid #333;box-shadow: inset 0 0 30px rgba(0, 255, 0, 0.1),inset 0 0 100px rgba(0, 0, 0, 0.8);
}/* 扫描线效果 */
.scanlines {position: absolute;top: 0;left: 0;width: 100%;height: 100%;background: repeating-linear-gradient(0deg,transparent,transparent 2px,rgba(0, 255, 0, 0.03) 2px,rgba(0, 255, 0, 0.03) 4px);pointer-events: none;z-index: 1000;
}/* 计分板内容 */
.scoreboard-content {width: 100%;height: 100%;padding: 30px;display: flex;flex-direction: column;position: relative;z-index: 10;
}/* 顶部标题区域 */
.header {display: flex;justify-content: space-between;align-items: center;margin-bottom: 30px;border-bottom: 2px solid #00ff00;padding-bottom: 20px;
}/* 点阵文字效果 */
.dot-matrix-text {font-family: 'Orbitron', monospace;font-size: 1.8rem;font-weight: 900;text-align: center;line-height: 1.2;
}.matrix-char {display: inline-block;color: #00ff00;text-shadow: 0 0 5px #00ff00,0 0 10px #00ff00,0 0 15px #00ff00;animation: matrixGlow 2s ease-in-out infinite alternate;margin: 0 2px;
}.matrix-char:nth-child(odd) {animation-delay: 0.1s;
}.matrix-char:nth-child(even) {animation-delay: 0.2s;
}@keyframes matrixGlow {0% { opacity: 0.8;text-shadow: 0 0 5px #00ff00,0 0 10px #00ff00,0 0 15px #00ff00;}100% { opacity: 1;text-shadow: 0 0 8px #00ff00,0 0 15px #00ff00,0 0 25px #00ff00;}
}/* 状态指示器 */
.status-indicators {display: flex;gap: 30px;
}.indicator {text-align: center;
}.label {display: block;font-size: 0.8rem;color: #888;margin-bottom: 5px;letter-spacing: 2px;
}.digital-display {font-family: 'Orbitron', monospace;font-size: 2rem;font-weight: 900;color: #00ff00;text-shadow: 0 0 10px #00ff00,0 0 20px #00ff00;background: rgba(0, 255, 0, 0.1);padding: 5px 15px;border: 2px solid #00ff00;border-radius: 5px;
}.status-text {font-family: 'Orbitron', monospace;font-size: 1.2rem;font-weight: 700;color: #ffff00;text-shadow: 0 0 10px #ffff00,0 0 20px #ffff00;background: rgba(255, 255, 0, 0.1);padding: 5px 15px;border: 2px solid #ffff00;border-radius: 5px;
}/* 主显示区域 */
.main-display {display: grid;grid-template-columns: 1fr auto 1fr;gap: 40px;flex: 1;align-items: center;
}/* 队伍区域 */
.team-section {display: flex;flex-direction: column;align-items: center;gap: 20px;
}.team-header {text-align: center;
}.team-label {display: block;font-size: 1rem;color: #888;letter-spacing: 3px;margin-bottom: 10px;
}.team-name {font-family: 'Orbitron', monospace;font-size: 1.5rem;font-weight: 900;color: #00ff00;text-shadow: 0 0 10px #00ff00,0 0 20px #00ff00;letter-spacing: 2px;border: 2px solid #00ff00;padding: 10px 20px;background: rgba(0, 255, 0, 0.05);
}/* 数字显示效果 */
.digital-score {display: flex;gap: 5px;justify-content: center;margin: 20px 0;
}.digit {font-family: 'Orbitron', monospace;font-size: 4rem;font-weight: 900;color: #00ff00;text-shadow: 0 0 15px #00ff00,0 0 30px #00ff00,0 0 45px #00ff00;background: rgba(0, 0, 0, 0.8);border: 3px solid #00ff00;border-radius: 8px;padding: 10px 15px;min-width: 80px;text-align: center;position: relative;overflow: hidden;
}.digit::before {content: '8';position: absolute;top: 10px;left: 15px;color: rgba(0, 255, 0, 0.1);z-index: -1;
}/* 队伍统计 */
.team-stats {display: flex;gap: 20px;
}.stat-item {text-align: center;
}.stat-label {display: block;font-size: 0.8rem;color: #888;margin-bottom: 5px;letter-spacing: 1px;
}.digital-small {font-family: 'Orbitron', monospace;font-size: 1.5rem;font-weight: 700;color: #00ff00;text-shadow: 0 0 8px #00ff00,0 0 15px #00ff00;background: rgba(0, 0, 0, 0.8);border: 2px solid #00ff00;border-radius: 5px;padding: 5px 10px;min-width: 50px;text-align: center;
}/* 中央时钟区域 */
.center-clock {display: flex;flex-direction: column;align-items: center;gap: 25px;background: rgba(0, 255, 0, 0.05);border: 3px solid #00ff00;border-radius: 15px;padding: 30px;min-width: 300px;
}.clock-label {font-size: 1rem;color: #888;letter-spacing: 2px;text-align: center;
}.main-clock {margin: 10px 0;
}.digital-clock {display: flex;align-items: center;gap: 5px;
}.time-digit {font-family: 'Orbitron', monospace;font-size: 3.5rem;font-weight: 900;color: #ff6600;text-shadow: 0 0 15px #ff6600,0 0 30px #ff6600;background: rgba(0, 0, 0, 0.8);border: 3px solid #ff6600;border-radius: 8px;padding: 10px 15px;min-width: 70px;text-align: center;position: relative;
}.time-digit::before {content: '8';position: absolute;top: 10px;left: 15px;color: rgba(255, 102, 0, 0.1);z-index: -1;
}.time-colon {font-family: 'Orbitron', monospace;font-size: 3rem;font-weight: 900;color: #ff6600;text-shadow: 0 0 15px #ff6600,0 0 30px #ff6600;animation: colonBlink 1s infinite;
}@keyframes colonBlink {0%, 50% { opacity: 1; }51%, 100% { opacity: 0.3; }
}/* 进攻时间 */
.shot-clock-display {margin: 10px 0;
}.digital-shot-clock {display: flex;gap: 5px;
}.shot-digit {font-family: 'Orbitron', monospace;font-size: 2.5rem;font-weight: 900;color: #00ffff;text-shadow: 0 0 15px #00ffff,0 0 30px #00ffff;background: rgba(0, 0, 0, 0.8);border: 3px solid #00ffff;border-radius: 8px;padding: 8px 12px;min-width: 60px;text-align: center;position: relative;
}.shot-digit::before {content: '8';position: absolute;top: 8px;left: 12px;color: rgba(0, 255, 255, 0.1);z-index: -1;
}.shot-digit.warning {color: #ff0000;border-color: #ff0000;text-shadow: 0 0 15px #ff0000,0 0 30px #ff0000;animation: warningBlink 0.5s infinite;
}@keyframes warningBlink {0%, 50% { opacity: 1; }51%, 100% { opacity: 0.5; }
}/* 控制面板 */
.control-panel {display: flex;flex-wrap: wrap;gap: 10px;justify-content: center;
}.retro-btn {font-family: 'Orbitron', monospace;font-size: 0.9rem;font-weight: 700;background: rgba(0, 0, 0, 0.8);color: #00ff00;border: 2px solid #00ff00;border-radius: 5px;padding: 10px 20px;cursor: pointer;transition: all 0.3s ease;text-transform: uppercase;letter-spacing: 1px;text-shadow: 0 0 10px #00ff00;
}.retro-btn:hover {background: rgba(0, 255, 0, 0.1);box-shadow: 0 0 20px #00ff00,inset 0 0 20px rgba(0, 255, 0, 0.1);
}.retro-btn:active {transform: scale(0.95);
}.retro-btn:disabled {opacity: 0.5;cursor: not-allowed;
}.simulate-btn {color: #ffff00;border-color: #ffff00;text-shadow: 0 0 10px #ffff00;
}.simulate-btn:hover {background: rgba(255, 255, 0, 0.1);box-shadow: 0 0 20px #ffff00,inset 0 0 20px rgba(255, 255, 0, 0.1);
}/* 底部区域 */
.bottom-section {display: grid;grid-template-columns: 1fr 1fr;gap: 30px;margin-top: 30px;border-top: 2px solid #00ff00;padding-top: 20px;
}.section-title {font-family: 'Orbitron', monospace;font-size: 1rem;font-weight: 700;color: #00ff00;text-shadow: 0 0 10px #00ff00;letter-spacing: 2px;margin-bottom: 15px;text-align: center;border-bottom: 1px solid #00ff00;padding-bottom: 5px;
}/* 分节比分 */
.quarter-grid {display: flex;flex-direction: column;gap: 5px;
}.quarter-header,
.quarter-row {display: grid;grid-template-columns: 2fr 1fr 1fr 1fr 1fr 1.5fr;gap: 10px;align-items: center;
}.quarter-header {font-size: 0.8rem;color: #888;letter-spacing: 1px;border-bottom: 1px solid #333;padding-bottom: 5px;
}.quarter-row {padding: 5px 0;
}.qr-team {font-family: 'Orbitron', monospace;font-weight: 700;color: #00ff00;text-shadow: 0 0 5px #00ff00;
}.digital-mini {font-family: 'Orbitron', monospace;font-size: 1rem;font-weight: 700;color: #00ff00;text-shadow: 0 0 5px #00ff00;background: rgba(0, 0, 0, 0.8);border: 1px solid #00ff00;border-radius: 3px;padding: 3px 8px;text-align: center;
}/* 事件日志 */
.events-display {height: 120px;overflow-y: auto;background: rgba(0, 0, 0, 0.8);border: 2px solid #00ff00;border-radius: 5px;padding: 10px;
}.events-list {display: flex;flex-direction: column;gap: 3px;
}.event-line {font-family: 'Share Tech Mono', monospace;font-size: 0.8rem;color: #00ff00;text-shadow: 0 0 5px #00ff00;padding: 2px 0;border-bottom: 1px solid rgba(0, 255, 0, 0.2);animation: eventAppear 0.5s ease-in;
}@keyframes eventAppear {0% { opacity: 0; transform: translateX(-20px); }100% { opacity: 1; transform: translateX(0); }
}/* CRT 效果层 */
.crt-effects {position: absolute;top: 0;left: 0;width: 100%;height: 100%;pointer-events: none;z-index: 1001;
}.screen-flicker {position: absolute;top: 0;left: 0;width: 100%;height: 100%;background: rgba(0, 255, 0, 0.02);animation: flicker 0.15s infinite linear alternate;
}@keyframes flicker {0% { opacity: 1; }100% { opacity: 0.98; }
}.screen-curve {position: absolute;top: 0;left: 0;width: 100%;height: 100%;border-radius: 10px;box-shadow: inset 0 0 100px rgba(0, 0, 0, 0.3),inset 0 0 200px rgba(0, 0, 0, 0.2);
}/* CRT 边框装饰 */
.crt-bezel {position: absolute;bottom: 10px;right: 20px;display: flex;align-items: center;gap: 15px;
}.power-indicator {width: 12px;height: 12px;background: #00ff00;border-radius: 50%;box-shadow: 0 0 10px #00ff00,0 0 20px #00ff00;animation: powerBlink 2s infinite;
}@keyframes powerBlink {0%, 90% { opacity: 1; }95%, 100% { opacity: 0.5; }
}.brand-label {font-family: 'Orbitron', monospace;font-size: 0.8rem;color: #666;letter-spacing: 2px;
}/* 滚动条样式 */
.events-display::-webkit-scrollbar {width: 6px;
}.events-display::-webkit-scrollbar-track {background: rgba(0, 0, 0, 0.5);
}.events-display::-webkit-scrollbar-thumb {background: #00ff00;border-radius: 3px;box-shadow: 0 0 5px #00ff00;
}/* 响应式设计 */
@media (max-width: 1200px) {.main-display {grid-template-columns: 1fr;gap: 20px;}.center-clock {order: -1;}.bottom-section {grid-template-columns: 1fr;}
}@media (max-width: 768px) {.crt-frame {padding: 20px;}.scoreboard-content {padding: 15px;}.digit {font-size: 3rem;min-width: 60px;padding: 8px 12px;}.time-digit {font-size: 2.5rem;min-width: 50px;padding: 8px 12px;}.dot-matrix-text {font-size: 1.2rem;}.control-panel {flex-direction: column;width: 100%;}.retro-btn {width: 100%;}
}/* 特殊状态样式 */
.game-paused .time-digit {color: #ffff00;border-color: #ffff00;text-shadow: 0 0 15px #ffff00,0 0 30px #ffff00;
}.game-ended .time-digit {color: #ff0000;border-color: #ff0000;text-shadow: 0 0 15px #ff0000,0 0 30px #ff0000;
}.leading-team .team-name {color: #ffff00;border-color: #ffff00;text-shadow: 0 0 15px #ffff00,0 0 30px #ffff00;animation: leadingGlow 1s infinite alternate;
}@keyframes leadingGlow {0% { box-shadow: 0 0 20px rgba(255, 255, 0, 0.5);}100% { box-shadow: 0 0 40px rgba(255, 255, 0, 0.8);}
}
