@ayasaka

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

javascriptのストップウォッチをつくるさいの経過時間の仕方がわからない。

わからない処理

javascriptでストップウォッチをつくっているが、経過時間がもどってしまう。

該当するソースコード

言語名 javascript
ソースコードを入力

elapsedTime = Date.now() - startTime;
(経過時間) (スタートボタンを押した時間)

自分で試したこと

ここに問題・エラーに対して試したことを記載してください。
二回目以降のストップからのスタートでなぜか秒数がもどってしまいます。
解決方法はわかるのですが、なぜもどってしまうのかがわかりません。
よろしければ、教えてください。よろしくお願いします。

0 likes

3Answer

Comments

  1. @ayasaka

    Questioner

    <!doctype html>
    <html lang="ja">
    <head>
    <meta charset="UTF-8">
    <meta name="viewport"
    content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    </head>
    <body>
    <p class="timer">00:00:00</p>
    <button class="start">開始</button>
    <button class="stop">停止</button>
    <button class="reset">リセット</button>
    <script>
    let startTime = 0;
    let elapsedTime = 0;
    let timeoutId ;

    const timer = document.querySelector(".timer");
    const start = document.querySelector(".start");
    const stop = document.querySelector(".stop");
    const reset = document.querySelector(".reset");

    const countUp = () => {
    let d = new Date(Date.now() - startTime + elapsedTime).getTime();
    let t = (Math.floor(d / (1000 * 60 * 60))).toString().padStart(2, '0');
    d = new Date(Date.now() - startTime);
    let m = d.getMinutes().toString().padStart(2, '0');
    let s = d.getSeconds().toString().padStart(2, '0');
    timer.textContent = `${t}:${m}:${s}`;
    timeoutId = setTimeout(countUp, 1000);
    }

    start.addEventListener('click', () => {
    startTime = Date.now();
    countUp();
    });

    stop.addEventListener('click', () => {
    clearTimeout(timeoutId);
    elapsedTime += Date.now() - startTime;
    });

    reset.addEventListener('click', () => {
    clearTimeout(timeoutId);
    timer.textContent = '00:00:00';
    });
    </script>
    </body>
    </html>

今回のように繰り返しcountUpを呼ぶのなら、setTimeoutよりsetIntervalの方が良いと思います。
そうするとclearTimeoutではなくclearIntervalを呼ぶことになる。

elapsedTime = Date.now() - startTime;

なので、

let elapsedTime = 0;
...
elapsedTime += Date.now() - startTime;

は必要ないような気がします。そうなると

let d = new Date(Date.now() - startTime + elapsedTime).getTime();

let d = new Date(Date.now() - startTime).getTime();

0Like

Comments

  1. @ayasaka

    Questioner

    ありがとうございます。

経過時間がもどってしまう

停止したあと再び開始した場合に、止めた時間からの続きではなく00:00:00からの再計測になってしまう、ということですよね。

開始を押した際にはstartTimeDate.now()を足し、停止時にはstartTimeからDate.now()を引くようにすると、elapsedTimeを別に持つ必要が無くなって処理が簡略化できるかな、と思います。

<p class='timer'></p>
<button class='start'>開始</button>
<button class='stop'>停止</button>
<button class='reset'>リセット</button>

<script>
'use strict';
{
  const el = {};
  let startTime = 0;

  window.addEventListener('DOMContentLoaded', () => {
    el.timer = document.querySelector('.timer');
    el.start = document.querySelector('.start');
    el.stop  = document.querySelector('.stop');
    el.reset = document.querySelector('.reset');

    el.timer.textContent = getFormat(0);
    setButtonStatus();

    window.addEventListener('click', e => {
      const cl = e.target.classList;
      const now = Date.now();

      if(cl.contains('start')) {
        startTime += now;
        printTime();
        setButtonStatus();
      }
      else if(cl.contains('stop')) {
        startTime -= now;
        setButtonStatus();
      }
      else if(cl.contains('reset')) {
        startTime = 0;
        el.timer.textContent = getFormat(0);
      }
    });
  });

  const printTime = () => {
    if(startTime > 0) {
      el.timer.textContent = getFormat(Date.now() - startTime);
      requestAnimationFrame(printTime);
    }
  };

  const getFormat = t => new Date(t).toJSON().slice(11, 22);

  const setButtonStatus = () => {
    const f = startTime > 0;
    el.start.disabled = el.reset.disabled = f;
    el.stop.disabled = !f;
  };
}
</script>
0Like

Comments

  1. @ayasaka

    Questioner

    ありがとうございます。参考にさせていただきます。

Your answer might help someone💌