자바스크립트 반응속도 테스트 만들기

버건디·2022년 9월 15일
0
post-thumbnail

🔍 순서도 만들기


🔍 HTML, CSS 코드

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>반응속도</title>
<style>
  #screen {
    width: 300px;
    height: 200px;
    text-align: center;
    user-select: none;
  }
  #screen.waiting {
    background-color: aqua;
  }
  #screen.ready {
    background-color: red;
    color: white;
  }
  #screen.now {
    background-color: greenyellow;
  }
</style>
</head>

<body>
<div id="screen" class="waiting">클릭해서 시작하세요</div>
<div id="result"></div>

</body>
</html>

🔍 클릭할 때 화면 전환하기

CSS 에서 클래스 이름이 waiting 일때 파란색, ready 일때 빨간색, now 일때 초록색으로 변한다.

변수.classList.contains('클래스명');

을 사용하면 그 변수안에 '클래스명'이 존재하는지 판단하고 true/false 를 리턴한다.

document.addEventListener("DOMContentLoaded", () => {
  const screen = document.querySelector("#screen");
  const result = document.querySelector("#result");
  
  screen.addEventListener("click", () => {
    if (screen.classList.contains("waiting")) {
      screen.classList.replace("waiting", "ready");
      screen.textContent = "초록색이 되면 클릭하세요";

      setTimeout(() => {
        screen.classList.replace("ready", "now");
        screen.textContent = "클릭 하세요!";
      }, Math.floor(Math.random() * 1000) + 2000);
    } else if (screen.classList.contains("ready")) {
    } else if (screen.classList.contains("now")) {
    }
  });
});

처음 화면에는 파란색 화면을 띄웠다가 screen 을 클릭하는 순간 class명이 ready로 바뀌면서 빨간색으로 변화한다.

그리고 setTimeout 으로 인해 2~3초 사이에 랜덤으로 클래스명이 now로 바뀌면서 배경색이 초록색으로 변화한다.


🔍 반응 속도 측정하기

시간을 측정하기 위해서는 new Date() 를 사용해야한다.

저렇게 Date 객체를 만들어주어서 date 를 출력하면 현재 시각이 나오는것을 확인할 수 있다.

document.addEventListener("DOMContentLoaded", () => {
  const screen = document.querySelector("#screen");
  const result = document.querySelector("#result");

  let startTime; // 시작시간
  let endTime; // 끝나는 시간
  let responseTime; // 측정시간

  screen.addEventListener("click", () => {
    if (screen.classList.contains("waiting")) {
      screen.classList.replace("waiting", "ready");
      screen.textContent = "초록색이 되면 클릭하세요";

      setTimeout(() => {
        startTime = new Date();
        screen.classList.replace("ready", "now");
        screen.textContent = "클릭 하세요!";
      }, Math.floor(Math.random() * 1000) + 2000);
    } else if (screen.classList.contains("ready")) {
    } else if (screen.classList.contains("now")) {
      endTime = new Date();
      responseTime = endTime - startTime; // 측정시간
      result.textContent = responseTime + "ms";
      screen.classList.replace("now", "waiting");
      screen.textContent = "클릭해서 시작하세요";
    }
  });
});

이런식으로 시작 시간, 끝나는 시간, 측정 시간 변수를 하나씩 만들어주어서 Date 객체를 이용하여 시간을 측정했다.

🔍 평균 반응 속도 구하기

평균을 구하려면 그 값들의 합을 먼저 구하는게 우선이다.

records 라는 빈 배열을 만들어주고 reduce 메서드를 이용하여 평균을 구해주었다.

<script>
  document.addEventListener("DOMContentLoaded", () => {
  const screen = document.querySelector("#screen");
  const result = document.querySelector("#result");

  let startTime; // 시작시간
  let endTime; // 끝나는 시간
  let responseTime; // 측정시간
  let records = []; // 평균 반응 속도 구할 빈 배열

  screen.addEventListener("click", () => {
    if (screen.classList.contains("waiting")) {
      screen.classList.replace("waiting", "ready");
      screen.textContent = "초록색이 되면 클릭하세요";

      setTimeout(() => {
        startTime = new Date();
        screen.classList.replace("ready", "now");
        screen.textContent = "클릭 하세요!";
      }, Math.floor(Math.random() * 1000) + 2000);
    } else if (screen.classList.contains("ready")) {
    } else if (screen.classList.contains("now")) {
      endTime = new Date();
      responseTime = endTime - startTime; // 측정시간
      records.push(responseTime);
      let Avg = records.reduce((acc, cur) => {return acc+cur}, 0) / records.length; // 평균 반응 속도
      result.textContent = '현재 : ' + responseTime + " ms" + ' ' + '평균 속도 : ' + Avg;
    //   startTime = null;
    //   endTime = null; 여기서 null 이거 없어도 되지 않나?
      screen.classList.replace("now", "waiting");
      screen.textContent = "클릭해서 시작하세요";
    }
  });
});
</script>

🔍 성급한 클릭 막기

빨간 화면이 등장 했을때는 대기 화면인건데, 이때 클릭을 누르면 성급하다는 메세지가 뜨면서 다시 파란화면으로 전환되도록 해야한다.

else if (screen.classList.contains("ready")) {
      screen.textContent = '너무 성급합니다!';
      screen.classList.replace('ready', 'waiting')
    }

이렇게 작성을 하니 반복해서 계속 클릭을 할때, 대기중인 상태인데도 불구하고 계속 시간이 측정되에서 창에 띄어지는 문제가 발생했다.

저 setTimeout 함수가 계속 누적이 되어서 문제가 발생하는 것이었다.

그렇기 때문에 빨강 배경일때 클릭을 했을때 저 setTimeout 을 clearTimeout 을 동시에 해주어야지 오류가 발생하지 않았다.

else if (screen.classList.contains("ready")) {
      clearTimeout(timeoutId);
      screen.textContent = '너무 성급합니다!';
      screen.classList.replace('ready', 'waiting')
    }

정상적으로 잘 출력이 된다.


🔍 전체 코드

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>반응속도</title>
<style>
  #screen {
    width: 300px;
    height: 200px;
    text-align: center;
    user-select: none;
  }
  #screen.waiting {
    background-color: aqua;
  }
  #screen.ready {
    background-color: red;
    color: white;
  }
  #screen.now {
    background-color: greenyellow;
  }
</style>
</head>

<body>
<div id="screen" class="waiting">클릭해서 시작하세요</div>
<div id="result"></div>

</body>

<script>
  document.addEventListener("DOMContentLoaded", () => {
  const screen = document.querySelector("#screen");
  const result = document.querySelector("#result");

  let startTime; // 시작시간
  let endTime; // 끝나는 시간
  let responseTime; // 측정시간
  let records = []; // 평균 반응 속도 구할 빈 배열
  let timeoutId; // setTimeout 함수를 담을 변수

  screen.addEventListener("click", () => {
    if (screen.classList.contains("waiting")) {
      screen.classList.replace("waiting", "ready");
      screen.textContent = "초록색이 되면 클릭하세요";
      timeoutId = setTimeout(() => {
        startTime = new Date();
        screen.classList.replace("ready", "now");
        screen.textContent = "클릭 하세요!";
      }, Math.floor(Math.random() * 1000) + 2000);
    } else if (screen.classList.contains("ready")) {
      clearTimeout(timeoutId);
      screen.textContent = '너무 성급합니다!';
      screen.classList.replace('ready', 'waiting')
    } else if (screen.classList.contains("now")) {
      endTime = new Date();
      responseTime = endTime - startTime; // 측정시간
      records.push(responseTime);
      let Avg = records.reduce((acc, cur) => {return acc+cur}, 0) / records.length; // 평균 반응 속도
      result.textContent = '현재 : ' + responseTime + " ms" + ' ' + '평균 속도 : ' + Avg;
    //   startTime = null;
    //   endTime = null; 여기서 null 이거 없어도 되지 않나?
      screen.classList.replace("now", "waiting");
      screen.textContent = "클릭해서 시작하세요";
    }
  });
});
</script>
</html>
profile
https://brgndy.me/ 로 옮기는 중입니다 :)

3개의 댓글

comment-user-thumbnail
2023년 12월 22일

안녕하세요 올려주신 소스코드를 사용하고 싶은데 혹시 가능하실가요?

1개의 답글