- 多种精美主题
深色主题:经典深色背景
星空之夜:深蓝渐变配合星星效果
海洋之蓝:蓝绿色渐变,清新海洋风格
森林之绿:绿色渐变,自然森林风格
日落橙黄:橙黄色渐变,温暖日落风格 - 表盘样式选择
阿拉伯数字:传统数字显示
罗马数字:古典罗马数字风格
极简刻度:仅显示刻度,无数字 - 动态天气效果
下雪效果:飘落的雪花动画
下雨效果:雨滴下落动画
可根据季节或心情切换 - 音效系统
滴答声:模拟真实钟表声音
整点报时:每小时播放提示音 - 3D交互效果
鼠标移动时时钟会轻微旋转,产生3D立体感
增强用户体验和沉浸感 - 高级视觉特效
动态粒子背景
霓虹光晕效果
文字发光动画
多层次阴影和渐变
源码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>精美模拟时钟</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: linear-gradient(135deg, #1a2a6c, #b21f1f, #fdbb2d);
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: #fff;
overflow: hidden;
position: relative;
transition: background 1.5s ease;
}
/* 动态背景粒子 */
.particles {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
}
.particle {
position: absolute;
border-radius: 50%;
animation: float 15s infinite linear;
}
@keyframes float {
0% {
transform: translateY(0) rotate(0deg);
opacity: 0;
}
10% {
opacity: 1;
}
90% {
opacity: 1;
}
100% {
transform: translateY(-100vh) rotate(360deg);
opacity: 0;
}
}
/* 霓虹光效 */
.neon-glow {
position: absolute;
width: 400px;
height: 400px;
border-radius: 50%;
background: transparent;
filter: blur(50px);
z-index: 2;
animation: pulse 4s infinite alternate;
}
.neon-glow.blue {
background: rgba(0, 153, 255, 0.3);
top: 20%;
left: 10%;
}
.neon-glow.pink {
background: rgba(255, 51, 153, 0.3);
bottom: 20%;
right: 10%;
}
@keyframes pulse {
0% {
transform: scale(0.8);
opacity: 0.5;
}
100% {
transform: scale(1.2);
opacity: 0.8;
}
}
.container {
text-align: center;
padding: 40px;
background: rgba(0, 0, 0, 0.25);
border-radius: 25px;
backdrop-filter: blur(15px);
box-shadow:
0 15px 35px rgba(0, 0, 0, 0.25),
0 0 25px rgba(255, 255, 255, 0.1);
z-index: 10;
position: relative;
border: 1px solid rgba(255, 255, 255, 0.15);
max-width: 90vw;
width: 900px;
transition: all 0.5s ease;
overflow: hidden;
}
/* 容器光效 */
.container::before {
content: '';
position: absolute;
top: -10px;
left: -10px;
right: -10px;
bottom: -10px;
background: linear-gradient(45deg, #ff0066, #ff9900, #33cc33, #3399ff, #ff0066);
background-size: 400%;
z-index: -1;
border-radius: 30px;
animation: glow 10s linear infinite;
filter: blur(20px);
opacity: 0.3;
}
@keyframes glow {
0% {
background-position: 0 0;
}
100% {
background-position: 400% 0;
}
}
h1 {
margin-bottom: 35px;
font-weight: 300;
letter-spacing: 3px;
text-shadow:
0 0 5px rgba(0, 0, 0, 0.5),
0 0 10px rgba(255, 255, 255, 0.3);
display: flex;
align-items: center;
justify-content: center;
gap: 15px;
font-size: 2.2rem;
}
.clock-container {
position: relative;
margin: 0 auto 35px;
width: 320px;
height: 320px;
transition: all 0.5s ease;
perspective: 1000px;
}
.clock {
position: relative;
width: 100%;
height: 100%;
border: 15px solid rgba(255, 255, 255, 0.9);
border-radius: 50%;
box-shadow:
inset 0 0 40px rgba(0, 0, 0, 0.15),
0 8px 25px rgba(0, 0, 0, 0.25),
0 0 0 6px rgba(255, 255, 255, 0.1),
0 0 20px rgba(255, 255, 255, 0.2);
background: rgba(255, 255, 255, 0.95);
display: flex;
justify-content: center;
align-items: center;
transition: all 0.5s ease;
transform-style: preserve-3d;
}
.clock-face {
position: relative;
width: 88%;
height: 88%;
border-radius: 50%;
background: linear-gradient(135deg, #f5f7fa, #e4e8ee);
box-shadow:
inset 0 0 20px rgba(0, 0, 0, 0.1),
0 5px 15px rgba(0, 0, 0, 0.1);
transition: all 0.5s ease;
overflow: hidden;
}
/* 表盘纹理 */
.clock-face::before {
content: '';
position: absolute;
width: 100%;
height: 100%;
background:
radial-gradient(circle at center, transparent 65%, rgba(0, 0, 0, 0.05) 66%),
repeating-radial-gradient(circle at center, rgba(0, 0, 0, 0.03) 0, transparent 1px, transparent 3px);
border-radius: 50%;
}
/* 时钟刻度 */
.marking {
position: absolute;
width: 100%;
height: 100%;
border-radius: 50%;
}
.marking::after {
content: "";
position: absolute;
left: 50%;
width: 2px;
height: 12px;
background: #555;
transform-origin: bottom center;
transform: translateX(-50%);
transition: all 0.5s ease;
}
/* 小时刻度 */
.marking.hour-mark::after {
height: 20px;
width: 5px;
background: #333;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
}
/* 时钟指针 */
.hand {
position: absolute;
bottom: 50%;
left: 50%;
transform-origin: bottom;
border-radius: 5px 5px 0 0;
transition: transform 0.5s cubic-bezier(0.4, 2.3, 0.8, 1);
box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
}
.hour-hand {
width: 10px;
height: 30%;
background: linear-gradient(to top, #333, #555);
transform: translateX(-50%);
z-index: 3;
}
.min-hand {
width: 7px;
height: 40%;
background: linear-gradient(to top, #555, #777);
transform: translateX(-50%);
z-index: 2;
}
.second-hand {
width: 3px;
height: 45%;
background: linear-gradient(to top, #e74c3c, #c0392b);
transform: translateX(-50%);
z-index: 1;
}
/* 中心圆点 */
.center-circle {
position: absolute;
top: 50%;
left: 50%;
width: 20px;
height: 20px;
background: #e74c3c;
border-radius: 50%;
transform: translate(-50%, -50%);
z-index: 10;
box-shadow:
0 0 10px rgba(231, 76, 60, 0.8),
0 0 20px rgba(231, 76, 60, 0.4);
transition: all 0.5s ease;
}
.center-circle::after {
content: "";
position: absolute;
top: 50%;
left: 50%;
width: 8px;
height: 8px;
background: #fff;
border-radius: 50%;
transform: translate(-50%, -50%);
}
/* 数字时间显示 */
.digital-clock {
font-size: 3rem;
font-weight: 300;
letter-spacing: 4px;
margin: 30px 0 20px;
text-shadow:
2px 2px 5px rgba(0, 0, 0, 0.3),
0 0 10px rgba(255, 255, 255, 0.2);
background: rgba(0, 0, 0, 0.2);
padding: 15px 25px;
border-radius: 20px;
display: inline-block;
transition: all 0.5s ease;
font-family: 'Courier New', monospace;
border: 1px solid rgba(255, 255, 255, 0.1);
animation: textGlow 3s infinite alternate;
}
@keyframes textGlow {
0% {
text-shadow:
2px 2px 5px rgba(0, 0, 0, 0.3),
0 0 5px rgba(255, 255, 255, 0.2);
}
100% {
text-shadow:
2px 2px 5px rgba(0, 0, 0, 0.3),
0 0 15px rgba(255, 255, 255, 0.4);
}
}
.date {
font-size: 1.4rem;
margin-bottom: 30px;
font-weight: 300;
text-shadow:
1px 1px 3px rgba(0, 0, 0, 0.3),
0 0 5px rgba(255, 255, 255, 0.1);
display: flex;
align-items: center;
justify-content: center;
gap: 12px;
transition: all 0.5s ease;
}
/* 控制面板 */
.control-panel {
display: flex;
flex-wrap: wrap;
gap: 20px;
justify-content: center;
margin-top: 25px;
}
.control-btn {
background: rgba(255, 255, 255, 0.15);
border: none;
padding: 15px 25px;
border-radius: 50px;
color: white;
font-size: 1.1rem;
cursor: pointer;
transition: all 0.3s ease;
backdrop-filter: blur(5px);
box-shadow:
0 5px 15px rgba(0, 0, 0, 0.2),
0 0 0 1px rgba(255, 255, 255, 0.1);
display: flex;
align-items: center;
gap: 10px;
position: relative;
overflow: hidden;
}
.control-btn::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
transition: all 0.5s ease;
}
.control-btn:hover {
background: rgba(255, 255, 255, 0.25);
transform: translateY(-3px);
box-shadow:
0 8px 20px rgba(0, 0, 0, 0.3),
0 0 0 1px rgba(255, 255, 255, 0.2);
}
.control-btn:hover::before {
left: 100%;
}
.control-btn.active {
background: rgba(255, 255, 255, 0.3);
box-shadow:
0 0 0 2px rgba(255, 255, 255, 0.5),
0 0 15px rgba(255, 255, 255, 0.3);
}
/* 时钟品牌标签 */
.brand {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
font-size: 0.7rem;
font-weight: 300;
letter-spacing: 3px;
color: #777;
text-transform: uppercase;
opacity: 0.7;
}
/* 设置面板 */
.settings-panel {
position: absolute;
top: 20px;
right: 20px;
background: rgba(0, 0, 0, 0.4);
border-radius: 15px;
padding: 20px;
backdrop-filter: blur(10px);
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
width: 320px;
transform: translateX(350px);
transition: transform 0.5s ease;
z-index: 100;
}
.settings-panel.open {
transform: translateX(0);
}
.settings-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 1px solid rgba(255, 255, 255, 0.2);
}
.settings-title {
font-size: 1.2rem;
font-weight: 400;
}
.close-settings {
background: none;
border: none;
color: white;
font-size: 1.5rem;
cursor: pointer;
opacity: 0.7;
transition: opacity 0.3s ease;
}
.close-settings:hover {
opacity: 1;
}
.settings-group {
margin-bottom: 20px;
}
.settings-label {
display: block;
margin-bottom: 8px;
font-size: 0.9rem;
opacity: 0.9;
}
.settings-select, .settings-input {
width: 100%;
padding: 10px 15px;
border-radius: 8px;
border: 1px solid rgba(255, 255, 255, 0.2);
background: rgba(255, 255, 255, 0.1);
color: white;
font-size: 1rem;
backdrop-filter: blur(5px);
}
.settings-select option {
background: rgba(0, 0, 0, 0.8);
color: white;
}
/* 时钟数字样式 */
.clock-number {
position: absolute;
font-weight: bold;
color: #333;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2);
transform-origin: center;
}
/* 天气效果 */
.weather-effect {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 5;
}
.snowflake, .raindrop {
position: absolute;
background: rgba(255, 255, 255, 0.8);
border-radius: 50%;
}
.snowflake {
width: 6px;
height: 6px;
animation: snowfall linear infinite;
}
.raindrop {
width: 3px;
height: 15px;
animation: rainfall linear infinite;
}
@keyframes snowfall {
0% {
transform: translateY(-10px) rotate(0deg);
}
100% {
transform: translateY(100vh) rotate(360deg);
}
}
@keyframes rainfall {
0% {
transform: translateY(-10px);
}
100% {
transform: translateY(100vh);
}
}
/* 主题样式 */
body.theme-night {
background: linear-gradient(135deg, #0f0c29, #302b63, #24243e);
}
body.theme-night .clock {
border: 15px solid rgba(255, 255, 255, 0.1);
background: rgba(30, 30, 50, 0.9);
}
body.theme-night .clock-face {
background: linear-gradient(135deg, #2c3e50, #34495e);
}
body.theme-ocean {
background: linear-gradient(135deg, #1a2980, #26d0ce);
}
body.theme-ocean .clock {
border: 15px solid rgba(173, 216, 230, 0.8);
background: rgba(224, 247, 250, 0.9);
}
body.theme-ocean .clock-face {
background: linear-gradient(135deg, #a8e6cf, #dcedc1);
}
body.theme-forest {
background: linear-gradient(135deg, #134e5e, #71b280);
}
body.theme-forest .clock {
border: 15px solid rgba(139, 195, 74, 0.8);
background: rgba(232, 245, 233, 0.9);
}
body.theme-forest .clock-face {
background: linear-gradient(135deg, #c8e6c9, #a5d6a7);
}
body.theme-sunset {
background: linear-gradient(135deg, #ff6b6b, #ffa726, #ffecb3);
}
body.theme-sunset .clock {
border: 15px solid rgba(255, 167, 38, 0.8);
background: rgba(255, 253, 231, 0.9);
}
body.theme-sunset .clock-face {
background: linear-gradient(135deg, #ffecb3, #ffe0b2);
}
/* 响应式设计 */
@media (max-width: 1000px) {
.container {
width: 95%;
padding: 30px;
}
.settings-panel {
width: 280px;
}
}
@media (max-width: 600px) {
.clock-container {
width: 260px;
height: 260px;
}
.digital-clock {
font-size: 2.2rem;
}
.date {
font-size: 1.1rem;
}
.control-panel {
gap: 10px;
}
.control-btn {
padding: 12px 20px;
font-size: 0.9rem;
}
h1 {
font-size: 1.8rem;
}
}
@media (max-width: 400px) {
.clock-container {
width: 200px;
height: 200px;
}
.digital-clock {
font-size: 1.8rem;
letter-spacing: 1px;
}
.date {
font-size: 0.9rem;
}
h1 {
font-size: 1.5rem;
}
.settings-panel {
width: 260px;
right: 10px;
}
}
</style>
</head>
<body class="theme-dark">
<!-- 背景粒子 -->
<div class="particles" id="particles"></div>
<!-- 霓虹光效 -->
<div class="neon-glow blue"></div>
<div class="neon-glow pink"></div>
<!-- 天气效果 -->
<div class="weather-effect" id="weather-effect"></div>
<!-- 设置面板 -->
<div class="settings-panel" id="settings-panel">
<div class="settings-header">
<h3 class="settings-title">时钟设置</h3>
<button class="close-settings" id="close-settings">
<i class="fas fa-times"></i>
</button>
</div>
<div class="settings-group">
<label class="settings-label">主题</label>
<select class="settings-select" id="theme-select">
<option value="dark">深色主题</option>
<option value="night">星空之夜</option>
<option value="ocean">海洋之蓝</option>
<option value="forest">森林之绿</option>
<option value="sunset">日落橙黄</option>
</select>
</div>
<div class="settings-group">
<label class="settings-label">表盘样式</label>
<select class="settings-select" id="dial-select">
<option value="arabic">阿拉伯数字</option>
<option value="roman">罗马数字</option>
<option value="minimalist">极简刻度</option>
</select>
</div>
<div class="settings-group">
<label class="settings-label">天气效果</label>
<select class="settings-select" id="weather-select">
<option value="none">无效果</option>
<option value="snow">下雪</option>
<option value="rain">下雨</option>
</select>
</div>
<div class="settings-group">
<label class="settings-label">音效</label>
<select class="settings-select" id="sound-select">
<option value="off">关闭</option>
<option value="tick">滴答声</option>
<option value="chime">整点报时</option>
</select>
</div>
<div class="settings-group">
<label class="settings-label">3D效果</label>
<select class="settings-select" id="effect3d-select">
<option value="off">关闭</option>
<option value="on">开启</option>
</select>
</div>
</div>
<div class="container">
<h1><i class="fas fa-clock"></i> 精美模拟时钟</h1>
<div class="clock-container" id="clock-container">
<div class="clock">
<div class="clock-face">
<div class="hand hour-hand"></div>
<div class="hand min-hand"></div>
<div class="hand second-hand"></div>
<div class="center-circle"></div>
<!-- 刻度标记 -->
<div class="marking"></div>
<!-- 数字 -->
<div class="clock-numbers" id="clock-numbers"></div>
<div class="brand">Chrono Excellence</div>
</div>
</div>
</div>
<div class="digital-clock" id="digital-time">00:00:00</div>
<div class="date" id="date-display">
<i class="far fa-calendar-alt"></i>
<span id="date-text">2023年11月1日 星期三</span>
</div>
<div class="control-panel">
<button class="control-btn" id="theme-btn">
<i class="fas fa-palette"></i> 主题
</button>
<button class="control-btn" id="style-btn">
<i class="fas fa-paint-brush"></i> 样式
</button>
<button class="control-btn" id="effects-btn">
<i class="fas fa-magic"></i> 特效
</button>
<button class="control-btn" id="settings-btn">
<i class="fas fa-cog"></i> 设置
</button>
</div>
</div>
<script>
// 获取DOM元素
const secondHand = document.querySelector('.second-hand');
const minHand = document.querySelector('.min-hand');
const hourHand = document.querySelector('.hour-hand');
const digitalTime = document.getElementById('digital-time');
const dateDisplay = document.getElementById('date-text');
const clockNumbers = document.getElementById('clock-numbers');
const particlesContainer = document.getElementById('particles');
const weatherEffect = document.getElementById('weather-effect');
const clockContainer = document.getElementById('clock-container');
// 控制按钮
const themeBtn = document.getElementById('theme-btn');
const styleBtn = document.getElementById('style-btn');
const effectsBtn = document.getElementById('effects-btn');
const settingsBtn = document.getElementById('settings-btn');
// 设置面板元素
const settingsPanel = document.getElementById('settings-panel');
const closeSettings = document.getElementById('close-settings');
const themeSelect = document.getElementById('theme-select');
const dialSelect = document.getElementById('dial-select');
const weatherSelect = document.getElementById('weather-select');
const soundSelect = document.getElementById('sound-select');
const effect3dSelect = document.getElementById('effect3d-select');
// 状态变量
let currentTheme = 'dark';
let currentDial = 'arabic';
let currentWeather = 'none';
let currentSound = 'off';
let is3dEffect = false;
let lastHour = -1;
// 创建背景粒子
function createParticles() {
particlesContainer.innerHTML = '';
for (let i = 0; i < 30; i++) {
const particle = document.createElement('div');
particle.className = 'particle';
// 随机大小和位置
const size = Math.random() * 5 + 2;
const posX = Math.random() * 100;
const delay = Math.random() * 15;
const duration = Math.random() * 10 + 15;
particle.style.width = `${size}px`;
particle.style.height = `${size}px`;
particle.style.left = `${posX}%`;
particle.style.animationDelay = `${delay}s`;
particle.style.animationDuration = `${duration}s`;
// 根据主题设置颜色
if (currentTheme === 'night') {
particle.style.background = 'rgba(255, 255, 255, 0.8)';
} else if (currentTheme === 'ocean') {
particle.style.background = 'rgba(173, 216, 230, 0.8)';
} else if (currentTheme === 'forest') {
particle.style.background = 'rgba(144, 238, 144, 0.8)';
} else if (currentTheme === 'sunset') {
particle.style.background = 'rgba(255, 215, 0, 0.8)';
} else {
particle.style.background = 'rgba(255, 255, 255, 0.5)';
}
particlesContainer.appendChild(particle);
}
}
// 创建天气效果
function createWeatherEffect() {
weatherEffect.innerHTML = '';
if (currentWeather === 'snow') {
for (let i = 0; i < 50; i++) {
const snowflake = document.createElement('div');
snowflake.className = 'snowflake';
const size = Math.random() * 4 + 2;
const posX = Math.random() * 100;
const delay = Math.random() * 10;
const duration = Math.random() * 10 + 10;
snowflake.style.width = `${size}px`;
snowflake.style.height = `${size}px`;
snowflake.style.left = `${posX}%`;
snowflake.style.animationDelay = `${delay}s`;
snowflake.style.animationDuration = `${duration}s`;
weatherEffect.appendChild(snowflake);
}
} else if (currentWeather === 'rain') {
for (let i = 0; i < 100; i++) {
const raindrop = document.createElement('div');
raindrop.className = 'raindrop';
const posX = Math.random() * 100;
const delay = Math.random() * 5;
const duration = Math.random() * 2 + 1;
raindrop.style.left = `${posX}%`;
raindrop.style.animationDelay = `${delay}s`;
raindrop.style.animationDuration = `${duration}s`;
weatherEffect.appendChild(raindrop);
}
}
}
// 创建时钟刻度
function createClockMarkings() {
// 清除现有刻度
const existingMarkings = document.querySelectorAll('.marking:not(.hour-mark)');
existingMarkings.forEach(marking => marking.remove());
// 创建分钟刻度
for (let i = 0; i < 60; i++) {
// 跳过小时位置(每5分钟)
if (i % 5 !== 0) {
const minMark = document.createElement('div');
minMark.className = 'marking';
minMark.style.transform = `rotate(${i * 6}deg)`;
document.querySelector('.clock-face').appendChild(minMark);
}
}
}
// 创建时钟数字
function createClockNumbers() {
clockNumbers.innerHTML = '';
const numbers = currentDial === 'roman'
? ['XII', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX', 'X', 'XI']
: ['12', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11'];
for (let i = 0; i < 12; i++) {
const number = document.createElement('div');
number.className = 'clock-number';
number.textContent = numbers[i];
number.style.fontSize = currentDial === 'minimalist' ? '0' : '1.2rem';
// 计算数字位置
const angle = (i * 30) * Math.PI / 180;
const radius = 38; // 距离中心的百分比
const x = 50 + radius * Math.sin(angle);
const y = 50 - radius * Math.cos(angle);
number.style.left = `$%`;
number.style.top = `${y}%`;
number.style.transform = `translate(-50%, -50%)`;
clockNumbers.appendChild(number);
}
}
// 更新时钟函数
function updateClock() {
const now = new Date();
// 获取时间
const seconds = now.getSeconds();
const minutes = now.getMinutes();
const hours = now.getHours() % 12; // 转换为12小时制
// 计算指针角度
const secondsDegrees = (seconds / 60) * 360 + 90;
const minsDegrees = (minutes / 60) * 360 + (seconds / 60) * 6 + 90;
const hoursDegrees = (hours / 12) * 360 + (minutes / 60) * 30 + 90;
// 应用旋转
secondHand.style.transform = `translateX(-50%) rotate(${secondsDegrees}deg)`;
minHand.style.transform = `translateX(-50%) rotate(${minsDegrees}deg)`;
hourHand.style.transform = `translateX(-50%) rotate(${hoursDegrees}deg)`;
// 更新数字时间
const formattedTime = now.toLocaleTimeString('zh-CN');
digitalTime.textContent = formattedTime;
// 更新日期
const options = { year: 'numeric', month: 'long', day: 'numeric', weekday: 'long' };
const formattedDate = now.toLocaleDateString('zh-CN', options);
dateDisplay.textContent = formattedDate;
// 整点报时
if (currentSound === 'chime' && now.getMinutes() === 0 && now.getSeconds() === 0 && now.getHours() !== lastHour) {
playChime();
lastHour = now.getHours();
}
// 滴答声
if (currentSound === 'tick') {
playTick();
}
// 3D效果
if (is3dEffect) {
const mouseX = (event?.clientX || 0) / window.innerWidth - 0.5;
const mouseY = (event?.clientY || 0) / window.innerHeight - 0.5;
clockContainer.style.transform = `perspective(1000px) rotateY(${mouseX * 10}deg) rotateX(${mouseY * -10}deg)`;
}
}
// 播放滴答声
function playTick() {
// 创建简单的滴答声
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
const oscillator = audioContext.createOscillator();
const gainNode = audioContext.createGain();
oscillator.connect(gainNode);
gainNode.connect(audioContext.destination);
oscillator.frequency.value = 1000;
oscillator.type = 'sine';
gainNode.gain.setValueAtTime(0.1, audioContext.currentTime);
gainNode.gain.exponentialRampToValueAtTime(0.001, audioContext.currentTime + 0.1);
oscillator.start(audioContext.currentTime);
oscillator.stop(audioContext.currentTime + 0.1);
}
// 播放整点报时
function playChime() {
// 创建简单的报时声
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
const oscillator = audioContext.createOscillator();
const gainNode = audioContext.createGain();
oscillator.connect(gainNode);
gainNode.connect(audioContext.destination);
oscillator.frequency.value = 800;
oscillator.type = 'sine';
gainNode.gain.setValueAtTime(0.3, audioContext.currentTime);
gainNode.gain.exponentialRampToValueAtTime(0.001, audioContext.currentTime + 0.5);
oscillator.start(audioContext.currentTime);
oscillator.stop(audioContext.currentTime + 0.5);
}
// 设置主题
function setTheme(theme) {
currentTheme = theme;
document.body.className = `theme-${theme}`;
themeSelect.value = theme;
createParticles();
}
// 设置表盘样式
function setDialStyle(style) {
currentDial = style;
dialSelect.value = style;
createClockNumbers();
}
// 设置天气效果
function setWeatherEffect(weather) {
currentWeather = weather;
weatherSelect.value = weather;
createWeatherEffect();
}
// 设置音效
function setSound(sound) {
currentSound = sound;
soundSelect.value = sound;
}
// 设置3D效果
function set3dEffect(enabled) {
is3dEffect = enabled;
effect3dSelect.value = enabled ? 'on' : 'off';
if (enabled) {
document.addEventListener('mousemove', handleMouseMove);
clockContainer.style.transition = 'transform 0.1s ease';
} else {
document.removeEventListener('mousemove', handleMouseMove);
clockContainer.style.transform = 'perspective(1000px) rotateY(0deg) rotateX(0deg)';
clockContainer.style.transition = 'transform 0.5s ease';
}
}
// 处理鼠标移动(3D效果)
function handleMouseMove(event) {
if (!is3dEffect) return;
const mouseX = (event.clientX / window.innerWidth) - 0.5;
const mouseY = (event.clientY / window.innerHeight) - 0.5;
clockContainer.style.transform = `perspective(1000px) rotateY(${mouseX * 15}deg) rotateX(${mouseY * -15}deg)`;
}
// 初始化
function init() {
createParticles();
createClockMarkings();
createClockNumbers();
updateClock();
// 事件监听
themeBtn.addEventListener('click', () => {
settingsPanel.classList.toggle('open');
});
styleBtn.addEventListener('click', () => {
settingsPanel.classList.toggle('open');
});
effectsBtn.addEventListener('click', () => {
settingsPanel.classList.toggle('open');
});
settingsBtn.addEventListener('click', () => {
settingsPanel.classList.toggle('open');
});
closeSettings.addEventListener('click', () => {
settingsPanel.classList.remove('open');
});
themeSelect.addEventListener('change', (e) => {
setTheme(e.target.value);
});
dialSelect.addEventListener('change', (e) => {
setDialStyle(e.target.value);
});
weatherSelect.addEventListener('change', (e) => {
setWeatherEffect(e.target.value);
});
soundSelect.addEventListener('change', (e) => {
setSound(e.target.value);
});
effect3dSelect.addEventListener('change', (e) => {
set3dEffect(e.target.value === 'on');
});
// 每秒更新一次
setInterval(updateClock, 1000);
}
// 启动应用
init();
</script>
</body>
</html>
