模拟时钟
根据本地时间实时转动的精致机械表盘。
启用 JavaScript 后可编辑、运行和保存此案例。固定源码如下:
<!doctype html>
<html lang="zh-Hans" dir="ltr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>模拟时钟</title>
<style>
* { box-sizing: border-box; }
body { min-height: 100vh; margin: 0; display: grid; place-items: center; padding: 24px; color: #2b2923; font-family: "Baskerville", "STSong", serif; background: #c9bda4; background-image: radial-gradient(circle at 20% 20%, rgba(255,255,255,.35), transparent 30%), repeating-linear-gradient(90deg, rgba(82,61,40,.025) 0 1px, transparent 1px 5px); }
main { width: min(620px, 100%); text-align: center; }
.eyebrow { color: #775f42; font: 800 10px/1 "Courier New", monospace; letter-spacing: .3em; }
h1 { margin: 10px 0 30px; font-size: clamp(33px, 7vw, 54px); font-weight: 500; }
.clock-case { position: relative; width: min(390px, 80vw); aspect-ratio: 1; margin: auto; padding: 20px; border-radius: 50%; background: linear-gradient(145deg, #6d4c2f, #bd9365 45%, #51371f); box-shadow: 0 30px 60px rgba(51,37,24,.32), inset 0 0 0 3px rgba(255,255,255,.26), inset 0 0 0 9px rgba(40,25,14,.25); }
.face { position: relative; width: 100%; height: 100%; border: 1px solid #b8a888; border-radius: 50%; background: radial-gradient(circle, #faf5e8 0 58%, #eee4cf 80%, #c8b58f); box-shadow: inset 0 0 24px rgba(65,48,29,.2); }
.tick { position: absolute; inset: 9px 50% 50%; width: 1px; transform-origin: 50% 100%; }
.tick::before { content: ""; display: block; width: 1px; height: 8px; background: #6e6759; }
.tick.major::before { width: 3px; height: 14px; margin-left: -1px; background: #282722; }
.number { position: absolute; color: #2b2923; font-size: clamp(20px, 5vw, 29px); font-weight: 700; transform: translate(-50%, -50%); }
.n12 { left: 50%; top: 15%; } .n3 { left: 85%; top: 50%; } .n6 { left: 50%; top: 85%; } .n9 { left: 15%; top: 50%; }
.maker { position: absolute; top: 30%; left: 50%; transform: translateX(-50%); color: #8c7d63; font: 800 9px/1 "Courier New", monospace; letter-spacing: .15em; }
.hand { position: absolute; left: 50%; bottom: 50%; border-radius: 999px; transform-origin: 50% 100%; }
.hour { width: 7px; height: 24%; margin-left: -3.5px; background: #272722; }
.minute { width: 4px; height: 33%; margin-left: -2px; background: #3a3932; }
.second { width: 2px; height: 38%; margin-left: -1px; background: #a74336; }
.pin { position: absolute; left: 50%; top: 50%; width: 18px; height: 18px; border: 4px solid #eee4cf; border-radius: 50%; background: #a74336; box-shadow: 0 1px 4px rgba(0,0,0,.3); transform: translate(-50%, -50%); }
.digital { display: inline-flex; gap: 12px; align-items: center; margin-top: 25px; padding: 10px 16px; border: 1px solid rgba(72,56,37,.24); border-radius: 999px; color: #594d3d; font: 700 12px/1 "Courier New", monospace; background: rgba(250,245,232,.42); }
.digital time { color: #9c4337; font-size: 14px; }
</style>
</head>
<body>
<main><span class="eyebrow">LOCAL TIMEPIECE · NO. 12</span><h1>让时间被看见</h1>
<div class="clock-case"><div id="face" class="face" aria-label="模拟时钟"><span class="number n12">12</span><span class="number n3">3</span><span class="number n6">6</span><span class="number n9">9</span><span class="maker">CHRONOS</span><i id="hour" class="hand hour"></i><i id="minute" class="hand minute"></i><i id="second" class="hand second"></i><i class="pin"></i></div></div>
<div class="digital"><span id="date"></span><time id="digitalTime"></time></div>
</main>
<script>
const face = document.querySelector('#face');
for (let index = 0; index < 60; index += 1) {
const tick = document.createElement('i'); tick.className = `tick${index % 5 === 0 ? ' major' : ''}`; tick.style.transform = `rotate(${index * 6}deg)`; face.prepend(tick);
}
function updateClock() {
const now = new Date();
const seconds = now.getSeconds();
const minutes = now.getMinutes() + seconds / 60;
const hours = now.getHours() % 12 + minutes / 60;
document.querySelector('#second').style.transform = `rotate(${seconds * 6}deg)`;
document.querySelector('#minute').style.transform = `rotate(${minutes * 6}deg)`;
document.querySelector('#hour').style.transform = `rotate(${hours * 30}deg)`;
document.querySelector('#digitalTime').textContent = now.toLocaleTimeString('zh-CN', { hour12: false });
document.querySelector('#date').textContent = now.toLocaleDateString('zh-CN', { month: 'long', day: 'numeric', weekday: 'short' });
}
updateClock();
window.setInterval(updateClock, 1000);
</script>
</body>
</html>