JavaScriptでストップウォッチを作ってみた


##手順

タイマーを停止した時間から再開させる機能の実装。
clickイベントの設定
Date.now()

ボタンを押しても1回だけでは止まらないという不具合を直す
ボタンの状態をbutton要素のdisabled属性で無効化

CSSでストップウォッチ全体の見た目を整える。
bodyのスタイリング
.containerのスタイリング

タイマーのスタイルを整える。
スタイルの設定をするために、buttonタグをdivタグに置き換える。
timerのスタイリング
button要素とdiv要素の違い

divタグを使ったボタンの有効・無効の切り替えを実装。
classList.add()
classList.remove()
classList.contains()


###メモ
・textContent プロパティは、 ノードおよびその子孫のテキスト情報を取得・設定するために使います

・clearTimeout() メソッドは、以前の setTimeout() の呼び出して確立されたタイムアウトを解除します。

・padStart()メソッドは、結果の文字列が所定の長さになるように、現在の文字列を別の文字列（必要に応じて繰り返しpadStart()ます。 パディングは、現在の文字列の最初（左）から適用されます。

・elapsedTimeの意味は「経過時間」

・setTimeout() メソッド は、指定された遅延の後に関数またはコードの断片を実行するタイマーを設定する。


```index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>ストップウォッチ</title>
    <link rel="stylesheet" href="css/style2.css">
</head>
<body>  
  <div class="container">
   <div id="timer">00:00.000</div>
   <div class="controls">
        
        <div class="btn" id="start">Start</div>
        <div class="btn" id="stop">Stop</div>
        <div class="btn" id="reset">Reset</div>
    </div>  
  </div>
   <script src="js/main2.js"></script>
</body>
</html>

```

```css/styles.css
body {
  font-family: 'Courier New', monospace;
  font-size: 14px;
  background: #eee
}

.container {
  margin: 20px auto;
  width: 270px;
  background: #fff;
  padding: 15px;
  text-align: center;
}

#timer {
  background: #ddd;
  height: 120px;
  line-height: 120px;
  font-size: 40px;
  margin-bottom: 15px;
}

.btn {
  width: 80px;
  height: 45px;
  line-height: 45px;
  background: #ddd;
  font-weight: bold ;
  cursor: pointer;
  user-select: none;
}

.controls {
  display: flex;
  justify-content: space-between;
}

.inactive {
  opacity: 0.6;
}
```

```js/main.js
'use strict';

{
  const timer = document.getElementById('timer');
  const start = document.getElementById('start');
  const stop = document.getElementById('stop');
  const reset = document.getElementById('reset');

  let startTime;
  let timeoutId;
  let elapsedTime = 0;

  function countUp() {
    const d = new Date(Date.now() - startTime + elapsedTime);
    const m = String(d.getMinutes()).padStart(2, '0');
    const s = String(d.getSeconds()).padStart(2, '0');
    const ms = String(d.getMilliseconds()).padStart(3, '0');
    timer.textContent = `${m}:${s}.${ms}`;

    timeoutId = setTimeout(() => {
      countUp();
    }, 10);
  }

  function setButtonStateInitial() {
    start.classList.remove('inactive');
    stop.classList.add('inactive');
    reset.classList.add('inactive');
  }

  function setButtonStateRunning() {    start.classList.add('inactive');
    stop.classList.remove('inactive');
    reset.classList.add('inactive');
  }

  function setButtonStateStopped() {
    start.classList.remove('inactive');
    stop.classList.add('inactive');
    reset.classList.remove('inactive');
  }

  setButtonStateInitial();


  start.addEventListener('click', () => {
    if (start.classList.contains('inactive') === true) {
      return;
    }
    setButtonStateRunning();
    startTime = Date.now();
    countUp();
  });

  stop.addEventListener('click', () => {
    if(stop.classList.contains('inactive') === true) {
      return;
    }
    setButtonStateStopped();
    clearTimeout(timeoutId);
    elapsedTime += Date.now() - startTime;
  });

  reset.addEventListener('click', () => {
    if(reset.classList.contains('inactive') === true){
      return;
  }
    setButtonStateInitial();
    timer.textContent = '00:00.000';
    elapsedTime = 0;
  });
}
```

【プログラマー未経験者の方へ】
ドットインストールが難しくて萎えている方や、模写コーディングが出来なくて悩んでいる方はUdemyがめっちゃおすすめです。
僕はプログラマー未経験者ですが、以下の記事の講座で模写コーディング、さらには自分でコーディングできるまでになりました。
https://greenberet.net/mosya-coding-udemy/
僕はコーディングできるまでかなり苦しみ、何度も挫折しかけましたが、Udemyに助けられました。
参考にしていただければ幸いです。