5日目のゴールと今日やること
引用元:なし(本教材はオリジナル解説です)
5日目のテーマは
「タイマーの操作性(UI/UX)を高める」
ことです。
1〜4日目であなたはすでに、
- setTimeout を使った 1 秒ごとのカウント
- isRunning による状態管理
- 開始・停止・リセットの基本動作
- 00:00 表示の整形
ここまで理解できています。
5日目はここに、
- ボタンの状態を制御する(開始中は開始ボタンを押せないようにする)
- タイマーの状態を画面に反映する
- 「操作ミスを防ぐ」ための UI ロジックを追加する
という、“アプリとしての使いやすさ”を加えていきます。
ボタンの状態を制御するという発想
なぜボタン制御が必要なのか?
今のタイマーは、
開始ボタンを何度押しても動きます。
でも実際のアプリでは、
- タイマーが動いているときに「開始」を押しても意味がない
- 停止中に「停止」を押しても意味がない
- リセット中に「リセット」を押しても意味がない
こうした「無駄な操作」を防ぐ必要があります。
そのために必要なのが、
ボタンの状態(enabled / disabled)を制御する という考え方です。
HTML 側でボタンに ID をつける
ボタンを JavaScript から操作できるようにする
<button id="startBtn" onclick="startTimer()">開始</button>
<button id="stopBtn" onclick="stopTimer()">停止</button>
<button id="resetBtn" onclick="resetTimer()">リセット</button>
これで JavaScript から、
document.getElementById("startBtn")
JavaScriptのようにアクセスできます。
ボタンを無効化(disabled)する方法
disabled = true / false を使う
JavaScript では、
ボタンを無効化するにはこう書きます。
document.getElementById("startBtn").disabled = true;
JavaScript有効化するには、
document.getElementById("startBtn").disabled = false;
JavaScriptこれを使って、
「開始中は開始ボタンを押せない」
「停止中は停止ボタンを押せない」
といった制御を行います。
ボタン状態をまとめて管理する関数を作る
状態管理の考え方を UI にも応用する
タイマーの状態は isRunning で管理していますが、
UI(ボタン)も同じように状態を持たせるとスッキリします。
function updateButtons() {
document.getElementById("startBtn").disabled = isRunning;
document.getElementById("stopBtn").disabled = !isRunning;
document.getElementById("resetBtn").disabled = false;
}
JavaScriptここでのポイントは、
- isRunning が true → startBtn は押せない
- isRunning が false → stopBtn は押せない
- resetBtn はいつでも押せる
というルールをまとめていることです。
深掘り:なぜ関数にまとめるのか?
開始・停止・リセットのたびに
毎回ボタン状態を手動で書くと、
コードがバラバラになって管理しづらくなります。
updateButtons にまとめることで、
- どこを直せば UI が変わるかが明確
- コードの重複がなくなる
- 状態管理が一箇所に集まる
というメリットがあります。
startTimer にボタン制御を追加する
開始時に UI を更新する
function startTimer() {
if (isRunning) return;
isRunning = true;
updateButtons();
timerId = setTimeout(tick, 1000);
}
JavaScript開始した瞬間に、
- startBtn → disabled
- stopBtn → enabled
という状態になります。
stopTimer にボタン制御を追加する
停止時に UI を更新する
function stopTimer() {
if (!isRunning) return;
clearTimeout(timerId);
timerId = null;
isRunning = false;
updateButtons();
}
JavaScript停止した瞬間に、
- startBtn → enabled
- stopBtn → disabled
になります。
resetTimer にボタン制御を追加する
リセット時は「停止+0に戻す+UI更新」
function resetTimer() {
if (isRunning) {
clearTimeout(timerId);
}
isRunning = false;
timerId = null;
elapsed = 0;
updateDisplay();
updateButtons();
}
JavaScriptリセット後は、
- startBtn → enabled
- stopBtn → disabled
- resetBtn → enabled
という状態になります。
5日目のミニ完成版:UI 制御付きタイマー
HTML
<div id="display">00:00</div>
<button id="startBtn" onclick="startTimer()">開始</button>
<button id="stopBtn" onclick="stopTimer()">停止</button>
<button id="resetBtn" onclick="resetTimer()">リセット</button>
JavaScript(重要部分のみ)
let timerId = null;
let isRunning = false;
let elapsed = 0;
function pad(num) {
return num.toString().padStart(2, "0");
}
function updateDisplay() {
const totalSeconds = Math.floor(elapsed / 1000);
const minutes = Math.floor(totalSeconds / 60);
const seconds = totalSeconds % 60;
document.getElementById("display").innerText =
pad(minutes) + ":" + pad(seconds);
}
function updateButtons() {
document.getElementById("startBtn").disabled = isRunning;
document.getElementById("stopBtn").disabled = !isRunning;
document.getElementById("resetBtn").disabled = false;
}
function tick() {
if (!isRunning) return;
elapsed += 1000;
updateDisplay();
timerId = setTimeout(tick, 1000);
}
function startTimer() {
if (isRunning) return;
isRunning = true;
updateButtons();
timerId = setTimeout(tick, 1000);
}
function stopTimer() {
if (!isRunning) return;
clearTimeout(timerId);
timerId = null;
isRunning = false;
updateButtons();
}
function resetTimer() {
if (isRunning) {
clearTimeout(timerId);
}
isRunning = false;
timerId = null;
elapsed = 0;
updateDisplay();
updateButtons();
}
JavaScript5日目で特に深く理解してほしいこと
1つ目:UI も「状態管理」で動かす
isRunning を UI にも反映することで、
アプリ全体の動きが一貫します。
2つ目:ボタン制御は「操作ミスを防ぐ」ために必須
開始中に開始を押せない
停止中に停止を押せない
これだけでアプリの品質が一気に上がります。
3つ目:updateButtons は UI の司令塔
UI の状態を一箇所で管理することで、
コードが読みやすく、修正しやすくなります。
6日目へのつなぎ
6日目からは、
- タイマーのデザインを整える(CSS)
- ボタンの見た目をアプリ風にする
- タイマーのレイアウトを整える
という、“見た目の完成度”を高める段階に入ります。
今日の「UI 制御」ができた時点で、
あなたのタイマーはもう「アプリとしての振る舞い」を持ち始めています。

