【JavaScript】世界一シンプルなストップウォッチ

# 世界一シンプルなストップウォッチ
長押しして、離したらスタート

<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="js,result" data-user="masa_mf3rs" data-slug-hash="abvNGXO" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="ストップウォッチ">
  <span><a href="https://codepen.io/masa_mf3rs/pen/abvNGXO">
  ストップウォッチ</a></span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

## 特徴
- 画面全体がボタンになっているため、扱いやすい
- 押す状態によって色が変化するため、直感的に使える
- スマホとPCそれぞれのイベントに対応（Chromeは確認済）
- iPhoneやAndroidのデフォルトのストップウォッチの問題点を改善

## 使い方
1. 500ミリ秒長押しして、離すとスタート
2. クリック（スマホはホバーまたはクリック）するとストップ

```javascript:script.js
const swCheck = document.getElementById('sw-check');
const count = document.getElementById('count');
const btn = document.getElementById('btn');

let elapsedTime1 = 0; // 経過時間（単位:ミリ秒）
let elapsedTime2 = 0;
let startTime1; // スタート時の時刻
let startTime2;
let timerId1; // タイマーのID
let timerId2;

// 10ミリ秒ごと計算
function preCountUp() {
    timerId1 = setTimeout(() => {
        elapsedTime1 = Date.now() - startTime1;
        preCountUp();
    }, 10);
    if(elapsedTime1 > 500){
        clearTimeout(timerId1);
        //経過時間
        elapsedTime1 = 0;
        swCheck.checked = true;
        count.textContent = 'OK';
    }
}

// 10ミリ秒ごと計算&更新
function countUp() {
    timerId2 = setInterval(() => {
        elapsedTime2 = Date.now() - startTime2;
        let m = Math.floor(elapsedTime2 / (1000 * 60));
        let s = Math.floor((elapsedTime2 % (1000 * 60)) / 1000);
        let ms = elapsedTime2 % 1000;
        m = `0${m}`.slice(-2);
        s = `0${s}`.slice(-2);
        ms = `00${ms}`.slice(-3);
        count.textContent = `${m}:${s}.${ms}`;
    }, 10);
}

// 事前カウント開始
function preStart() {
    btn.classList.add('start');
    btn.classList.remove('stop');
    if(swCheck.checked === false) {
        startTime1 = Date.now();
        preCountUp(); //カウントを開始
    }
}
// 事前カウント終了
function preStop() {
    btn.classList.remove('start');
    btn.classList.add('stop');
    if(swCheck.checked === false) {
        clearTimeout(timerId1);
    }
}

function start() {
    if(swCheck.checked === true) {
        btn.classList.add('start');
        btn.classList.remove('stop');
        startTime2 = Date.now();
        clearTimeout(timerId1);
        countUp(); //カウントを開始
    }
}
function stop() {
    if(swCheck.checked === true) {
        swCheck.checked = false;
        btn.classList.remove('start');
        btn.classList.add('stop');
        clearTimeout(timerId2);
        // 最終的な記録
        let m = Math.floor(elapsedTime2 / (1000 * 60));
        let s = Math.floor((elapsedTime2 % (1000 * 60)) / 1000);
        let ms = elapsedTime2 % 1000;
        m = `0${m}`.slice(-2);
        s = `0${s}`.slice(-2);
        ms = `00${ms}`.slice(-3);
        count.textContent = `${m}:${s}.${ms}`;
    }
}

const ua = navigator.userAgent;
if (ua.indexOf('iPhone') > -1 
    || (ua.indexOf('Android') > -1 && ua.indexOf('Mobile') > -1) 
    ||  (ua.indexOf('iPad') > -1 || ua.indexOf('Android') > -1)) {
    // スマートフォン or タブレット
    //touchstartはSafariとIE以外対応
    btn.addEventListener("touchstart", ()=> {
        preStart();
        stop();
    });
    btn.addEventListener("touchend", ()=> {
        preStop();
        start();
    });
} else {
    // PC
    btn.addEventListener("pointerdown", ()=> {
        preStart();
        stop();
    });
    btn.addEventListener("pointerleave", ()=> {
        stop();
    });
    btn.addEventListener("pointerup", ()=> {
        preStop();
        start();
    });
}
```

## 仕組み
- 長押し状態で、500ms経過するとチェックボックスにフラグを立てる
- フラグが立っている場合のみ、クリックを離したらスタート可にする
- クリックされると、フラグを消す

## 最後に
これがJavaScriptを学習されている皆様にお役に立てれば幸いです。誤り等ございましたら、ご気軽にコメントをいただけたらと思います。