<!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>
:root {
--primary-color: #3498db;
--secondary-color: #2c3e50;
--accent-color: #e74c3c;
--background-color: #1a2a6c;
--card-bg: #2c3e50;
--text-color: #ecf0f1;
--border-color: #34495e;
--success-color: #2ecc71;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
background: var(--background-color);
color: var(--text-color);
min-height: 100vh;
padding: 15px;
transition: background-color 0.5s, color 0.5s;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
header {
text-align: center;
margin-bottom: 25px;
padding: 15px;
}
h1 {
font-size: 2.2rem;
margin-bottom: 8px;
color: var(--primary-color);
text-shadow: 0 0 10px rgba(52, 152, 219, 0.5);
}
.subtitle {
font-size: 1.1rem;
color: #bdc3c7;
}
.tabs {
display: flex;
justify-content: center;
margin-bottom: 25px;
flex-wrap: wrap;
gap: 8px;
}
.tab-btn {
padding: 12px 22px;
background: var(--card-bg);
border: 2px solid var(--border-color);
color: var(--text-color);
border-radius: 30px;
cursor: pointer;
font-weight: 600;
transition: all 0.3s;
outline: none;
white-space: nowrap;
}
.tab-btn.active {
background: var(--primary-color);
border-color: var(--primary-color);
box-shadow: 0 0 15px rgba(52, 152, 219, 0.5);
}
.tab-btn:hover:not(.active) {
background: rgba(255, 255, 255, 0.1);
}
.tab-content {
display: none;
background: var(--card-bg);
border-radius: 15px;
padding: 25px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
border: 1px solid var(--border-color);
}
.tab-content.active {
display: block;
animation: fadeIn 0.5s ease;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.display-container {
display: flex;
justify-content: center;
align-items: center;
margin: 20px 0;
}
.clock-display, .stopwatch-display, .countdown-display {
font-size: 4rem;
font-weight: 700;
font-family: 'Courier New', monospace;
letter-spacing: 2px;
text-shadow: 0 0 15px rgba(52, 152, 219, 0.7);
background: rgba(0, 0, 0, 0.2);
padding: 15px 30px;
border-radius: 10px;
min-width: 300px;
text-align: center;
}
.milliseconds {
font-size: 2.5rem;
color: var(--primary-color);
}
.date-display {
text-align: center;
font-size: 1.3rem;
margin-bottom: 25px;
color: #bdc3c7;
}
.controls {
display: flex;
justify-content: center;
gap: 12px;
margin: 25px 0;
flex-wrap: wrap;
}
.btn {
padding: 12px 22px;
border: none;
border-radius: 50px;
cursor: pointer;
font-weight: 600;
transition: all 0.3s;
min-width: 110px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
display: flex;
align-items: center;
justify-content: center;
}
.btn-primary {
background: var(--primary-color);
color: white;
}
.btn-secondary {
background: var(--secondary-color);
color: white;
}
.btn-danger {
background: var(--accent-color);
color: white;
}
.btn-success {
background: var(--success-color);
color: white;
}
.btn:hover {
transform: translateY(-3px);
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.3);
}
.btn:active {
transform: translateY(1px);
}
.btn:disabled {
opacity: 0.6;
cursor: not-allowed;
transform: none;
}
.timer-input {
display: flex;
justify-content: center;
gap: 15px;
margin: 20px 0;
flex-wrap: wrap;
}
.input-group {
display: flex;
flex-direction: column;
align-items: center;
}
.input-group label {
margin-bottom: 8px;
font-weight: 600;
font-size: 0.9rem;
}
.input-group input {
width: 70px;
padding: 10px;
border-radius: 10px;
border: 2px solid var(--border-color);
background: rgba(0, 0, 0, 0.2);
color: var(--text-color);
text-align: center;
font-size: 1.1rem;
}
.history-panel {
background: rgba(0, 0, 0, 0.2);
border-radius: 10px;
padding: 20px;
margin-top: 25px;
max-height: 250px;
overflow-y: auto;
}
.history-title {
font-size: 1.3rem;
margin-bottom: 15px;
color: var(--primary-color);
text-align: center;
}
.history-list {
list-style-type: none;
}
.history-item {
padding: 12px 15px;
border-bottom: 1px solid var(--border-color);
display: flex;
justify-content: space-between;
font-family: 'Courier New', monospace;
}
.history-item:last-child {
border-bottom: none;
}
.settings-panel {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 20px;
margin-top: 20px;
}
.setting-card {
background: rgba(0, 0, 0, 0.2);
padding: 20px;
border-radius: 10px;
}
.setting-title {
font-size: 1.2rem;
margin-bottom: 15px;
color: var(--primary-color);
}
.theme-options {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-top: 10px;
}
.theme-option {
width: 30px;
height: 30px;
border-radius: 50%;
cursor: pointer;
border: 2px solid transparent;
transition: transform 0.2s;
}
.theme-option:hover {
transform: scale(1.2);
}
.theme-option.active {
border-color: white;
transform: scale(1.2);
}
.color-blue { background: linear-gradient(135deg, #3498db, #1a2a6c); }
.color-green { background: linear-gradient(135deg, #2ecc71, #27ae60); }
.color-red { background: linear-gradient(135deg, #e74c3c, #c0392b); }
.color-purple { background: linear-gradient(135deg, #9b59b6, #8e44ad); }
.color-orange { background: linear-gradient(135deg, #e67e22, #d35400); }
.color-teal { background: linear-gradient(135deg, #1abc9c, #16a085); }
.custom-color {
display: flex;
align-items: center;
gap: 10px;
margin-top: 10px;
}
.custom-color input {
width: 100%;
padding: 8px;
border-radius: 5px;
border: 1px solid var(--border-color);
background: rgba(0, 0, 0, 0.2);
color: var(--text-color);
}
.font-size-control {
display: flex;
align-items: center;
gap: 10px;
margin-top: 10px;
}
.font-size-control input {
flex: 1;
}
footer {
text-align: center;
margin-top: 30px;
padding: 15px;
color: #7f8c8d;
font-size: 0.85rem;
}
/* 桌面端优化 */
@media (min-width: 1024px) {
.container {
padding: 20px;
}
h1 {
font-size: 2.5rem;
}
.clock-display, .stopwatch-display, .countdown-display {
font-size: 5rem;
padding: 20px 40px;
min-width: 400px;
}
.milliseconds {
font-size: 3rem;
}
.date-display {
font-size: 1.5rem;
}
.btn {
padding: 14px 25px;
min-width: 130px;
}
.tab-btn {
padding: 14px 25px;
}
.history-panel {
max-height: 350px;
}
}
/* 横屏模式优化 */
@media (orientation: landscape) and (max-height: 500px) {
.clock-display, .stopwatch-display, .countdown-display {
font-size: 3rem;
padding: 10px 20px;
min-width: 250px;
}
.milliseconds {
font-size: 1.8rem;
}
.controls {
gap: 8px;
margin: 15px 0;
}
.btn {
padding: 10px 18px;
min-width: 90px;
font-size: 0.9rem;
}
.tab-btn {
padding: 10px 18px;
font-size: 0.9rem;
}
.history-panel {
max-height: 150px;
}
}
/* 小屏幕设备优化 */
@media (max-width: 480px) {
.clock-display, .stopwatch-display, .countdown-display {
font-size: 2.5rem;
min-width: 200px;
padding: 10px 15px;
}
.milliseconds {
font-size: 1.8rem;
}
.date-display {
font-size: 1.1rem;
}
.btn {
padding: 10px 15px;
min-width: 90px;
font-size: 0.85rem;
}
.tab-btn {
padding: 10px 15px;
font-size: 0.85rem;
}
.input-group input {
width: 60px;
font-size: 1rem;
}
.history-panel {
max-height: 200px;
}
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>多功能时钟</h1>
<p class="subtitle">时钟 | 秒表 | 倒计时 | 个性化设置</p>
</header>
<div class="tabs">
<button class="tab-btn active" data-tab="clock">时钟</button>
<button class="tab-btn" data-tab="stopwatch">秒表</button>
<button class="tab-btn" data-tab="countdown">倒计时</button>
<button class="tab-btn" data-tab="settings">设置</button>
</div>
<!-- 时钟标签页 -->
<div id="clock" class="tab-content active">
<div class="display-container">
<div class="clock-display" id="current-time">00:00:00</div>
</div>
<div class="date-display" id="current-date">Monday, January 1, 2023</div>
<div class="settings-panel">
<div class="setting-card">
<h3 class="setting-title">时钟设置</h3>
<label>
<input type="checkbox" id="24hour-format"> 使用24小时制
</label>
<br><br>
<label>
<input type="checkbox" id="show-seconds" checked> 显示秒
</label>
</div>
<div class="setting-card">
<h3 class="setting-title">时间格式</h3>
<select id="time-zone" style="width: 100%; padding: 10px; margin-top: 10px; border-radius: 5px; background: rgba(0,0,0,0.2); color: white; border: 1px solid #34495e;">
<option value="local">本地时间</option>
<option value="UTC">协调世界时 (UTC)</option>
<option value="America/New_York">纽约时间</option>
<option value="Europe/London">伦敦时间</option>
<option value="Asia/Tokyo">东京时间</option>
</select>
</div>
</div>
</div>
<!-- 秒表标签页 -->
<div id="stopwatch" class="tab-content">
<div class="display-container">
<div class="stopwatch-display" id="stopwatch-time">00:00:00</div>
</div>
<div class="controls">
<button id="start-stop-btn" class="btn btn-primary">开始</button>
<button id="lap-btn" class="btn btn-secondary" disabled>圈数</button>
<button id="reset-btn" class="btn btn-danger">重置</button>
</div>
<div class="history-panel">
<h3 class="history-title">圈数历史</h3>
<ul class="history-list" id="lap-history">
<!-- 圈数历史将在这里添加 -->
</ul>
</div>
</div>
<!-- 倒计时标签页 -->
<div id="countdown" class="tab-content">
<div class="display-container">
<div class="countdown-display" id="countdown-time">00:00:00</div>
</div>
<div class="timer-input">
<div class="input-group">
<label for="hours">小时</label>
<input type="number" id="hours" min="0" max="23" value="0">
</div>
<div class="input-group">
<label for="minutes">分钟</label>
<input type="number" id="minutes" min="0" max="59" value="5">
</div>
<div class="input-group">
<label for="seconds">秒</label>
<input type="number" id="seconds" min="0" max="59" value="0">
</div>
</div>
<div class="controls">
<button id="start-countdown" class="btn btn-primary">开始</button>
<button id="pause-countdown" class="btn btn-secondary" disabled>暂停</button>
<button id="reset-countdown" class="btn btn-danger">重置</button>
</div>
</div>
<!-- 设置标签页 -->
<div id="settings" class="tab-content">
<h2 style="text-align: center; margin-bottom: 20px;">个性化设置</h2>
<div class="settings-panel">
<div class="setting-card">
<h3 class="setting-title">主题颜色</h3>
<div class="theme-options">
<div class="theme-option color-blue active" data-theme="blue"></div>
<div class="theme-option color-green" data-theme="green"></div>
<div class="theme-option color-red" data-theme="red"></div>
<div class="theme-option color-purple" data-theme="purple"></div>
<div class="theme-option color-orange" data-theme="orange"></div>
<div class="theme-option color-teal" data-theme="teal"></div>
</div>
<div class="custom-color">
<label for="custom-color">自定义颜色:</label>
<input type="color" id="custom-color" value="#3498db">
</div>
</div>
<div class="setting-card">
<h3 class="setting-title">字体大小</h3>
<div class="font-size-control">
<label for="font-size">主显示:</label>
<input type="range" id="font-size" min="2" max="6" step="0.5" value="4">
<span id="font-size-value">4rem</span>
</div>
</div>
<div class="setting-card">
<h3 class="setting-title">显示选项</h3>
<label>
<input type="checkbox" id="show-date" checked> 显示日期
</label>
<br><br>
<label>
<input type="checkbox" id="show-weekday"> 显示星期几
</label>
<br><br>
<label>
<input type="checkbox" id="digital-style" checked> 数字风格
</label>
</div>
</div>
</div>
<footer>
<p>多功能时钟应用 © 2023 | 支持秒表、倒计时、个性化设置</p>
</footer>
</div>
<script>
// 当前活动标签页管理
const tabBtns = document.querySelectorAll('.tab-btn');
const tabContents = document.querySelectorAll('.tab-content');
tabBtns.forEach(btn => {
btn.addEventListener('click', () => {
// 移除所有激活状态
tabBtns.forEach(b => b.classList.remove('active'));
tabContents.forEach(c => c.classList.remove('active'));
// 激活当前标签
btn.classList.add('active');
document.getElementById(btn.dataset.tab).classList.add('active');
});
});
// 时钟功能
function updateClock() {
const now = new Date();
const timeOptions = {
hour: '2-digit',
minute: '2-digit',
second: showSeconds ? '2-digit' : undefined,
hour12: !hour24Format.checked
};
const timeString = now.toLocaleTimeString('zh-CN', timeOptions);
currentTimeEl.textContent = timeString;
let dateStr = now.toLocaleDateString('zh-CN', {
year: 'numeric',
month: 'long',
day: 'numeric'
});
if (showWeekday.checked) {
const weekdays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
dateStr += ` (${weekdays[now.getDay()]})`;
}
currentDateEl.textContent = dateStr;
}
const currentTimeEl = document.getElementById('current-time');
const currentDateEl = document.getElementById('current-date');
const hour24Format = document.getElementById('24hour-format');
const showSeconds = document.getElementById('show-seconds');
const showWeekday = document.getElementById('show-weekday');
// 初始更新时钟
updateClock();
setInterval(updateClock, 1000);
// 秒表功能
let stopwatchInterval = null;
let stopwatchRunning = false;
let stopwatchTime = 0;
let lapCount = 1;
const stopwatchDisplay = document.getElementById('stopwatch-time');
const startStopBtn = document.getElementById('start-stop-btn');
const lapBtn = document.getElementById('lap-btn');
const resetBtn = document.getElementById('reset-btn');
const lapHistory = document.getElementById('lap-history');
function updateStopwatch() {
const hours = Math.floor(stopwatchTime / 3600000);
const minutes = Math.floor((stopwatchTime % 3600000) / 60000);
const seconds = Math.floor((stopwatchTime % 60000) / 1000);
const milliseconds = Math.floor((stopwatchTime % 1000) / 10);
stopwatchDisplay.textContent =
`${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}.${milliseconds.toString().padStart(2, '0')}`;
}
startStopBtn.addEventListener('click', () => {
if (!stopwatchRunning) {
// 开始
stopwatchStartTime = Date.now() - stopwatchTime;
stopwatchInterval = setInterval(() => {
stopwatchTime = Date.now() - stopwatchStartTime;
updateStopwatch();
}, 10);
startStopBtn.textContent = '暂停';
lapBtn.disabled = false;
stopwatchRunning = true;
} else {
// 暂停
clearInterval(stopwatchInterval);
startStopBtn.textContent = '继续';
stopwatchRunning = false;
}
});
resetBtn.addEventListener('click', () => {
clearInterval(stopwatchInterval);
stopwatchTime = 0;
updateStopwatch();
startStopBtn.textContent = '开始';
lapBtn.disabled = true;
stopwatchRunning = false;
lapCount = 1;
lapHistory.innerHTML = '';
});
lapBtn.addEventListener('click', () => {
if (stopwatchRunning) {
const lapItem = document.createElement('li');
lapItem.className = 'history-item';
const lapNumber = document.createElement('span');
lapNumber.textContent = `圈数 ${lapCount}`;
lapNumber.style.fontWeight = 'bold';
const lapTime = document.createElement('span');
lapTime.textContent = stopwatchDisplay.textContent;
lapItem.appendChild(lapNumber);
lapItem.appendChild(lapTime);
lapHistory.appendChild(lapItem);
lapCount++;
// 滚动到最新圈数
lapHistory.scrollTop = lapHistory.scrollHeight;
}
});
// 倒计时功能
let countdownInterval = null;
let countdownActive = false;
let countdownTime = 0;
const countdownDisplay = document.getElementById('countdown-time');
const startCountdownBtn = document.getElementById('start-countdown');
const pauseCountdownBtn = document.getElementById('pause-countdown');
const resetCountdownBtn = document.getElementById('reset-countdown');
const hoursInput = document.getElementById('hours');
const minutesInput = document.getElementById('minutes');
const secondsInput = document.getElementById('seconds');
function updateCountdownDisplay() {
const hours = Math.floor(countdownTime / 3600000);
const minutes = Math.floor((countdownTime % 3600000) / 60000);
const seconds = Math.floor((countdownTime % 60000) / 1000);
const milliseconds = Math.floor((countdownTime % 1000) / 10);
countdownDisplay.textContent =
`${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}.${milliseconds.toString().padStart(2, '0')}`;
}
startCountdownBtn.addEventListener('click', () => {
if (!countdownActive) {
// 开始倒计时
const hours = parseInt(hoursInput.value) || 0;
const minutes = parseInt(minutesInput.value) || 0;
const seconds = parseInt(secondsInput.value) || 0;
countdownTime = (hours * 3600000) + (minutes * 60000) + (seconds * 1000);
if (countdownTime <= 0) {
alert('请设置有效的时间!');
return;
}
countdownStartTime = Date.now() + countdownTime;
countdownInterval = setInterval(() => {
countdownTime = countdownStartTime - Date.now();
if (countdownTime <= 0) {
clearInterval(countdownInterval);
countdownTime = 0;
updateCountdownDisplay();
countdownActive = false;
startCountdownBtn.disabled = false;
pauseCountdownBtn.disabled = true;
alert('倒计时结束!');
return;
}
updateCountdownDisplay();
}, 10);
countdownActive = true;
startCountdownBtn.disabled = true;
pauseCountdownBtn.disabled = false;
}
});
pauseCountdownBtn.addEventListener('click', () => {
if (countdownActive) {
clearInterval(countdownInterval);
countdownActive = false;
startCountdownBtn.disabled = false;
pauseCountdownBtn.disabled = true;
}
});
resetCountdownBtn.addEventListener('click', () => {
clearInterval(countdownInterval);
countdownActive = false;
countdownTime = 0;
updateCountdownDisplay();
startCountdownBtn.disabled = false;
pauseCountdownBtn.disabled = true;
});
// 主题设置
const themeOptions = document.querySelectorAll('.theme-option');
const customColorPicker = document.getElementById('custom-color');
themeOptions.forEach(option => {
option.addEventListener('click', () => {
// 移除所有激活状态
themeOptions.forEach(opt => opt.classList.remove('active'));
// 激活当前选项
option.classList.add('active');
// 应用主题
applyTheme(option.dataset.theme);
});
});
customColorPicker.addEventListener('input', (e) => {
// 移除所有激活状态
themeOptions.forEach(opt => opt.classList.remove('active'));
// 应用自定义颜色
document.documentElement.style.setProperty('--primary-color', e.target.value);
});
function applyTheme(theme) {
switch(theme) {
case 'blue':
document.documentElement.style.setProperty('--primary-color', '#3498db');
break;
case 'green':
document.documentElement.style.setProperty('--primary-color', '#2ecc71');
break;
case 'red':
document.documentElement.style.setProperty('--primary-color', '#e74c3c');
break;
case 'purple':
document.documentElement.style.setProperty('--primary-color', '#9b59b6');
break;
case 'orange':
document.documentElement.style.setProperty('--primary-color', '#e67e22');
break;
case 'teal':
document.documentElement.style.setProperty('--primary-color', '#1abc9c');
break;
}
}
// 字体大小设置
const fontSizeControl = document.getElementById('font-size');
const fontSizeValue = document.getElementById('font-size-value');
fontSizeControl.addEventListener('input', (e) => {
const size = e.target.value;
fontSizeValue.textContent = `${size}rem`;
// 更新主要显示元素的字体大小
document.querySelectorAll('.clock-display, .stopwatch-display, .countdown-display').forEach(el => {
el.style.fontSize = `${size}rem`;
});
});
// 初始设置
document.documentElement.style.setProperty('--primary-color', '#3498db');
</script>
</body>
</html>
index.html
index.html