자바스크립트를 이용하여,
반응속도 테스트를 구현하는 예제입니다.
반응속도 테스트를 구현하는 예제입니다.
예제는 인프런의 제로초, "조현영"님의 강의를 들으면서 공부한 내용입니다.
순서도
특이사항
준비 화면 상태 일 때 랜덤 한 시간 후에 자동으로 테스트 화면으로 전환
setTimeout으로
Math.floor(Math.random()*1000): 0-1초 사이 랜덤 시간 이후
click() 자동 클릭 시킴
html 코드
<div id="screen" class="waiting">Click to start</div>
<div id="show"></div>
css 코드
#screen {
width: 400px;
height: 300px;
text-align: center;
user-select: none;
/*해당요소의 드레그, 더블클릭, 블럭지정을 막는다.*/
font-size: 20px;
font-weight: bold;
}
#screen.waiting {
background: skyblue;
}
#screen.ready {
background: pink;
}
#screen.go {
background: greenyellow;
}
순수 자바스크립트(디버깅 전)
const screen = document.querySelector('#screen');
screen.addEventListener('click', function() {
//classList.contains로 현재 class 파악 -> return true or false
//처음 시작 waiting 화면 -> ready 화면
if (screen.classList.contains('waiting')) {
screen.classList.remove('waiting');
screen.classList.add('ready');
screen.textContent = 'wait for green';
//ready 화면에 되는 순간 timer 동작
setTimeout(function() {
let start = new Date();
screen.click();
}, Math.floor(Math.random() * 1000) + 2000); //2-3초 사이 랜덤한 시간
//ready 화면 -> go 화면
} else if (screen.classList.contains('ready')) {
screen.classList.remove('ready');
screen.classList.add('go');
screen.textContent = 'Click';
//go 화면 -> waiting 화면
} else if (screen.classList.contains('go')) {
let end = new Date();
//아래 콘솔에서 에러발생: Uncaught ReferenceError: start is not defined
console.log((end - start) / 1000);
screen.classList.remove('go');
screen.classList.add('waiting');
screen.textContent = 'Click to start';
}
});
new Data()
· new Data() 하는 순간 그 시작이 저장(ms 밀리초 단위)됩니다.
· 이를 1000으로 나뉘면 초로 계산됩니다. (1000ms -> 1초)
비동기 함수 특징
· 비동기 함수는 이벤트(클릭)를 하는 순간 콜스택 들어갔다가 함수가 끝나면 바로 나갑니다.
· 함수 안에 {명령} 내용을 실행을 완료후 함수가 사라집니다.
코드 에러 발생
console.log((end - start) / 1000);
//결과 Uncaught ReferenceError: start is not defined
문제점: scope 문제
· start를 감싸고 있는 함수(click 이벤트 콜백 함수) scope안에 start 변수 선언이 없음
· 그 바깥 전역 범위에도 없음
· start 변수선언을 setTimeout 함수 안에 했기 때문에 밖에서 함수 접근 불가하여 undefined 에러 발생
· 비동기 함수의 특징 때문에 실행 완료 후 콜스택의 함수가 사라지면서 start, end 변수 선언한 것이 사라짐
문제 해결 방법:
변수선언을 전역 변수로(함수의 밖) 꺼냅니다.
순수 자바스크립트(디버깅 후, 추가 기능)
· scope 문제 디버깅
· ready화면에서 부정 클릭 시 코
· 3번 테스트 후 평균 반응속도 점수 출력
· 초기화
const screen = document.querySelector('#screen');
let start;
let end;
let count = 0;
let score = [];
let sum = 0;
let averageScore = 0;
let timer;
screen.addEventListener('click', function() {
if (screen.classList.contains('waiting')) {
screen.classList.remove('waiting');
screen.classList.add('ready');
screen.textContent = 'wait for green';
//ready 화면에 되는 순간 timer 동작
timer = setTimeout(function() { //timer 변수에 대입하여 clearTimeout에 사용
start = new Date();
screen.click();
}, Math.floor(Math.random() * 1000) + 2000);
} else if (screen.classList.contains('ready')) {
//ready 화면에서 부정 클릭시
if (!start) { //start가 없으면 부정 클릭
clearTimeout(timer);
screen.classList.remove('ready');
screen.classList.add('waiting');
screen.textContent = 'Clicked too soon';
} else {
screen.classList.remove('ready');
screen.classList.add('go');
screen.textContent = 'Click';
}
} else if (screen.classList.contains('go')) {
end = new Date();
result = (end - start) / 1000
console.log(result + '초');
count += 1;
score.push(result);
screen.classList.remove('go');
screen.classList.add('waiting');
screen.textContent = 'Click to start';
//초기화
start = null;
end = null;
}
if (count >= 3) {
for (let i = 0; i < score.length; i++) {
sum = sum + score[i]
}
averageScore = sum / score.length;
console.log(count, score, sum, averageScore);
document.querySelector('#show').textContent = `당신의 평균 속도는 ${averageScore.toFixed(2)} 입니다.`;
setTimeout(function() {
backtoBegin();
}, 2000);
}
//게임 초기화
function backtoBegin() {
count = 0;
document.querySelector('#show').textContent = '';
}
});
전체 코드
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>반응속도테스트</title>
<style>
#screen {
width: 400px;
height: 300px;
text-align: center;
user-select: none;
font-size: 20px;
font-weight: bold;
}
#screen.waiting {
background: skyblue;
}
#screen.ready {
background: pink;
}
#screen.go {
background: greenyellow;
}
</style>
</head>
<body>
<div id="screen" class="waiting">Click to start</div>
<div id="show"></div>
<script>
const screen = document.querySelector('#screen');
let start;
let end;
let count = 0;
let score = [];
let sum = 0;
let averageScore = 0;
let timer;
screen.addEventListener('click', function() {
if (screen.classList.contains('waiting')) {
screen.classList.remove('waiting');
screen.classList.add('ready');
screen.textContent = 'wait for green';
timer = setTimeout(function() {
start = new Date();
screen.click();
}, Math.floor(Math.random() * 1000) + 2000);
} else if (screen.classList.contains('ready')) {
if (!start) {
clearTimeout(timer);
screen.classList.remove('ready');
screen.classList.add('waiting');
screen.textContent = 'Clicked too soon';
} else {
screen.classList.remove('ready');
screen.classList.add('go');
screen.textContent = 'Click';
}
} else if (screen.classList.contains('go')) {
end = new Date();
result = (end - start) / 1000
console.log(result + '초');
count += 1;
score.push(result);
screen.classList.remove('go');
screen.classList.add('waiting');
screen.textContent = 'Click to start';
//초기화
start = null;
end = null;
}
if (count >= 3) {
for (let i = 0; i < score.length; i++) {
sum = sum + score[i]
}
averageScore = sum / score.length;
console.log(count, score, sum, averageScore);
document.querySelector('#show').textContent = `당신의 평균 속도는 ${averageScore.toFixed(2)} 입니다.`;
setTimeout(function() {
backtoBegin();
}, 2000);
}
//게임 초기화
function backtoBegin() {
count = 0;
document.querySelector('#show').textContent = '';
}
});
</script>
</body>
</html>
화면 결과(Result 클릭)
반응형
'개발 > Javascript' 카테고리의 다른 글
[js] 자바스크립트로 틱택토(심화버전) 구현하기 (0) | 2021.01.10 |
---|---|
[js]자바스크립트 스코프, 클로저(ft. 지역/글로벌/렉시컬 scope) (0) | 2021.01.08 |
[js] 자바스크립트로 지뢰찾기 게임 구현하기 (0) | 2021.01.02 |
[js] 자바스크립트로 가위바위보 게임 구현하기 (0) | 2020.12.27 |
[js] 자바스크립트로 로또추첨기 구현하기 (4) | 2020.12.25 |
댓글