JavaScriptでタイマー機能を作成する方法

JavaScriptでタイマー機能を作成する方法 JavaScript

この記事では、JavaScriptタイマーを作成する方法について見ていきたいと思います。
ここで説明する通りにコードを書くことで次にようなタイマーを作成することができます。

Sample Code

HTMLの作成

ここでは、タイマーを操作するためのボタンとタイマーをセットするためのボタンと表示する要素を作成します。

<div class="board">
  <div>
    <input type="button" id="start" class="inactive" value="開始">
    <input type="button" id="stop" class="inactive" value="一時停止">
    <input type="button" id="reset" class="inactive" value="リセット">
  </div>
  <div id="setTimeBtns">
    <input type="button" id="addHours" value="時">
    <input type="button" id="addMinutes" value="分">
    <input type="button" id="addSeconds" value="秒">
  </div>
  <p id="display"></p>
</div>

CSSの作成

ここでは、CSSでボタンや背景色などのデザインを設定します。

.board {
  background-color: aqua;
  height: 150px;
  width: 230px;
  padding: 20px;
  margin: 0 auto;
}
#setTimeBtns { margin-top: 10px;}
.inactive { opacity: 50%;}
#display {
  padding: 10px;
  background-color: #fff;
  font-size: 1.4em;
}
.board,#display {
  text-align: center;
  user-select: none;
  border-radius: 5px;
}

以下からはJavaScriptの処理です。

変数の定義

ここでは、あとで使う変数を定義していきます。

let hours;
let hours;
let minutes;
let seconds;
let initial = true;
let running = false;
let timeUp = false;
let display = document.getElementById("display");
let start = document.getElementById("start");
let stop = document.getElementById("stop");
let reset = document.getElementById("reset");
let addHours = document.getElementById("addHours");
let addMinutes = document.getElementById("addMinutes");
let addSeconds = document.getElementById("addSeconds");

※ここで用いているgetElementById()は、HTML要素をIdをキーに取得するメソッドです。
詳しくは以下の記事にて参照していただけます。
JavaScriptのgetElementById()の使い方

時間をリセットする関数の定義

ここでは、時・分・秒をリセットするための関数を定義します。

function resetTime() {
  hours = 0;
  minutes = 0;
  seconds = 0;
}

時間を表示する関数の定義

ここでは、時間を表示する関数を定義します。

function displayTime() {
  display.textContent = `${("0" + hours).slice(-2)}:${("0" + minutes).slice(-2)}:${("0" + seconds).slice(-2)}`;
}

ここで用いている("0" + hours).slice(-2)は、文字列「0」に変数「hours」に代入されている数値をつなげて文字列にし、その文字列の末尾から数えて2番目の文字から末尾の文字までを切り取るという意味になります。
そうすることで、2桁の数値を表示にすることができるわけですね。
「minutes」や「seconds」についても同様です。
なお、ここで用いているslice()については以下の記事で解説をしています。
JavaScriptのslice()で文字列の一部を切り抜く方法

カウントダウンをする関数の定義

ここでは、カウントダウンをする関数を定義していきます。

function countDown() {
  setTimeout(()=>{
    if(!running) {
      return;
    } else if(seconds > 0) {
      seconds--;
      displayTime();
    } else if(seconds === 0) {
        if(minutes > 0) {
          minutes--;
          seconds = 59;
          displayTime();
        } else if(minutes === 0) {
          if(hours > 0) {
            hours--;
            minutes = 59;
            seconds = 59;
            displayTime();
          } else if(hours === 0) {
            stopped = true;
            timeUp = true;
            display.textContent = "タイムアップです。";
            stop.classList.add("inactive");
          }
        }
    }
    countDown();
  }, 1000);
}

ここでは、setTimeout()を用いて、変数「running」がfalseであれば「return」で関数を終了させ、そうでなければ、1000ミリ秒(=1秒)毎にcountDown()を実行させるという内容ですね。
●条件分岐は次の通りになります。
・「seconds」が0より大きい場合
→「seconds」から1をマイナス
・「seconds」が0で「minutes」が0より大きい場合
→「minutes」から1をマイナスし、「seconds」に59を代入
・「seconds」が0で、「minutes」が0で「hours」が0より大き場合
→「hours」から1を減算し、「seconds」と「minutes」に59を代入
・「seconds」が0で、「minutes」が0で「hours」が0の場合
→「タイムアップです。」と表示させる。

ボタンをクリックしたときの処理を定義

ここでは、ボタンをクリックしたときに実行される処理を定義していきます。

「start」ボタンをクリックしたときの処理

start.addEventListener("click", () => {
  if(initial) {
    return;
  } else if(running) {
    return;
  } else {
    running = true;
    start.classList.add("inactive");
    stop.classList.remove("inactive");
    reset.classList.add("inactive");
    addHours.classList.add("inactive");
    addMinutes.classList.add("inactive");
    addSeconds.classList.add("inactive");
    countDown();
  }
});

ここでは、「start」ボタンを押した時、もし変数「initial」が「true」であれば「return」を用いて処理を終了させます。
そうでない場合でも、もし変数「running」が「true」であれば同様に「return」を用いて
処理を終了させます。
上記の2パターンの両方に当てはまらない場合は、「running」を「true」にして「stop」ボタン以外を半透明にしたうえでcountDown()を開始(もしくは再開)させます。

「stop」ボタンをクリックしたときの処理

stop.addEventListener("click", () => {
  if(running) {
    running = false;
    stop.classList.add("inactive");
    start.classList.remove("inactive");
    reset.classList.remove("inactive");
    addHours.classList.remove("inactive");
    addMinutes.classList.remove("inactive");
    addSeconds.classList.remove("inactive");
  } else {
    return;
  }
});

ここでは、「stop」ボタンを押した時に、もし変数「running」が「true」である場合は「running」を「false」にして「stop」ボタン以外のボタンを不透明にします。
そうでなければ、「return」で処理を終了させます。

「reset」ボタンをクリックしたときの処理

reset.addEventListener("click", () => {
  if(running) {
    return;
  } else if(hours !==0 || minutes !== 0 || seconds !== 0) {
    initial = true;
    resetTime();
    displayTime();
    start.classList.add("inactive");
    reset.classList.add("inactive");
    addHours.classList.remove("inactive");
    addMinutes.classList.remove("inactive");
    addSeconds.classList.remove("inactive");
  }
});

ここでは、「reset」ボタンを押した時に、もし変数「running」が「true」である場合は「return」で処理を終了させます。
そうでなければ、変数「initial」を「true」にし、resetTime()で変数「hours」「minutes」「seconds」の値を全て0にし、「start」「reset」ボタンを半透明にし、「addHours」「addMinutes」「addSeconds」ボタンを不透明にします。

「addHours」ボタンをクリックしたときの処理

addHours.addEventListener("click", () => {
  if(running) {
    return;
  } else {
    hours++;
    displayTime();
    if(hours !== 0 || minutes !== 0 || seconds !== 0) {
      initial = false;
      start.classList.remove("inactive");
      reset.classList.remove("inactive");
    }
  }
});

ここでは、「addHours」ボタンをクリックした場合の処理を指定します。
その中で、もし変数「running」が「true」である場合は「return」で処理を終了させ、そうでない場合は変数「hours」に1を加算し、displayTime()でディスプレイに時間を表示させ、もし変数「hours」「minutes」「seconds」のどれかが0でない場合は、「start」ボタンと「reset」ボタンを不透明にします。

「addMinutes」ボタンをクリックしたときの処理

addMinutes.addEventListener("click", () => {
  if(running) {
    return;
  } else if(minutes < 59) {
    minutes++;
  } else {
    minutes = 0;
    hours++;
  }
  displayTime();
  if(hours !== 0 || minutes !== 0 || seconds !== 0) {
    initial = false;
    start.classList.remove("inactive");
    reset.classList.remove("inactive");
  }
});

ここでは、「addMinutes」ボタンをクリックした時の処理を指定します。
その中で、もし変数「running」が「true」であれば、「return」で処理を終了させます。
それ以外の場合で、変数「minutes」が59よりも小さい場合は「minutes」に1を加算し、
そうでない場合は、「minutes」に0を代入し、「hours」に1を加算します。
そしてdisplayTime()でディスプレイに時間を表示させます。
そして、「addHours」と同様に、変数「hours」「minutes」「seconds」のどれかが0でない場合は、「start」ボタンと「reset」ボタンを不透明にします。

「addSeconds」ボタンをクリックしたときの処理

addSeconds.addEventListener("click", () => {
  if(running) {
    return;
  } else if(seconds < 59) {
    seconds++;
  } else {
    if(minutes < 59) {
      seconds = 0;
      minutes++;
    } else {
      seconds = 0;
      minutes = 0;
      hours++;
    }
  }
  
  displayTime();
  if(hours !== 0 || minutes !== 0 || seconds !== 0) {
    initial = false;
    start.classList.remove("inactive");
    reset.classList.remove("inactive");
  }
});

ここでは、「addSeconds」ボタンをクリックした時の処理を指定します。
その中で、もし「running」が「true」であれば、処理を終了させます。
そうではなく、もし「seconds」が59よりも小さい場合は「seconds」に1を加算させ、そうではなくもし「seconds」が59以上である場合で「minutes」が59よりも小さい場合は「seconds」に0を代入し、「minutes」に1を加算します。そうでもなく「minutes」が59以上である場合は「seconds」と「minutes」に0を代入し「hours」に1を加算します。
そして、「addHours」「addMinutes」ボタンを押した時と同様に、ディスプレイに時間を表示し、変数「hours」「minutes」「seconds」のどれかが0でない場合は、「start」ボタンと「reset」ボタンを不透明にします。

関数の実行

setTime();
displayTime();

ここでは、最初にページが表示されたときに行われる処理を指定します。

完成

上記で説明したコードをつなぎ合わせると以下のようになります。

let hours;
let minutes;
let seconds;
let initial = true;
let running = false;
let timeUp = false;
let display = document.getElementById("display");
let start = document.getElementById("start");
let stop = document.getElementById("stop");
let reset = document.getElementById("reset");
let addHours = document.getElementById("addHours");
let addMinutes = document.getElementById("addMinutes");
let addSeconds = document.getElementById("addSeconds");

function resetTime() {
  hours = 0;
  minutes = 0;
  seconds = 0;
}

function displayTime() {
  display.textContent = `${("0" + hours).slice(-2)}:${("0" + minutes).slice(-2)}:${("0" + seconds).slice(-2)}`;
}

function countDown() {
  setTimeout(()=>{
    if(!running) {
      return;
    } else if(seconds > 0) {
      seconds--;
      displayTime();
    } else if(seconds === 0) {
        if(minutes > 0) {
          minutes--;
          seconds = 59;
          displayTime();
        } else if(minutes === 0) {
          if(hours > 0) {
            hours--;
            minutes = 59;
            seconds = 59;
            displayTime();
          } else if(hours === 0) {
            stopped = true;
            timeUp = true;
            display.textContent = "タイムアップです。";
            stop.classList.add("inactive");
          }
        }
    }
    countDown();
  }, 1000);
}

start.addEventListener("click", () => {
  if(initial) {
    return;
  } else if(running) {
    return;
  } else {
    running = true;
    start.classList.add("inactive");
    stop.classList.remove("inactive");
    reset.classList.add("inactive");
    addHours.classList.add("inactive");
    addMinutes.classList.add("inactive");
    addSeconds.classList.add("inactive");
    countDown();
  }
});

stop.addEventListener("click", () => {
  if(running) {
    running = false;
    stop.classList.add("inactive");
    start.classList.remove("inactive");
    reset.classList.remove("inactive");
    addHours.classList.remove("inactive");
    addMinutes.classList.remove("inactive");
    addSeconds.classList.remove("inactive");
  } else {
    return;
  }
});

reset.addEventListener("click", () => {
  if(running) {
    return;
  } else if(hours !==0 || minutes !== 0 || seconds !== 0) {
    initial = true;
    resetTime();
    displayTime();
    start.classList.add("inactive");
    reset.classList.add("inactive");
    addHours.classList.remove("inactive");
    addMinutes.classList.remove("inactive");
    addSeconds.classList.remove("inactive");
  }
});

addHours.addEventListener("click", () => {
  if(running) {
    return;
  } else {
    hours++;
    displayTime();
    if(hours !== 0 || minutes !== 0 || seconds !== 0) {
      initial = false;
      start.classList.remove("inactive");
      reset.classList.remove("inactive");
    }
  }
});

addMinutes.addEventListener("click", () => {
  if(running) {
    return;
  } else if(minutes < 59) {
    minutes++;
  } else {
    minutes = 0;
    hours++;
  }
  displayTime();
  if(hours !== 0 || minutes !== 0 || seconds !== 0) {
    initial = false;
    start.classList.remove("inactive");
    reset.classList.remove("inactive");
  }
});

addSeconds.addEventListener("click", () => {
  if(running) {
    return;
  } else if(seconds < 59) {
    seconds++;
  } else {
    if(minutes < 59) {
      seconds = 0;
      minutes++;
    } else {
      seconds = 0;
      minutes = 0;
      hours++;
    }
  }
  
  displayTime();
  if(hours !== 0 || minutes !== 0 || seconds !== 0) {
    initial = false;
    start.classList.remove("inactive");
    reset.classList.remove("inactive");
  }
});

resetTime();
displayTime();

コメント

タイトルとURLをコピーしました