こんにちは。KOUKIです。
本記事は、Udemyの「50 Projects In 50 Days – HTML, CSS & JavaScript」で学習したことを載せています。
<目次>
実装するもの
今回は、JavaScriptでアナログ時計を作成します。
demoは「こちら」で確認できます。
環境構築
簡単な環境構築をお願いします。
必要なファイルは、以下の通りです。
1 2 3 4 5 6 |
$ tree . ├── index.html ├── script.js └── style.css |
CSS版
ページ(HTML)の作成
最初にページを作成しましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" href="style.css" /> <title>Theme Clock</title> </head> <body> <!-- Inspired by this dribbble shot https://dribbble.com/shots/5958443-Alarm-clock --> <button class="toggle">Dark mode</button> <div class="clock-container"> <div class="clock"> <div class="needle hour"></div> <div class="needle minute"></div> <div class="needle second"></div> <div class="center-point"></div> </div> <div class="time"></div> <div class="date"></div> </div> <script src="script.js"></script> </body> </html> |
このHTMLをブラウザ上で表示すると以下のようになります。

スタイル(CSS)を装飾
次にスタイルを記述しましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
@import url('https://fonts.googleapis.com/css?family=Heebo:300&display=swap'); * { box-sizing: border-box; } :root { --primary-color: #000; --secondary-color: #fff; } html { transition: all 0.5s ease-in; } html.dark { --primary-color: #fff; --secondary-color: #333; } html.dark { background-color: #111; color: var(--primary-color); } body { font-family: 'Heebo', sans-serif; display: flex; align-items: center; justify-content: center; height: 100vh; overflow: hidden; margin: 0; } .toggle { cursor: pointer; background-color: var(--primary-color); color: var(--secondary-color); border: 0; border-radius: 4px; padding: 8px 12px; position: absolute; top: 100px; } .toggle:focus { outline: none; } .clock-container { display: flex; flex-direction: column; justify-content: space-between; align-items: center; } .clock { position: relative; width: 200px; height: 200px; } .needle { background-color: var(--primary-color); position: absolute; top: 50%; left: 50%; height: 65px; width: 3px; transform-origin: bottom center; transition: all 0.5s ease-in; } .needle.hour { transform: translate(-50%, -100%) rotate(0deg); } .needle.minute { transform: translate(-50%, -100%) rotate(0deg); height: 100px; } .needle.second { transform: translate(-50%, -100%) rotate(0deg); height: 100px; background-color: #e74c3c; } .center-point { background-color: #e74c3c; width: 10px; height: 10px; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); border-radius: 50%; } .center-point::after { content: ''; background-color: var(--primary-color); width: 5px; height: 5px; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); border-radius: 50%; } .time { font-size: 60px; } .date { color: #aaa; font-size: 14px; letter-spacing: 0.3px; text-transform: uppercase; } .date .circle { background-color: var(--primary-color); color: var(--secondary-color); border-radius: 50%; height: 18px; width: 18px; display: inline-flex; align-items: center; justify-content: center; line-height: 18px; transition: all 0.5s ease-in; font-size: 12px; } |
ここまで実装すると以下のようになります。

JavaScriptの実装
準備が完了したので、JavaScriptを実装していきましょう。
今回の肝は、以下のCSSです。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
.needle.hour { transform: translate(-50%, -100%) rotate(0deg); } .needle.minute { transform: translate(-50%, -100%) rotate(0deg); ... } .needle.second { transform: translate(-50%, -100%) rotate(0deg); ... } |
transformでアニメーションを設定していて、針の動きをrotateが制御しています。
例えば、現在は全て「0」に設定されていますが、それぞれ、「10」、「20」、「30」に設定すると時計の針はこんな感じになります。

JavaScriptでこの値を制御して、時計が動いているように見せましょう。
要素を取得する
画面操作に必要な要素を取得します。
1 2 3 4 5 6 7 |
// 要素を取得する const hourEl = document.querySelector('.hour') const minuteEl = document.querySelector('.minute') const secondEl = document.querySelector('.second') const timeEl = document.querySelector('.time') const dateEl = document.querySelector('.date') const toggle = document.querySelector('.toggle') |
日付要素を定義
日付要素を定数で定義しましょう。
1 2 3 4 5 |
// 日付要素 const days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; |
clickイベントを登録
「Dark mode」ボタンを押下すると背景色が反転するようにclickイベントを登録しましょう。
1 2 |
// clickイベントの登録 toggle.addEventListener('click', (e) => {}) |
背景色の反転
次は、背景色を反転させる処理を実装します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
toggle.addEventListener('click', (e) => { // html要素を取得 const html = document.querySelector('html') // darkクラスの存在確認 if(html.classList.contains('dark')) { // darkクラスを除去 html.classList.remove('dark') // ボタンの名称を変更 e.target.innerHTML = 'Dark Mode' } else { // darkクラスを付与 html.classList.add('dark') // ボタンの名称を変更 e.target.innerHTML = 'Light Mode' } }) |
これでボタンをクリックした時に、背景色が反転するようになりました。ついでにボタンの名称も変わります。

日付の設定
次に日付の設定をおこないます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
function setTime() { // 日時取得 const time = new Date(); const month = time.getMonth() const day = time.getDay() const date = time.getDate() const hours = time.getHours() const hoursForClock = hours >= 13 ? hours % 12 : hours; const minutes = time.getMinutes() const seconds = time.getSeconds() const ampm = hours >= 12 ? 'PM' : 'AM' // 日時の設定 hourEl.style.transform = `translate(-50%, -100%) rotate(${scale(hoursForClock, 0, 11, 0, 360)}deg)` minuteEl.style.transform = `translate(-50%, -100%) rotate(${scale(minutes, 0, 59, 0, 360)}deg)` secondEl.style.transform = `translate(-50%, -100%) rotate(${scale(seconds, 0, 59, 0, 360)}deg)` // 画面に表示 timeEl.innerHTML = `${hoursForClock}:${minutes < 10 ? `0${minutes}` : minutes} ${ampm}` dateEl.innerHTML = `${days[day]}, ${months[month]} <span class="circle">${date}</span>` } // StackOverflow https://stackoverflow.com/questions/10756313/javascript-jquery-map-a-range-of-numbers-to-another-range-of-numbers const scale = (num, in_min, in_max, out_min, out_max) => { return (num - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } // 日付をセット setTime() |
JavaScriptだと「new Date()」にて日付オブジェクトが取得できるので、これを使って日時の設定を行っています。
また前述の通り、rotateの数値を変更すると針が動きます。この針を回す間隔を制御するためにscale変数を用意しました 。※JavaScriptは、変数に処理を格納できます
scaleは、指定した数値の幅を返却します。例えば時間の場合は0~11の間の数値が返ってきて欲しいので、この間の数値が返ってきます。
ここまで実装すると以下のように表示されます。

setIntervalで時計の針を動かす
setIntervalを使って、時計の針を動かしましょう。
1 2 3 4 |
// 日付をセット // 時計の針を動かす setInterval(setTime, 1000) |
setIntervalは、第一引数に指定した関数をミリ秒単位で実行してくれます。今回は時計なので、1000ミリ秒(1秒)間隔を指定しました。
これで完成です。
おわりに
アナログ時計かっけぇええ。工夫次第でなんでも実装できる感じがしますね^^
それには、CSSの知識が不可欠ですけど^^;
それでは、また!
JavaScriptまとめ
JavaScript ソースコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
// 要素を取得する const hourEl = document.querySelector('.hour') const minuteEl = document.querySelector('.minute') const secondEl = document.querySelector('.second') const timeEl = document.querySelector('.time') const dateEl = document.querySelector('.date') const toggle = document.querySelector('.toggle') // 日付要素 const days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; // clickイベントの登録 toggle.addEventListener('click', (e) => { // html要素を取得 const html = document.querySelector('html') // darkクラスの存在確認 if(html.classList.contains('dark')) { // darkクラスを除去 html.classList.remove('dark') // ボタンの名称を変更 e.target.innerHTML = 'Dark Mode' } else { // darkクラスを付与 html.classList.add('dark') // ボタンの名称を変更 e.target.innerHTML = 'Light Mode' } }) function setTime() { // 日時取得 const time = new Date(); const month = time.getMonth() const day = time.getDay() const date = time.getDate() const hours = time.getHours() const hoursForClock = hours >= 13 ? hours % 12 : hours; const minutes = time.getMinutes() const seconds = time.getSeconds() const ampm = hours >= 12 ? 'PM' : 'AM' // 日時の設定 hourEl.style.transform = `translate(-50%, -100%) rotate(${scale(hoursForClock, 0, 11, 0, 360)}deg)` minuteEl.style.transform = `translate(-50%, -100%) rotate(${scale(minutes, 0, 59, 0, 360)}deg)` secondEl.style.transform = `translate(-50%, -100%) rotate(${scale(seconds, 0, 59, 0, 360)}deg)` // 画面に表示 timeEl.innerHTML = `${hoursForClock}:${minutes < 10 ? `0${minutes}` : minutes} ${ampm}` dateEl.innerHTML = `${days[day]}, ${months[month]} <span class="circle">${date}</span>` } // StackOverflow https://stackoverflow.com/questions/10756313/javascript-jquery-map-a-range-of-numbers-to-another-range-of-numbers const scale = (num, in_min, in_max, out_min, out_max) => { return (num - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } // 日付をセット setTime() // 時計の針を動かす setInterval(setTime, 1000) |
コメントを残す
コメントを投稿するにはログインしてください。