【javascriptでカウントダウンタイマーを作る】part.1 忘備録

# 完成形のイメージ
日本人の平均男性が80歳ぐらいまで生きると想定し、
自分の年齢を入力して余生を日数ではなく時間単位でカウントダウン表示する


# 実装したい機能を言葉にしよう

       0             1             2            3           4
       |=============|=============|============|===========|
     スタート　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　現時点　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　終了

       (---------------------カウントされる時間-------------------)

       (---現時点まで経過した時間------)(---タイマーに表示させる時間---)


今回考えなければならないことは **"タイマーにどうやって時間を表示させるか"**なので


上記の図を見てもらうと以下のように計算することで欲しい値を出力できることがわかった。


"カウントされる時間" - "現時点までの時間" = "タイマーに表示したい残り時間"

# 普通のカウントダウンタイマーに必要な機能
1 : カウントが0になったらタイマーが止まるようにする
2 : カウント時間を設定できるようにする
3 : リセットボタンをアクティブにする
4 : 一時停止、再開ができるようにする
5 : カウントダウン中に操作ができないようにする
# スタートしたらカウントダウンが始まるようにする。
自分用補足) 

スタートボタンを押してから何分経過したか = 現在時刻 - スタートボタンを押した時間
残り時間 = カウントされる時間 - (現在時刻 - スタートボタンを押した時間)

```html:life_timer.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charaset="utf-8">
<title>LIFE TIMER</title>
</head>
<body>
    <div id="timer">00:00:000</div>
    <div id="controls">
        <button id="min">Min</button>
        <button id="sec">Sec</button>
        <button id="reset">Reset</button>
        <button id="start">start</button>
    </div>
    <script src="life_timer.js"></script>
</body>

</html>
```
```javascript:life_timer.js
//即時関数で囲う
(function(){

    //厳密なエラーチェックのための記述
    'use strict'; 

    var timer = document.getElementById('timer');
    var min = document.getElementById('min');
    var sec = document.getElementById('sec');
    var reset = document.getElementById('reset');
    var start = document.getElementById('start');

    //スタートタイムを押した時の時間を入れる変数
    var startTime;

    //残り時間を計算するための変数
    var timeLeft;

    //とりあえず4秒で設定しておく。 現在時刻と表示形式を合わせるために * 1000
    var timeToCountDown = 4 * 1000;


    //残り時間を表示するためにミリ秒を渡すと分とか秒に直してくれる関数を作る
    function updateTimer(t){

    //引数として渡されたtでデータオブジェクトを作りたいので変数dという変数名で作ってみる
    var d = new Date(t);

    var m = d.getMinutes();
    var s = d.getSeconds();
    var ms = d.getMilliseconds();
    m = ('0' + m).slice(-2);
    s = ('0' + s).slice(-2);
    ms = ('00' + ms).slice(-3);
    timer.textContent =  m + ':' + s + ':' + ms;

    }


    function countDown(){

        //setTimeoutを使って次の処理を10ミリ秒後に実行するようにする
        setTimeout(function(){

        //残り時間 = カウントされる時間 - 現在時刻
        timeLeft = timeToCountDown - (Date.now() - startTime);

        //countDownを再帰的に呼び出すためのに記述

        updateTimer(timeLeft)
        countDown();

       //1秒以下の時間も表示されるようにする
        },10);
    }

    //startを押した際に発火するイベント
    start.addEventListener('click',function(){
        startTime = Date.now();

        //カウントダウンの機能は再帰的に実行したいのでcountDown関数を入れとく
        countDown();
    });
})();
```

# その他機能も実装
```javascript:life_timer.js
//即時関数で囲う
(function(){

    //厳密なエラーチェックのための記述
    'use strict'; 

    var timer = document.getElementById('timer');
    var min = document.getElementById('min');
    var sec = document.getElementById('sec');
    var reset = document.getElementById('reset');
    var start = document.getElementById('start');

    //スタートタイムを押した時の時間を入れる変数
    var startTime;

    //残り時間を計算するための変数
    var timeLeft;

    //とりあえず4秒で設定しておく。 現在時刻と表示形式を合わせるために * 1000
    var timeToCountDown = 0;

    //clearTimeoutメソッドを使いたいので、その時用に変数定義
    var timerId;

    //変数を用意し、カウントダウンの状態を管理できるようにする * Startの兼用
    var isRunning = false;

    //残り時間を表示するためにミリ秒を渡すと分とか秒に直してくれる関数を作る
    function updateTimer(t){

    //引数として渡されたtでデータオブジェクトを作りたいので変数dという変数名で作ってみる
    var d = new Date(t);

    var m = d.getMinutes();
    var s = d.getSeconds();
    var ms = d.getMilliseconds();
    m = ('0' + m).slice(-2);
    s = ('0' + s).slice(-2);
    ms = ('00' + ms).slice(-3);
    timer.textContent =  m + ':' + s + ':' + ms;

    }


    function countDown(){

        //setTimeoutを使って次の処理を10ミリ秒後に実行するようにする
        timerId = setTimeout(function(){

        //残り時間 = カウントされる時間 - 現在時刻
        timeLeft = timeToCountDown - (Date.now() - startTime);


        //残り時間が0になった時の処理をif文で記述する。
        if(timeLeft < 0){
            isRunning = false;
            start.textContent = 'Start';
            clearTimeout(timerId);
            timeLeft = 0;

            //カウントをリスタートした際にデフォ値の4秒にならないようにする
            timeToCountDown = 0;

            updateTimer(timeLeft);
            return;
        }

        //countDownを再帰的に呼び出すためのに記述
        updateTimer(timeLeft)
        countDown();

       //1秒以下の時間も表示されるようにする
        },10);
    }

    //startを押した際に発火するイベント
    start.addEventListener('click',function(){

        if(isRunning === false){
            isRunning = true;

            start.textContent = 'Stop';

            startTime = Date.now();

            //カウントダウンの機能は再帰的に実行したいのでcountDown関数を入れとく
            countDown();
        }else{
            isRunning = false;

            //表記をStartに戻す
            start.textContent = 'Start';

            //この時点のtimeLeftで更新してあげる
            timeToCountDown = timeLeft;

            //カウントを止めたいのでclearTimeoutする
            clearTimeout(timerId);
        }
    });

    //Minを押した時の処理を記述
    min.addEventListener('click',function(){

        //カウントダウン中に設定時間を変更できないようにする
        if(isRunning === true){
            return;
        }

        //分 = 60秒なので
        timeToCountDown += 60 * 1000;

        //60分、60秒を超えたら0になるようにする
        if(timeToCountDown >= 60 * 60 * 1000){
            timeToCountDown = 0;
        }

        //timeToCountDownをtimerに反映させたいのでupDatetimerを使う
        updateTimer(timeToCountDown);
    });


    //Secを押した時の処理
    sec.addEventListener('click',function(){

        //カウントダウン中に設定時間を変更できないようにする
        if(isRunning === true){
            return;
        }

        //60秒なので
        timeToCountDown += 1000;

        if(timeToCountDown >= 60 * 60 * 1000){
            timeToCountDown = 0;
        }

        //timeToCountDownをtimerに反映させたいのでupDatetimerを使う
        updateTimer(timeToCountDown);
    });


    //Resetを押した時の処理
    reset.addEventListener('click',function(){

        //カウントダウン中に設定時間を変更できないようにする
        if(isRunning === true){
            return;
        }

        //60秒なので
        timeToCountDown = 0;

        //timeToCountDownをtimerに反映させたいのでupDatetimerを使う
        updateTimer(timeToCountDown);
    });
})();

```

# 課題
次回は年齢を入力したら80歳まで生きるとして乗り時間を表示させる