時間を設定し、タイマーが0になるまでカウントダウンするアプリです。リアルタイムで変化する状態管理や、条件分岐を学べます。
初めての人はお金持ちまでの道のり:0日目をまず読んでみてください!よろしくお願いします★
カウントダウンタイマーの基本構成
まず、シンプルなカウントダウンタイマーのHTMLとJavaScriptを一緒に書いてみましょう。これでスタート、ストップ、リセットのボタン機能を使い、設定した時間でカウントダウンができるようにします。
ステップ1:HTMLを作成する
まずは、HTMLの基本部分を作成します。これにより、タイマー表示エリアと各ボタンを準備します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>カウントダウンタイマー</title>
</head>
<body>
<h1>カウントダウンタイマー</h1>
<p id="timer">00:00</p>
<input type="number" id="minutes" placeholder="分を入力">
<button id="start">スタート</button>
<button id="stop">ストップ</button>
<button id="reset">リセット</button>
<script src="timer.js"></script>
</body>
</html>
<!DOCTYPE html>
:HTMLファイルであることを指定するための宣言です。- 和訳:「このファイルはHTMLで書かれているということをブラウザに伝えています。」
<html lang="ja">
:このHTML文書の言語が日本語であることを示します。- 和訳:「HTML全体が日本語であることを示します。」
<meta charset="UTF-8">
:このページの文字コードを設定します。UTF-8は日本語も含む多言語に対応しています。- 和訳:「ページ内の文字を正しく表示するために、文字コードをUTF-8に設定しています。」
<meta name="viewport" content="width=device-width, initial-scale=1.0">
:ページが画面サイズに合わせて表示されるようにします。- 和訳:「画面の幅に合わせてページが見やすくなるように設定しています。」
<title>カウントダウンタイマー</title>
:ページのタイトルを「カウントダウンタイマー」に設定します。- 和訳:「このページのタイトルを『カウントダウンタイマー』に設定しています。」
<h1>カウントダウンタイマー</h1>
:ページの見出しを「カウントダウンタイマー」にします。- 和訳:「見出しに『カウントダウンタイマー』と表示しています。」
<p id="timer">00:00</p>
:タイマーの表示を行う場所を作成し、最初は「00:00」と表示しています。- 和訳:「初期状態で00:00と表示するタイマーエリアを作成しています。」
<input type="number" id="minutes" placeholder="分を入力">
:タイマーの分数を入力するための入力フィールドを作成します。- 和訳:「カウントダウンする分数を入力するフィールドを作成しています。」
<button id="start">スタート</button>
:カウントダウンを始めるための「スタート」ボタンを作成します。- 和訳:「カウントダウンを開始するためのスタートボタンです。」
<button id="stop">ストップ</button>
:カウントダウンを一時停止する「ストップ」ボタンを作成します。- 和訳:「カウントダウンを止めるストップボタンです。」
<button id="reset">リセット</button>
:カウントダウンをリセットする「リセット」ボタンを作成します。- 和訳:「カウントダウンを初期状態に戻すリセットボタンです。」
<script src="timer.js"></script>
:外部JavaScriptファイル(timer.js)を読み込みます。- 和訳:「このHTMLでJavaScriptファイル(timer.js)を読み込んでいます。」
idについて
HTML内の id
は、これから作成するJavaScriptで操作するための目印になります。JavaScriptから id
を使って特定のHTML要素を取得し、その要素の内容を動的に変更することで、タイマーの動作やボタンの操作ができるようになります。
たとえば、id="timer"
の部分は、JavaScriptで現在のカウントダウン時間を表示する場所として使用します。また、id="start"
, id="stop"
, id="reset"
のボタンも、それぞれのボタンが押されたときにどの動作をするかをJavaScriptで設定します。
timer.jsについて
timer.js
はこれから作成するJavaScriptファイルのことです。このファイルにカウントダウンタイマーの動作を記述して、HTMLのボタンやタイマー表示部分と連携させます。
ステップ2:JavaScript (timer.js) を作成
この timer.js
ファイルに、タイマーの動作やボタンの処理を追加していきます。まずは基本的なカウントダウン機能を実装して、スタート、ストップ、リセットができるようにしましょう。
let countdown; // カウントダウンのための変数を定義
let timeLeft; // 残り時間を保存する変数を定義
const timerDisplay = document.getElementById("timer"); // タイマー表示のエリアを取得
const startButton = document.getElementById("start"); // スタートボタンを取得
const stopButton = document.getElementById("stop"); // ストップボタンを取得
const resetButton = document.getElementById("reset"); // リセットボタンを取得
// スタートボタンが押されたときの動作
startButton.addEventListener("click", () => {
const minutes = document.getElementById("minutes").value; // 入力された分数を取得
if (minutes) {
timeLeft = minutes * 60; // 分数を秒数に変換
clearInterval(countdown); // 既存のカウントダウンをクリア
countdown = setInterval(updateTimer, 1000); // 1秒ごとにタイマーを更新
}
});
// ストップボタンが押されたときの動作
stopButton.addEventListener("click", () => {
clearInterval(countdown); // カウントダウンを停止
});
// リセットボタンが押されたときの動作
resetButton.addEventListener("click", () => {
clearInterval(countdown); // カウントダウンを停止
timerDisplay.textContent = "00:00"; // タイマー表示を初期状態に戻す
document.getElementById("minutes").value = ""; // 入力フィールドもクリア
});
// タイマーを更新する関数
function updateTimer() {
if (timeLeft > 0) {
timeLeft--; // 残り時間を1秒減らす
const minutes = Math.floor(timeLeft / 60); // 残り分を計算
const seconds = timeLeft % 60; // 残り秒を計算
timerDisplay.textContent = `${String(minutes).padStart(2, "0")}:${String(seconds).padStart(2, "0")}`; // タイマー表示を更新
} else {
clearInterval(countdown); // カウントダウンを停止
timerDisplay.textContent = "時間切れ!"; // 時間切れの表示
}
}
1. let countdown;
このコードは、カウントダウンタイマーを動かすために使う変数 countdown
を宣言しています。
let
:JavaScriptで変数を宣言するためのキーワードです。「変数」は、値を保存したり変更したりできる「箱」だと考えてください。let
は、同じ名前の変数を再定義できない特徴があります。countdown
:変数の名前です。ここでは「カウントダウン」を指しますが、この名前は自由に決めることができる部分です。=
がない理由:let countdown;
のように、変数を宣言するだけで値を入れないこともできます。この場合、初期値は「undefined
」と呼ばれる、値がまだないことを示す特殊な状態になります。- 和訳:「カウントダウンを動かすための変数を作成していますが、まだ値は設定していません。」
2. let timeLeft;
このコードも同じく let
を使って、カウントダウンの残り時間を保存する変数 timeLeft
を宣言しています。
timeLeft
:残りの時間を表す変数です。この変数も自由に名前をつけられますが、意味がわかりやすいようにtimeLeft
としています。- 和訳:「残りの時間を記録するための変数を作成していますが、まだ値は設定していません。」
3. const timerDisplay = document.getElementById("timer");
このコードは、HTMLの要素(部品)を取得して操作するための部分です。
const
:const
は「定数」を宣言するキーワードです。const
を使って作られた変数は、あとから値を変更することができません(読み取り専用の箱と考えられます)。timerDisplay
:この定数の名前です。HTML内のタイマー表示部分を指す名前として設定していますが、こちらも自由に名前をつけることができます。document
:これはJavaScriptの組み込みオブジェクトです。HTML全体(文書)を指し、HTMLの要素を操作するために使われます。getElementById("timer")
:document
が持つ組み込みの関数(操作のこと)です。getElementById
は、HTML内で特定のid
を持つ要素を取得します。ここではid="timer"
の要素、つまり<p id="timer">
の部分を取得しています。- 和訳:「HTMLの中から、タイマー表示をする部分を取得し、それをtimerDisplayという定数に保存しています。」
4. const startButton = document.getElementById("start");
このコードも、HTMLの中にある「スタート」ボタンを取得し、それを startButton
という定数に保存しています。
document.getElementById("start")
:id="start"
を持つボタン要素をHTML内から取得します。これで、JavaScriptからこのボタンを操作できるようになります。- 和訳:「HTML内のスタートボタンを取得し、それをstartButtonという定数に保存しています。」
5. const stopButton = document.getElementById("stop");
このコードも同じく、「ストップ」ボタンを取得して stopButton
という定数に保存します。
- 和訳:「HTML内のストップボタンを取得し、それをstopButtonという定数に保存しています。」
6. const resetButton = document.getElementById("reset");
同様に、「リセット」ボタンを取得して resetButton
という定数に保存します。
- 和訳:「HTML内のリセットボタンを取得し、それをresetButtonという定数に保存しています。」
7. startButton.addEventListener("click", () => { ... });
ここで、スタートボタンがクリックされたときの動作を設定しています。addEventListener
は「イベント」を待ち受けて、それが発生したときに特定の動作を行う仕組みです。
startButton
:HTMLのスタートボタンの要素(取得済み)です。これに対して動作を追加します。addEventListener("click", ... )
:addEventListener
はイベント(ここでは「クリック」)を待ち受けるJavaScriptの組み込み関数です。"click"
は「クリックされた時」を意味し、スタートボタンが押されたときにこのコードを実行するという指示になります。() => { ... }
:これは「アロー関数」と呼ばれるJavaScriptの構文で、ここにボタンがクリックされたときに実行する内容を書きます。{ ... }
内に、ボタンが押された際の動作が記述されています。- 和訳:「スタートボタンがクリックされたら、次の動作を行うように設定しています。」
スタートボタンがクリックされたときの処理内容:
const minutes = document.getElementById("minutes").value;
if (minutes) {
timeLeft = minutes * 60;
clearInterval(countdown);
countdown = setInterval(updateTimer, 1000);
}
const minutes = document.getElementById("minutes").value;
id="minutes"
の入力フィールドに入力された値(分)を取得し、それをminutes
という定数に保存します。- 和訳:「分の入力欄から値を取得し、それをminutesという定数に保存します。」
if (minutes)
もしminutes
に値があれば、次の処理を実行します。このif
文は、条件が真であるときにだけ{ ... }
内の処理を実行する構文です。- 和訳:「もしminutesに値がある場合、次の処理を行います。」
timeLeft = minutes * 60;
minutes
を 60 秒で掛け算し、合計秒数をtimeLeft
に保存します。入力されたminutes
が 5 のときは5 * 60 = 300
(秒)になります。- 和訳:「入力された分を秒数に変換し、timeLeftに保存します。」
clearInterval(countdown);
既に動作しているカウントダウンがあれば、一度停止します。clearInterval
は、指定したカウントダウン動作を止めるためのJavaScriptの組み込み関数です。- 和訳:「既存のカウントダウン動作を停止します。」
clearInterval(countdown);
は、既に動作しているカウントダウンがある場合にそれを一時停止するために使います。
具体例
例:タイマーをリセットする場合
- ユーザーが「スタート」ボタンを押す
- たとえば、3分を設定して「スタート」ボタンを押すと、カウントダウンが始まります。
- このとき、
setInterval
関数で毎秒updateTimer
関数が実行され、timeLeft
が1秒ずつ減っていきます。
- ユーザーがもう一度「スタート」ボタンを押す
- もし、カウントダウンがまだ動いている途中で再度「スタート」ボタンを押して新しい時間(例えば5分)を入力した場合、2つのカウントダウンが同時に動くことを避ける必要があります。
- ここで
clearInterval(countdown);
が重要です。現在のカウントダウンを停止してから新しいカウントダウンを始めることで、不要なタイマーの重複を防ぎます。
- 具体的な動き
- 最初の「スタート」で 3分のカウントダウンが開始。
- 1分経過した時点でユーザーが新たに5分を設定して再度「スタート」を押す。
clearInterval(countdown);
により、3分の残り時間のカウントダウンが停止され、代わりに新たに5分のカウントダウンが開始。
例:リセットボタンを押した場合
- カウントダウンが進行中
- ユーザーが設定した時間でカウントダウンが動いているときに「リセット」ボタンを押すと、カウントダウンを最初の状態に戻します。
clearInterval(countdown);
の動作clearInterval(countdown);
により、現在動作しているカウントダウンが一時停止され、画面が「00:00」に戻ります。
理由のまとめ
clearInterval(countdown);
は、次のような状況で必要になります:
- カウントダウンが動作しているときに新たにスタートボタンを押した場合
- リセットボタンを押してカウントダウンを止めたい場合
こうすることで、複数のカウントダウンが同時に動作することを防ぎ、アプリの動作が正確になります。
countdown = setInterval(updateTimer, 1000);
1秒ごとにupdateTimer
関数を実行するように設定します。setInterval
は、指定した時間ごとに特定の動作を繰り返すJavaScriptの組み込み関数です。ここでは 1000 ミリ秒(1秒)ごとにupdateTimer
関数を呼び出しています。- 和訳:「1秒ごとにupdateTimer関数を実行するカウントダウンを開始します。」
8. stopButton.addEventListener("click", () => { ... });
こちらは、ストップボタンがクリックされたときの動作です。
clearInterval(countdown);
countdown
で動作しているカウントダウンを停止します。スタートボタンで設定したsetInterval
の繰り返し動作を止める役割です。clearInterval
は、指定したカウントダウン動作を止めるためのJavaScriptの組み込み関数です。- 和訳:「カウントダウンを一時停止します。」
9. resetButton.addEventListener("click", () => { ... });
リセットボタンがクリックされたときの動作です。
clearInterval(countdown);
timerDisplay.textContent = "00:00";
document.getElementById("minutes").value = "";
clearInterval(countdown);
再び、現在のカウントダウンを停止します。clearInterval
は、指定したカウントダウン動作を止めるためのJavaScriptの組み込み関数です。- 和訳:「カウントダウンを停止します。」
timerDisplay.textContent = "00:00";
id="timer"
の表示内容を「00:00」に戻します。- 和訳:「タイマー表示を00:00に戻します。」
document.getElementById("minutes").value = "";
入力フィールドの値を空にしてリセットします。- 和訳:「分数の入力欄を空にします。」
HTMLコードとJavascriptコードを同じフォルダに保存してアプリを起動させると以下のようになります。保存方法はPCのメモ帳でそれぞれのコードを入力し、countdown.htmlとtimer.jsと保存します。
(countdownとtimerは名称を変えることができますがtimerに関してはコード内にその名称が組み込まれているので帰る場合はコード内の名称も変えてください)
ストップ後の残り時間から再度スタートさせための修正
このコードだとストップボタンを押してから、スタートで再開すると最初からのカウントダウンに戻ってしまいます。例えば60秒のカウントダウン中にストップボタンを押しからスタートボタンで再開すると、また60秒からのカウントダウンが始まってしまいます。これをストップ後に再度スタートするとその残り時間から再開するようにコードを調整します。
Javascriptを修正する
変更前のコード
// スタートボタンが押されたときの動作
startButton.addEventListener("click", () => {
const minutes = document.getElementById("minutes").value; // 入力された分数を取得
if (minutes) {
timeLeft = minutes * 60; // 分数を秒数に変換
clearInterval(countdown); // 既存のカウントダウンをクリア
countdown = setInterval(updateTimer, 1000); // 1秒ごとにタイマーを更新
}
});
// ストップボタンが押されたときの動作
stopButton.addEventListener("click", () => {
clearInterval(countdown); // カウントダウンを停止
});
// リセットボタンが押されたときの動作
resetButton.addEventListener("click", () => {
clearInterval(countdown); // カウントダウンを停止
timerDisplay.textContent = "00:00"; // タイマー表示を初期状態に戻す
document.getElementById("minutes").value = ""; // 入力フィールドもクリア
});
変更後のコード
let isPaused = false; // 一時停止状態かどうかを判断する変数
// スタートボタンが押されたときの動作
startButton.addEventListener("click", () => {
if (!isPaused) { // 一時停止状態でない場合のみ、新しい時間を設定
const minutes = document.getElementById("minutes").value; // 入力された分数を取得
if (minutes) {
timeLeft = minutes * 60; // 分数を秒数に変換
}
}
clearInterval(countdown); // 既存のカウントダウンをクリア
countdown = setInterval(updateTimer, 1000); // 1秒ごとにタイマーを更新
isPaused = false; // 一時停止状態を解除
});
// ストップボタンが押されたときの動作
stopButton.addEventListener("click", () => {
clearInterval(countdown); // カウントダウンを停止
isPaused = true; // 一時停止状態に設定
});
// リセットボタンが押されたときの動作
resetButton.addEventListener("click", () => {
clearInterval(countdown); // カウントダウンを停止
timerDisplay.textContent = "00:00"; // タイマー表示を初期状態に戻す
document.getElementById("minutes").value = ""; // 入力フィールドもクリア
isPaused = false; // 一時停止状態を解除
timeLeft = 0; // 残り時間もリセット
});
1. let isPaused = false;
このコードは、一時停止中かどうかを判断するための変数 isPaused
を定義しています。
let
:JavaScriptで変数を宣言するキーワードです。isPaused
:一時停止状態かどうかを判別するための変数で、true
(一時停止中)またはfalse
(一時停止していない)を保存します。初期状態ではfalse
に設定され、一時停止ボタンを押すとtrue
に変わります。= false
:初期状態は一時停止していないため、false
に設定しています。- 和訳:「一時停止状態かどうかを判断するための変数を作成し、初期状態では一時停止していないのでfalseに設定しています。」
2. startButton.addEventListener("click", () => { ... });
スタートボタンがクリックされたときの動作です。
スタートボタンの動作内容
if (!isPaused)
:一時停止状態でない(isPaused
がfalse
)場合のみ、次の処理を実行します。!
:否定の意味を表す記号で、isPaused
がfalse
のときにtrue
として扱います。- スタートボタンがクリックされたとき、まず
if (!isPaused)
の部分で 一時停止状態でない場合のみ 新しい時間を設定します。 - つまり、カウントダウンが一時停止中 (
isPaused
がtrue
) であれば、入力フィールドから再度時間を取得することなく、そのまま現在のtimeLeft
の残り時間を使って再開します。 - 一時停止中 (
isPaused
がtrue
) の場合、新しいtimeLeft
の設定は行われず、以前のtimeLeft
の値が保持されているので、残りの時間からカウントダウンが再開されます。 - 和訳:「もしisPausedがfalse(一時停止していない状態)の場合、次の処理を実行します。」
const minutes = document.getElementById("minutes").value;
:分数入力フィールドから値を取得し、それをminutes
という定数に保存します。- 和訳:「分の入力欄から値を取得し、それをminutesという定数に保存します。」
if (minutes)
:minutes
に値がある場合(0以外の場合)、次の処理を実行します。- 和訳:「もしminutesに値がある場合、次の処理を行います。」
timeLeft = minutes * 60;
:minutes
を秒に変換してtimeLeft
に保存します。- 和訳:「入力された分を秒数に変換し、timeLeftに保存します。」
clearInterval(countdown);
:既に動作しているカウントダウンがあれば、一度停止します。- 和訳:「既存のカウントダウン動作を停止します。」
countdown = setInterval(updateTimer, 1000);
:1秒ごとにupdateTimer
関数を実行してカウントダウンを開始します。- 和訳:「1秒ごとにupdateTimer関数を実行するカウントダウンを開始します。」
isPaused = false;
:一時停止状態を解除し、isPaused
をfalse
に設定します。- 和訳:「一時停止状態を解除して、isPausedをfalseに設定します。」
3. stopButton.addEventListener("click", () => { ... });
ストップボタンがクリックされたときの動作です。
clearInterval(countdown);
:現在動作しているカウントダウンを停止します。- 和訳:「カウントダウンを停止します。」
isPaused = true;
:一時停止状態を記録し、isPaused
をtrue
に設定します。- トップボタンがクリックされると、
clearInterval(countdown);
で現在のカウントダウンを停止し、isPaused
をtrue
に設定します。 - これにより、再度スタートボタンを押したときに、一時停止状態からの再開を判断できるようになります。
- 和訳:「isPausedをtrueに設定し、一時停止状態にします。」
- トップボタンがクリックされると、
4. resetButton.addEventListener("click", () => { ... });
リセットボタンがクリックされたときの動作です。
clearInterval(countdown);
:現在動作しているカウントダウンを停止します。- 和訳:「カウントダウンを停止します。」
timerDisplay.textContent = "00:00";
:タイマー表示を「00:00」に戻します。- 和訳:「タイマー表示を00:00に戻します。」
document.getElementById("minutes").value = "";
:分数の入力フィールドを空にしてリセットします。- 和訳:「分数の入力欄を空にします。」
isPaused = false;
:一時停止状態を解除し、isPaused
をfalse
に設定します。- 和訳:「isPausedをfalseに設定し、一時停止状態を解除します。」
timeLeft = 0;
:残り時間もリセットし、timeLeft
を 0 に設定します。- 和訳:「残り時間を0に設定し、初期状態に戻します。」
簡単な流れ
- 再度スタートボタンを押すと、
isPaused
がtrue
のため、timeLeft
がリセットされず、残りの時間から再開されます。 - スタートボタンを押すと、
isPaused
がfalse
の場合に限り新しい時間が設定され、カウントダウンが始まります。 - ストップボタンを押すと、カウントダウンが停止され、
isPaused
がtrue
になり、一時停止状態に入ります。
完成したJavascriptコード
let countdown; // カウントダウンのための変数を定義
let timeLeft; // 残り時間を保存する変数を定義
let isPaused = false; // 一時停止状態かどうかを判断する変数
const timerDisplay = document.getElementById("timer"); // タイマー表示のエリアを取得
const startButton = document.getElementById("start"); // スタートボタンを取得
const stopButton = document.getElementById("stop"); // ストップボタンを取得
const resetButton = document.getElementById("reset"); // リセットボタンを取得
// スタートボタンが押されたときの動作
startButton.addEventListener("click", () => {
if (!isPaused) { // 一時停止状態でない場合のみ、新しい時間を設定
const minutes = document.getElementById("minutes").value; // 入力された分数を取得
if (minutes) {
timeLeft = minutes * 60; // 分数を秒数に変換
}
}
clearInterval(countdown); // 既存のカウントダウンをクリア
countdown = setInterval(updateTimer, 1000); // 1秒ごとにタイマーを更新
isPaused = false; // 一時停止状態を解除
});
// ストップボタンが押されたときの動作
stopButton.addEventListener("click", () => {
clearInterval(countdown); // カウントダウンを停止
isPaused = true; // 一時停止状態に設定
});
// リセットボタンが押されたときの動作
resetButton.addEventListener("click", () => {
clearInterval(countdown); // カウントダウンを停止
timerDisplay.textContent = "00:00"; // タイマー表示を初期状態に戻す
document.getElementById("minutes").value = ""; // 入力フィールドもクリア
isPaused = false; // 一時停止状態を解除
timeLeft = 0; // 残り時間もリセット
});
// タイマーを更新する関数
function updateTimer() {
if (timeLeft > 0) {
timeLeft--; // 残り時間を1秒減らす
const minutes = Math.floor(timeLeft / 60); // 残り分を計算
const seconds = timeLeft % 60; // 残り秒を計算
timerDisplay.textContent = `${String(minutes).padStart(2, "0")}:${String(seconds).padStart(2, "0")}`; // タイマー表示を更新
} else {
clearInterval(countdown); // カウントダウンを停止
timerDisplay.textContent = "時間切れ!"; // 時間切れの表示
}
}
本日の感想
このアプリは前回のメモ帳アプリと違ってかなりシンプルだったので半日で完成しました。でもコード全体を100%理解しているわけではなくなんとなくの理解です。基礎の基礎は100%理解しておいた方がいいという学校の常識が頭から離れませんがAIを信じてスピードの方を重視します。
追記
半日で終わったのですが、カウントダウン中に導火線についた火がダイナマイトに近づいていくというアニメーションを追加したら、これが予想以上に時間がかかった。速攻でできると思いきや、アニメーション管理の複雑さにメンタルをやられました。。30日目にして初のスランプかもです。
27-29日目の記事はこちら
メモ帳アプリの作成 27-29日目 2024/11/2-4(お金持ちまでの道のり)
31日目の記事はこちら
フォームアプリ(例:ユーザー登録フォーム)について 31日目 2024/11/6(お金持ちまでの道のり)
ここに初めて来た人はゼヒ0日目を読んでください。プログラミング知識0のおじさんがお金持ちになるまでのプランと熱い思いが載っています。私と一緒に運要素を排除したゴリゴリの脳筋プレイでお金持ちを目指しませんか?
0日目の記事はこちら
お金持ちまでの道のり:0日目
コードの読み方が全く分からないという方は以下の記事がオススメです。コードの読み方の説明が一番詳しく書かれてある記事です。
ToDoリストアプリの作成 12-15日目 2024/10/18-21(お金持ちまでの道のり)
コメント