ストップウォッチクラス

by mahny

HTML

<div>ストップウォッチ1</div>
<div id="sw1">00:00:00.000</div>
<button onmousedown="start1()">START/STOP</button>
<button onmousedown="reset1()">RESET</button>

<hr>

<div>ストップウォッチ2</div>
<div id="sw2">00:00:00.000</div>
<button onmousedown="start2()">START/STOP</button>
<button onmousedown="reset2()">RESET</button>

JavaScript

/**
 * ストップウォッチクラス
 * @auther mahny
 * @copyright mahny
 * @license MIT License
 */
class StopWatch {
  /**
   * 指定したIDを持つタグに対してストップウォッチ処理を行う
   *
   * @params {string} displayId
   *   時間表示を行うタグのID
   * @params {number} interval
   *   タイマー表示の更新間隔(ms)
   * @throws 指定したIDを持つタグが見つからない時
   * @throws 指定した更新間隔が正の数値以外の時
   */
  constructor(displayId, interval = 100) {
    this._displayElement = document.getElementById(displayId);
    if ((typeof(interval) !== 'number') || interval < 1) {
    	throw "指定した更新間隔は正の数値ではない。 / interval=[" + interval + "]";
    }
    this._interval = Math.floor(interval);
    this._startTime = 0;
    this._totalTime = 0;
  }

  /**
   * 計測時間を取得する
   * @returns {number} 計測時間(ms)
   */
	get totalTime() {
    let result = 0;
    switch (this.getStatus()) {
      case 'start':
        result = this._totalTime + (new Date().getTime() - this._startTime);
        break;
      case 'stop':
        result = this._totalTime;
        break;
      default:
        // nop
    }
    return result;
  }

  /**
   * 計測時間の文字列表現を返す
   * @returns {string} 計測時間の文字列表現
   */
  toString() {
    let restTotalTime = this.totalTime;
    if (restTotalTime < 1) {
      return '00:00:00.000';
    }
    let hour = Math.floor(restTotalTime / 3600000);
    let min = Math.floor(restTotalTime / 60000) % 3600;
    let sec = Math.floor(restTotalTime / 1000) % 60;
    let msec = restTotalTime % 1000;
    return ('0' + hour).slice(-2) +
      ':' + ('0' + min).slice(-2) +
      ':' + ('0' + sec).slice(-2) +
      '.' + ('00' + msec).slice(-3);
  }

  /**
   * ストップウォッチの状態を取得する
   *
   * @returns {string} ストップウォッチの状態
   */
  getStatus() {
    if (0 < this._startTime) {
      return 'start';
    } else if (0 < this._totalTime) {
      return 'stop';
    } else {
      return 'init';
    }
  }

  /**
   * 時間表示タグの表示時間を現在値に更新する
   */
  _refresh() {
  	if (!this._displayElement) {
      return;
    }
    this._displayElement.innerHTML = this.toString();
  }

  /**
   * 計測を開始または再開する
  ...