Created
April 9, 2026 05:06
-
-
Save a70437043b/0d90d376694d16c0391d24096068565f to your computer and use it in GitHub Desktop.
My Notion Orbit Clock
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="zh-TW"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <style> | |
| :root { | |
| --bg-color: #d9e9f2; /* 背景:淡藍色 */ | |
| --hour-ring: #FF5733; /* 外環:橙色 */ | |
| --min-ring: #2ECC71; /* 中環:綠色 */ | |
| --sec-ring: #3498DB; /* 內環:藍色 */ | |
| --text-color: #2c3e50; /* 文字顏色 */ | |
| } | |
| body { | |
| margin: 0; padding: 0; background: var(--bg-color); | |
| display: flex; flex-direction: column; justify-content: center; align-items: center; | |
| height: 100vh; font-family: 'Helvetica Neue', Arial, sans-serif; overflow: hidden; | |
| } | |
| .clock-container { position: relative; width: 380px; height: 380px; } | |
| svg { width: 100%; height: 100%; } | |
| /* 軌道樣式 */ | |
| .ring-h { fill: none; stroke: var(--hour-ring); stroke-width: 1.5; opacity: 0.15; } | |
| .ring-m { fill: none; stroke: var(--min-ring); stroke-width: 1.5; opacity: 0.15; } | |
| .ring-s { fill: none; stroke: var(--sec-ring); stroke-width: 1.5; opacity: 0.15; } | |
| /* 刻度文字樣式 */ | |
| .tick-text { fill: var(--text-color); font-size: 11px; font-weight: bold; text-anchor: middle; dominant-baseline: middle; } | |
| .tick-line { stroke: #333; stroke-width: 1; opacity: 0.3; } | |
| /* 【修正重點】中央數字時間字體縮小 */ | |
| .digital-time { | |
| position: absolute; top: 46%; left: 50%; transform: translate(-50%, -50%); | |
| font-size: 20px; /* 從 28px 縮小到 20px */ | |
| font-weight: bold; display: flex; gap: 3px; | |
| } | |
| .t-h { color: var(--hour-ring); } | |
| .t-m { color: var(--min-ring); } | |
| .t-s { color: var(--sec-ring); } | |
| .day-label { | |
| position: absolute; top: 56%; left: 50%; transform: translate(-50%, -50%); | |
| font-size: 12px; color: #7f8c8d; font-weight: 500; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="clock-container"> | |
| <svg id="clock-svg" viewBox="0 0 400 400"> | |
| <circle class="ring-h" cx="200" cy="200" r="140" /> | |
| <circle class="ring-m" cx="200" cy="200" r="108" /> | |
| <circle class="ring-s" cx="200" cy="200" r="75" /> | |
| <g id="ticks-group"></g> | |
| <circle id="ball-h" r="7" fill="#E74C3C" stroke="white" stroke-width="1.5" /> | |
| <circle id="ball-m" r="6" fill="#27AE60" stroke="white" stroke-width="1.5" /> | |
| <g id="airplane"> | |
| <path d="M0,-8 L2,-4 L8,-2 L8,0 L2,0 L2,6 L5,8 L5,9 L0,8 L-5,9 L-5,8 L-2,6 L-2,0 L-8,0 L-8,-2 L-2,-4 Z" fill="#2980B9" stroke="white" stroke-width="0.5"/> | |
| </g> | |
| </svg> | |
| <div class="digital-time"> | |
| <span id="txt-h" class="t-h">00</span><span style="color:#bdc3c7">:</span> | |
| <span id="txt-m" class="t-m">00</span><span style="color:#bdc3c7">:</span> | |
| <span id="txt-s" class="t-s">00</span> | |
| </div> | |
| <div id="txt-day" class="day-label">Thursday</div> | |
| </div> | |
| <script> | |
| function setupTicks() { | |
| const g = document.getElementById('ticks-group'); | |
| const cx = 200, cy = 200; | |
| // 小時數字:12, 3, 6, 9 | |
| const hLabels = { 0: "12", 90: "3", 180: "6", 270: "9" }; | |
| for (let a = 0; a < 360; a += 30) { | |
| const rad = (a - 90) * Math.PI / 180; | |
| const line = document.createElementNS("http://www.w3.org/2000/svg", "line"); | |
| line.setAttribute("class", "tick-line"); | |
| line.setAttribute("x1", cx + 135 * Math.cos(rad)); line.setAttribute("y1", cy + 135 * Math.sin(rad)); | |
| line.setAttribute("x2", cx + 145 * Math.cos(rad)); line.setAttribute("y2", cy + 145 * Math.sin(rad)); | |
| g.appendChild(line); | |
| if (hLabels[a]) { | |
| const tx = cx + 160 * Math.cos(rad), ty = cy + 160 * Math.sin(rad); | |
| const t = document.createElementNS("http://www.w3.org/2000/svg", "text"); | |
| t.setAttribute("class", "tick-text"); t.setAttribute("x", tx); t.setAttribute("y", ty); | |
| t.textContent = hLabels[a]; g.appendChild(t); | |
| } | |
| } | |
| // 分鐘數字:60, 10, 20... | |
| const mLabels = { 0: "60", 60: "10", 120: "20", 180: "30", 240: "40", 300: "50" }; | |
| for (let a = 0; a < 360; a += 6) { | |
| const rad = (a - 90) * Math.PI / 180; | |
| const isMajor = a % 30 === 0; | |
| const line = document.createElementNS("http://www.w3.org/2000/svg", "line"); | |
| line.setAttribute("class", "tick-line"); | |
| const rIn = isMajor ? 103 : 105, rOut = isMajor ? 113 : 110; | |
| line.setAttribute("x1", cx + rIn * Math.cos(rad)); line.setAttribute("y1", cy + rIn * Math.sin(rad)); | |
| line.setAttribute("x2", cx + rOut * Math.cos(rad)); line.setAttribute("y2", cy + rOut * Math.sin(rad)); | |
| g.appendChild(line); | |
| if (isMajor && mLabels[a]) { | |
| const tx = cx + 125 * Math.cos(rad), ty = cy + 125 * Math.sin(rad); | |
| const t = document.createElementNS("http://www.w3.org/2000/svg", "text"); | |
| t.setAttribute("class", "tick-text"); t.setAttribute("x", tx); t.setAttribute("y", ty); | |
| t.textContent = mLabels[a]; g.appendChild(t); | |
| } | |
| } | |
| } | |
| function update() { | |
| const now = new Date(); | |
| const h = now.getHours(), m = now.getMinutes(), s = now.getSeconds(), ms = now.getMilliseconds(); | |
| const cx = 200, cy = 200; | |
| document.getElementById('txt-h').innerText = String(h).padStart(2, '0'); | |
| document.getElementById('txt-m').innerText = String(m).padStart(2, '0'); | |
| document.getElementById('txt-s').innerText = String(s).padStart(2, '0'); | |
| const days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; | |
| document.getElementById('txt-day').innerText = days[now.getDay()]; | |
| const s_progress = (s + ms/1000) / 60; | |
| const sRad = (s_progress * 360 - 90) * Math.PI / 180; | |
| const mRad = ((m + s/60) / 60 * 360 - 90) * Math.PI / 180; | |
| const hRad = (((h % 12) + m/60) / 12 * 360 - 90) * Math.PI / 180; | |
| // 更新球體 | |
| document.getElementById('ball-h').setAttribute('cx', cx + 140 * Math.cos(hRad)); | |
| document.getElementById('ball-h').setAttribute('cy', cy + 140 * Math.sin(hRad)); | |
| document.getElementById('ball-m').setAttribute('cx', cx + 108 * Math.cos(mRad)); | |
| document.getElementById('ball-m').setAttribute('cy', cy + 108 * Math.sin(mRad)); | |
| // 更新小飛機 (位置與轉向) | |
| const plane = document.getElementById('airplane'); | |
| const px = cx + 75 * Math.cos(sRad), py = cy + 75 * Math.sin(sRad); | |
| const pDeg = (s_progress * 360); // 修正旋轉角度計算 | |
| plane.setAttribute('transform', `translate(${px},${py}) rotate(${pDeg})`); | |
| requestAnimationFrame(update); | |
| } | |
| setupTicks(); | |
| update(); | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment