【JavaScript ~カウントダウンタイマー応用~】勉強メモ14

JavaScriptちゃんと学習中。
今回はカウントダウンタイマーの応用です。
<b>残り時間が刻一刻と変化する</b>実装をします。
ほぼ自分の勉強メモです。
過度な期待はしないでください。

前回の記事を参照の元作成してます。
必要が有れば参照下さい。
[【JavaScript ~カウントダウンタイマーの作成~】勉強メモ13](https://qiita.com/k-yasuhiro/items/7e7afa7f04a2d860be5a)

完成図
-
![image](https://i.gyazo.com/b073244fba70f544efd29f2ab3560c41.gif)
<br>


実装手順
-
- 残り時間を再計算をする関数を作成
- その関数を1秒ごとに繰り返す為の関数を作成
<br>

前回迄のコード
-

```.js:JavaScript
'use strict';

function countdown(set) {
  const now = new Date();

  const rest = set.getTime() - now.getTime();
  const sec = Math.floor(rest / 1000) % 60;
  const min = Math.floor(rest / 1000 / 60) % 60;
  const hours = Math.floor(rest / 1000 / 60 / 60) % 24;
  const days = Math.floor(rest / 1000 / 60 / 60 / 24);
  const count = [days, hours, min, sec];

  return count;
}

let goal = new Date();
goal.setHours(23);
goal.setMinutes(59);
goal.setSeconds(59);

const counter = countdown(goal);
const time = `${counter[1]}時間${counter[2]}分${counter[3]}秒`;
document.getElementById('timer').textContent = time;
```

```.html:HTML
<p>後、<span id="timer"></span>で1日が終わります。</p>
```
<br>

再計算する関数作成
-
- functionを使って新たな関数作成

下記の３行を関数にして、その関数を呼び出す記載をする

```
const counter = countdown(goal);
const time = `${counter[1]}時間${counter[2]}分${counter[3]}秒`;
document.getElementById('timer').textContent = time;
```
　
関数名は（なんでも良いのだが）、recalcという名で作成。
関数の定義は、「function(　)」と書き、その後ろの中括弧「{ }」の中にまとめたい処理を
書くことで関数を用意することができ、「関数名(　)」とする事で関数を呼び出す。

```.js:JavaScript
function recalc() {
  const counter = countdown(goal);
  const time = `${counter[1]}時間${counter[2]}分${counter[3]}秒`;
  document.getElementById('timer').textContent = time;
}

recalc();
```
　
ここで、プログラムの処理の流れですが、

```.js:JavaScript
'use strict';

// ④
function countdown(set) {
  const now = new Date();

  const rest = set.getTime() - now.getTime();
  const sec = Math.floor(rest / 1000) % 60;
  const min = Math.floor(rest / 1000 / 60) % 60;
  const hours = Math.floor(rest / 1000 / 60 / 60) % 24;
  const days = Math.floor(rest / 1000 / 60 / 60 / 24);
  const count = [days, hours, min, sec];

  return count;
}

// ①
let goal = new Date();
goal.setHours(23);
goal.setMinutes(59);
goal.setSeconds(59);

// ③
function recalc() {
  const counter = countdown(goal);
  const time = `${counter[1]}時間${counter[2]}分${counter[3]}秒`;
  document.getElementById('timer').textContent = time;
}

// ②
recalc();
```
先ず、変数goalが設定された後に、関数recalcが実行される。
その後、関数recalcは、関数countdownを呼び出し残り時間を計算するという流れ。

そして、関数recalcの中に、関数recalcを1秒ごとに繰り返す為の関数を作成する。
<br>

繰り返し処理の関数を作成
-
関数recalcの中に関数recalcを1秒ごとに繰り返す為の関数を呼び出す記載をし、
また、1秒ごとに繰り返す為の関数を作成。

これ実装する為にsetTimeoutメソッドを使用する。

書き方：`setTimeout(処理内容,実行タイミング)`
setTimeoutメソッドは、第二引数に与えられた実行タイミング(ミリ秒)で、第一引数に定義された
処理内容を1度実行する。
つまりは、ある処理を一定時間後に実行するように命令することができる、すなわち繰り返して実行してくれるメソッド。

繰り返して実行してくれる関数の名をrepeatという名で作成。
そして、setTimeoutメソッドの第一引数には、再計算する関数recalcを、
第二引数には、1秒ごとに繰り返すので、1秒はミリ秒単位で１０００なので、１０００を指定する。
ちなみに、引数に関数を指定する際には、関数の後ろの（　）は付けない。

```.js:JavaScript
function recalc() {
  const counter = countdown(goal);
  const time = `${counter[1]}時間${counter[2]}分${counter[3]}秒`;
  document.getElementById('timer').textContent = time;
  // 関数repeatの呼び出す
  repeat(); 
}
// 1秒ごとに繰り返す為の関数repeatを定義
function repeat() {
  setTimeout(recalc, 1000);
}

recalc();
```
<br>

これで、残り時間が刻一刻と変化するカウントタイマーの完成。
下記が完成図

```.js:JavaScript
'use strict';

function countdown(set) {
  const now = new Date();

  const rest = set.getTime() - now.getTime();
  const sec = Math.floor(rest / 1000) % 60;
  const min = Math.floor(rest / 1000 / 60) % 60;
  const hours = Math.floor(rest / 1000 / 60 / 60) % 24;
  const days = Math.floor(rest / 1000 / 60 / 60 / 24);
  const count = [days, hours, min, sec];

  return count;
}

let goal = new Date();
goal.setHours(23);
goal.setMinutes(59);
goal.setSeconds(59);

function recalc() {
  const counter = countdown(goal);
  const time = `${counter[1]}時間${counter[2]}分${counter[3]}秒`;
  document.getElementById('timer').textContent = time;
  repeat();
}

function repeat() {
  setTimeout(recalc, 1000);
}

recalc();
```
<br>


補足
-
さらにちょっとだけ手を加えて、
下記のようなもの作成（ちょっと悪ふざけが過ぎる気がするが。。。）
![image](https://i.gyazo.com/0e10a2c78889a619ba92f2a1704b4c58.gif)

これを実装するにあたって、
前回のコードと異なる部分は、

-Dateオブジェクトのよる日時設定方法
-padStartメソッドを使用
-Stringオブジェクトを使用
<br>

- Dateオブジェクトのよる日時設定方法

今までは、setHoursメソッド等を使用して日時の設定をおこなってきたが、
今回は、<b>日時を設定した状態でDateオブジェクトを初期化</b>する。

new Date( )の（ ）内にパラメータを含めておくと、予め日時を設定した状態で初期化出来る。
ただし、パラメータのうち、「年」、「月」は必須なので、ここの２つの設定しない場合はこのやり方は出来ない。
また、注意する点として、月の設定は、`「実際の月−１」`とする必要があるので、
今回で有れば7月で設定する場合は６を指定しなければならない点に注意。

書き方は、

```.text
new Date(年、　月、　日、　時、　分、　秒、　ミリ秒 )
```
実際に書くコードはこちら

```.js:JavaScript
const goal = new Date(2999, 6, 31);
```
<br>

今度は数字の桁数を揃える為に下記の事をする。
一番の上の完成図を見て貰えれば分かるが、秒数が一桁の時と二桁の時では、桁数が異なる為
ずれてしまい、ちょっとカッコが悪いので、それを修正する。

- padStartメソッド


padStartメソッドとは、指定した長さに合わすため、前方に文字列を加えるメソッド。
文字列を加えるので、第二引数にはクォテーションが付いている。
言葉だけだと理解しにくいので、例を交えて説明。

先ずは、書き方

```
文字列.padStart(揃える文字数,　埋め合わせ用の文字)
```

次に、padStartメソッドで、頭にゼロをつけるサンプル

```.js:JavaScript
const str = "90"
  console.log(str.padStart(3, "0")); 
  // 出力結果　→　090
  console.log(st1.padStart(5, "0"));
  // 出力結果　→　00090
  console.log(st1.padStart(2, "0"));
  // 出力結果　→　90
```
<br>

- Stringオブジェクト

Stringオブジェクトは、文字列を扱うオブジェクト。
なので、String（ ）は、（ ）の内のパラメータとして渡されたデータを文字列に変化する。
<br>

今回、padStartメソッドを使用して揃えたい文字列の対象は、counter[2]の分とcounter[3]の秒
という数値のデータです。数値のデータのままだとpadStartメソッドが使用出来ない為、Stringオブジェクトを
使用して文字列に変換する。

書き方はこんな感じになる

```.js:JavaScript
String(counter[2]).padStart(2, '0');
String(counter[3]).padStart(2, '0');
```
<br>
これで異なる実装は完了、
後は完成コードを下記に記載

```.js:JavaScript
'use strict';

function countdown(set) {
  const now = new Date();

  const rest = set.getTime() - now.getTime();
  const sec = Math.floor(rest / 1000) % 60;
  const min = Math.floor(rest / 1000 / 60) % 60;
  const hours = Math.floor(rest / 1000 / 60 / 60) % 24;
  const days = Math.floor(rest / 1000 / 60 / 60 / 24);
  const count = [days, hours, min, sec];

  return count;
}

const goal = new Date(2999, 6, 31);

function recalc() {
  const counter = countdown(goal);
  document.getElementById('day').textContent = counter[0];
  document.getElementById('hour').textContent = counter[1];
  document.getElementById('min').textContent = String(counter[2]).padStart(2, '0');
  document.getElementById('sec').textContent = String(counter[3]).padStart(2, '0');
  repeat();
}

function repeat() {
  setTimeout(recalc, 1000);
}

recalc();
```

```.html:HTML
<h2>大予言です<br>
2999年7月世界が滅亡します</h2>
<p>あと<span id="day"></span>日<span id="hour"></span>時間<span id="min"></span>分<span id="sec"></span>秒</p>

```

<br>
過去投稿記事
-
[【JavaScript ~変数・定数、if文・switch文~】勉強メモ](https://qiita.com/k-yasuhiro/items/1fb63f0881faf67bcb29)
[【JavaScript ~for文、配列、オブジェクトについて~】勉強メモ②](https://qiita.com/k-yasuhiro/items/6625942cc901feb6bfdf)
[【JavaScript ~関数について~】勉強メモ③](https://qiita.com/k-yasuhiro/items/52e3ebb79bb0248a7c5e)
[【JavaScript ~クラスやインスタンス、メソッドについて~】勉強メモ④](https://qiita.com/k-yasuhiro/items/52e3ebb79bb0248a7c5e)
[【JavaScript ~ファイルの分割について~】勉強メモ⑤](https://qiita.com/k-yasuhiro/items/209eda27bbc61ae961a1)
[【JavaScript 読み込み】勉強メモ⑥](https://qiita.com/k-yasuhiro/items/fe3fc2bd7b14fe4f3968)
[【JavaScript ~配列のメソッド~】勉強メモ⑦](https://qiita.com/k-yasuhiro/items/279b7bb59f112f917c51)
[【JavaScript ~コールバック関数~】勉強メモ⑧](https://qiita.com/k-yasuhiro/private/ded7e2cad732774d059e)
[【JavaScript ~HTMLを置き換え、ダイアログボックス~】勉強メモ⑨](https://qiita.com/k-yasuhiro/items/7a72bf38d78b141d6fac)
[【JavaScript ~イベント~】勉強メモ⑩](https://qiita.com/k-yasuhiro/items/b0d4037d0edaae38a495)
[【JavaScript ~イベント(入力内容を取得)とDateオブジェクト~】勉強メモ11](https://qiita.com/k-yasuhiro/items/fa586154cf7064eb7058)
[【JavaScript ~Mathオブジェクト~】勉強メモ12](https://qiita.com/k-yasuhiro/items/b931a15fb71322ee3cca)
[【JavaScript ~カウントダウンタイマーの作成~】勉強メモ13](https://qiita.com/k-yasuhiro/items/7e7afa7f04a2d860be5a)