一定時間おきに処理を行う
一定時間おきに特定の処理を行うには、setInterval()メソッドを使います。
基本的な使い方をする場合、第一引数に関数、第二引数に時間(ミリ秒)を指定します。
- setInterval(func,delay)
- function test() { …処理… }
- setInterval(test, 1000)
上の例では、test関数を1000ミリ秒(=1秒)間隔で実行し続ける…ということになります。
これを利用して、ボタンクリックで一定時間ごとにカウントをが減っていくコードのサンプルを下に用意しました。
HTML
<div class="timer-container">
<div id="timer">3</div>
<button id="startBtn">START</button>
</div>
JavaScript
//タイマー表示要素を取得
const timer = document.getElementById("timer");
//スタートボタンを取得
const startBtn = document.getElementById("startBtn");
//カウントの秒数
let count = 3;
//スタートボタンクリックで処理を行う
startBtn.addEventListener("click", () => {
//一定時間おきに行いたい関数を宣言
function countDown() {
if(count > 0) {
//countが0より大きい場合はcountを1ずつ減らす
count--;
//タイマー表示要素にcountの数値を表示
timer.textContent = count;
} else {
//countが0以下になったら0を表示
timer.textContent = 0;
console.log("タイマーが停止しました");
}
}
//1000ミリ秒(1秒)ごとに、countDown関数を実行
setInterval(countDown,1000);
});
上のコードを実行すると、1秒ごとに3から1ずつカウントが減っていき、見た目上は0で停止します。
『見た目上』という表現をしたのは、上のコードではあくまで0で停止しているように見えるだけで、関数自体は1000m秒ごとに実行され続けることになるからです。
コンソール画面で確認してみると、『タイマーが停止しました』のログメッセージが、1秒おきに何度も表示され続けることが確認できます。
処理が停止されていないのでログメッセージが1秒おきに増えている
これではブラウザに余計な負荷をかけ続けることになってしまいますね。
そこで、次のステップとして、setInterval()の停止を行ってみましょう。
setInterval()は、intervalIDという戻り値を返すようになっています。
そして、これを定数や変数に格納してintervalIDを呼び出せる状態にしておき、clearInterval()メソッドの引数にintervalIDを渡せば処理を停止させることができます。
clearInterval()を使って、処理が停止するように改良を加えたサンプルが下です。
JavaScript
//タイマー表示要素を取得
const timer = document.getElementById("timer");
//スタートボタンを取得
const startBtn = document.getElementById("startBtn");
//カウントの秒数
let count = 3;
//スタートボタンクリックで処理を行う
startBtn.addEventListener("click", () => {
//一定時間おきに行いたい関数を宣言
function countDown() {
if(count > 0) {
//countが0より大きい場合はcountを1ずつ減らす
count--;
//タイマー表示要素にcountの数値を表示
timer.textContent = count;
} else {
//countが0以下になったら0を表示
timer.textContent = 0;
console.log("タイマーが停止しました");
//clearIntervalで処理を停止させる
clearInterval(countDownTimer);
}
}
//1000ミリ秒(1秒)ごとに、countDown関数を実行
//定数countDownTimerに、intervalIDを格納している
const countDownTimer = setInterval(countDown,1000);
});
これで、カウントが0になったら見た目だけでなく、内部的にもちゃんと処理が停止するようになりました。
コンソールで確認すると、ログメッセージの表示は一回で終わっており、処理が完全に停止していることがわかります。
処理が停止されているので、ログメッセージは1つだけ
ブラウザに余計な負荷をかけ続けることのない、より実用的なカウントダウン機能を実装することができましたね。
リセットボタンを付け加えた実際のサンプルを下に置いておくので、挙動を確かめてみてください。
ちなみにですが、スタートボタンをクリックした後は、タイマーが停止してリセットされるまで再度クリックできないように調整を加えています。
これは、スタートボタンを連打されるとsetInterval()の処理が重なってしまい、正しくカウントダウンできなくなるためです。
クリックできないようにするには、CSSのpointer-eventsプロパティなどを使って調整すると良いです。
単純な数値のカウントダウンだけならばこれだけでも十分ですが、カウントダウンを分と秒に変換したい場合も多いですよね。
ということで、次の章では、『○分×秒』というふうにカウントダウンする機能を作ってみたいと思います!
POINT!
- ・一定の時間おきに処理を行うには、setInterval()メソッドを使う!
- ・通常の使い方では、第一引数に関数、第二引数にミリ秒を指定する!
- ・setInterval()の処理を停止させるには、intervalIDを利用してclearInterval()を実行する!
カウントを分と秒に分ける
カウントを分と秒に分ける…たとえば、90秒を1分30秒に変換したいとしましょう。
このような計算を行う際、小数点以下を切り捨てたいことがよくあります。
90秒を60で割ると1.5(分)になりますが、分の整数部分(1)だけを得たい場合、小数点以下(0.5の部分)は必要ありませんよね。
また、90秒から90を60で割った整数部分(1)× 60 を引けば、90 – 60 = 30 となり、秒の部分だけ(30秒)を計算できます。
このように、小数点以下を切り捨てて整数部分のみを利用したい場合に使えるのが、Math.floor()メソッドです。
ここで注意点です。Math.floor()は小数点以下を切り捨てる時に使うと言いましたが、正確には与えられた数値以下の最大の整数を得るものです。
数値が正の数であれば、単に小数点以下を切り捨てた結果が得られると認識して良いのですが、負の数の場合は『与えられた数値以下の最大の整数』という認識を持っておかないと、予想と結果がズレる場合があり得ます。
JavaScript
console.log(Math.floor(0.6)); // 0
console.log(Math.floor(3.15)); // 3
console.log(Math.floor(-2.05)); // -3
ここでは負の数を扱わないので、Math.floor() = 小数点以下切り捨て…という認識でOKです。
それでは、90秒を1分30秒に変換するコードのサンプルを確認してきましょう。
HTML
<div class="timer-container">
<div id="minute"></div>
<div id="second"></div>
<button id="startBtn">START</button>
</div>
JavaScript
//タイマー表示要素を取得
const minute = document.getElementById("minute");
const second = document.getElementById("second");
//カウントの秒数
let count = 90;
//分に変換
let minuteCount = Math.floor(count / 60);
//秒に変換
let secondCount = count - (Math.floor(count / 60) * 60);
//変換した分と秒を要素に表示
minute.textContent = `${minuteCount}分`;
second.textContent = `${secondCount}秒`;
これで、90秒のカウントを1分30秒と表示させることができます。(下は表示結果です)
90カウントが1分30秒になった
あとは、前章で紹介したカウントダウン機能を実装すれば、分と秒に分けたカウントダウンタイマーの完成です。
下はカウントを分と秒に分けたカウントダウンタイマーのサンプルコードです。
JavaScript
//タイマー表示要素を取得
const minute = document.getElementById("minute");
const second = document.getElementById("second");
//スタートボタンを取得
const startBtn = document.getElementById("startBtn");
//カウントの秒数
let count = 90;
//分に変換
let minuteCount = Math.floor(count / 60);
//秒に変換
let secondCount = count - (Math.floor(count / 60) * 60);
//変換した分と秒を要素に表示
minute.textContent = `${minuteCount}分`;
second.textContent = `${secondCount}秒`;
//スタートボタンクリックで処理を行う
startBtn.addEventListener("click", () => {
//一定時間おきに行いたい関数を宣言
function countDown() {
if(count > 0) {
//countが0より大きい場合はcountを1ずつ減らす
count--;
//分に変換
let minuteCount = Math.floor(count / 60);
//秒に変換
let secondCount = count - (Math.floor(count / 60) * 60);
//タイマー表示要素にcountの数値を表示
minute.textContent = `${minuteCount}分`;
second.textContent = `${secondCount}秒`
} else {
//countが0以下になったら0分0秒を表示して、処理を停止させる
minute.textContent = "0分";
second.textContent = "0秒";
console.log("タイマーが停止しました");
clearInterval(countDownTimer);
}
}
const countDownTimer = setInterval(countDown,1000);
});
下は、リセットボタンと停止ボタンを付け加えたカウントダウンタイマーのサンプルです。
カウントダウンの表示が分と秒に分けられ、それぞれ正しくカウントダウンされている様子が確認できます。
時間表示を分と秒に分けることで、60秒(1分)を超えるタイマーでも残り時間を見やすく、分かりやすくすることができましたね。
しかし、まだ気になる点が残っています。
通常、時間を表す際は『2分05秒(2:05)』というふうに、秒が1桁の時は0を足して2桁で表すことが多いですよね。
『1:1』のような表記だと、1対1(比率)を表しているように見えてしまいますが、『1:01』ならば、時間を表していることがより分かりやすくなります。
というわけで次の章では、秒が1桁になったときは0を付け足すという処理を行なってみたいと思います!
POINT!
- ・小数点以下を切り捨てたい時は、Math.floor()メソッドを使う!
- ・Math.floor()は、与えられた数値以下の最大の整数を得る!
- ・正の数に対してMath.floor()で処理する場合は、単に小数点以下が切り捨てられると認識してOK!
秒が1桁の時に0を付け足す
秒が1桁(9秒以下)になった時にのみ『0』を付け足し、『09』というふうに表示させたい場合はどうすれば良いのでしょうか?
方法は色々あると思いますが、ここでは使用頻度の高い三項演算子を使ってみたいと思います。
三項演算子とは、Aという条件がtrueならBという処理をし、そうでない(false)の場合はCの処理をする…というふうに、条件分岐を行うことができる式のことです。
条件分岐と言えばif文がメジャーですが、if文は文であって式ではないので、returnで戻り値を返すときなど、式しか挿入できない場面では使うことができません。
一方、三項演算子は式を挿入できる場面で使用できるため、非常に使い勝手が良いです。
三項演算子の記述は以下のようになります。
- 三項演算子
- 条件 ? trueの場合の処理 : falseの場合の処理
これを利用して、『秒数が10以上ならば秒数をそのまま表示し、それ以外(10未満)ならば0を付け足す』ようにしてみましょう。
秒数表示を改良したサンプルのコードは次のようになります。(改良部分は赤色のところです)
JavaScript
//タイマー表示要素を取得
const minute = document.getElementById("minute");
const second = document.getElementById("second");
//スタートボタンを取得
const startBtn = document.getElementById("startBtn");
//カウントの秒数
let count = 75;
//分に変換
let minuteCount = Math.floor(count / 60);
//秒に変換
let secondCount = count - (Math.floor(count / 60) * 60);
//変換した分と秒を要素に表示
minute.textContent = `${minuteCount}分`;
second.textContent = `${secondCount}秒`;
//スタートボタンクリックで処理を行う
startBtn.addEventListener("click", () => {
//一定時間おきに行いたい関数を宣言
function countDown() {
if(count > 0) {
//countが0より大きい場合はcountを1ずつ減らす
count--;
//分に変換
let minuteCount = Math.floor(count / 60);
//秒に変換
let secondCount = count - (Math.floor(count / 60) * 60);
//タイマー表示要素にcountの数値を表示
minute.textContent = `${minuteCount}分`;
//秒が10秒以上ならばそのまま秒数を表示させ、それ以外(9以下)になると0を付け足す
second.textContent = secondCount >= 10 ? `${secondCount}秒` : `0${secondCount}秒`;
} else {
//countが0以下になったら0分00秒を表示して、処理を停止させる
minute.textContent = "0分";
second.textContent = "00秒";
console.log("タイマーが停止しました");
clearInterval(countDownTimer);
}
}
const countDownTimer = setInterval(countDown,1000);
});
これでプログラムを実行すると、下のように秒の桁が1桁(9秒以下)の時は0が付け足されます。
0が付け足されて07秒という表示になった
なお、確認を容易にするため、カウントも90秒(1分30秒)から75秒(1分15秒)に変更しています。
こちらも確認用のサンプルを置いておくので、実際に挙動を確かめてみてください。
秒数が1桁の時に0が付け足されることにより、残りの時間がより見やすくなりましたね!
『より見やすく、より分かりやすくするにはどのように表示したら良いか?』という部分は、プログラミングの知識だけでなく、UI/UXデザインの知識や考え方も重要となります。
フロントエンド開発とデザインは切っても切り離せない関係なので、興味が出てきたらUIデザインについて深く学んでみるのも良いかもしれません。
POINT!
- ・三項演算子で条件別の処理を簡単に行うことができる!
- ・三項演算子は文ではなく式なので、if文と違って式を挿入できる場所で使用できる!
- ・見やすく、分かりやすいアプリを作るには、UIデザインの知識も重要!