...
728x90
반응형
여러개의 객관식문제 출력하기
HTML 문서작성
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>퀴즈 이펙트05</title>
<link rel="stylesheet" href="css/quiz.css">
<link rel="stylesheet" href="css/reset.css">
<link href="https://unpkg.com/pattern.css" rel="stylesheet">
</head>
<body>
<header id="header">
<h1><a href="../javascript14.html">Quiz</a> <em>객관식(여러문제) 확인하기 유형</em></h1>
<ul>
<li><a href="quizEffect01.html">1</a></li>
<li><a href="quizEffect02.html">2</a></li>
<li><a href="quizEffect03.html">3</a></li>
<li><a href="quizEffect04.html">4</a></li>
<li class="active"><a href="quizEffect05.html">5</a></li>
</ul>
</header>
<!-- //header -->
<main id="main">
<div class="quiz__wrap">
</div>
</main>
<!-- //main -->
<footer id="footer">
<a href="mailto:gnsrbdi@naver.com">gnsrdbi@naver.com</a>
</footer>
<!-- //footer -->
</body>
</html>
HTML 정리해보기
- 이번 객관식 퀴즈 유형은 문제의 갯수만큼 계속 출력시키도록 script를 작성하기 때문에 기존의 html문서에서는 헤더와 푸터, quiz__wrap부분만 남기고 전부 지웠습니다.
새로 추가된 CSS
.quiz__check {
position: fixed;
right: 40px;
bottom: 70px;
width: 100px;
height: 100px;
line-height: 95px;
border-radius: 45%;
text-align: center;
background-color: rgb(247, 157, 157);
font-family: HealthsetGothic;
font-weight: bold;
font-size: 20px;
color: #fff;
transition: all 0.2s;
z-index: 1000;
}
.quiz__check:hover {
cursor: pointer;
background-color: #f87070;
border: 1px solid #949494;
font-size: 22px;
}
.quiz__info {
width: 130px;
border-radius: 10px;
height: 50px;
position: fixed;
right: 25px;
bottom: 200px;
text-align: center;
line-height: 50px;
background-color: #c48484;
font-family: HealthsetGothic;
color: #fff;
}
.quiz__info::after {
content: '';
position: absolute;
left: 50%;
margin-left: -10px;
bottom: -10px;
border-top: 10px solid #c48484;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
}
CSS 정리해보기
- 모든 문제를 풀고 전체를 채점할 수 있는 버튼(quiz__check)을 하나 만들고, 점수를 알려주는 박스(quiz__info)를 만들기 위해 미리 속성을 만들어 놓았습니다.
- quiz__info에 가상요소를 만들어 border의 속성을 통해 삼각형을 만들어 주었습니다.
Javascript 작성하기
// 문제 정보
const quizInfo = [
{
infoType : "문제 유형",
infoTime : "문제 회차",
infoNumber : "문제 고유 번호",
infoQuestion : "문제 내용",
infoChoice : {
1: "문제보기",
2: "문제보기",
3: "문제보기",
4: "문제보기"
},
infoAnswer : "정답 번호",
infoDesc : "문제 해설"
},{
infoType : "문제 유형",
infoTime : "문제 회차",
infoNumber : "문제 고유 번호",
infoQuestion : "문제 내용",
infoChoice : {
1: "문제보기",
2: "문제보기",
3: "문제보기",
4: "문제보기"
},
infoAnswer : "정답 번호",
infoDesc : "문제 해설"
}
// 모든 문제 정보 적어주기
];
// 선택자
const quizWrap = document.querySelector(".quiz__wrap");
const quizQuestion = quizWrap.querySelector(".quiz__question");
let quizScore = 0;
// 문제 출력
const updateQuiz = () => {
const exam = [];
quizInfo.forEach((question, number)=>{
exam.push(`
<div class="quiz">
<div class="quiz__header">
<h2 class="quiz__title">${question.infoType} ${question.infoTime}</h2>
</div>
<div class="quiz__main">
<div class="quiz__question"><em>${number+1}.</em> ${question.infoQuestion}</div>
<div class="quiz__view">
<div class="dog__wrap">
<div class="true">정답 !</div>
<div class="false">오답 !</div>
<div class="card-container">
<div class="dog">
<div class="head">
<div class="ears"></div>
<div class="face"></div>
<div class="eyes">
<div class="teardrop"></div>
</div>
<div class="nose"></div>
<div class="mouth">
<div class="tongue"></div>
</div>
<div class="chin"></div>
</div>
<div class="body">
<div class="tail"></div>
<div class="legs"></div>
</div>
</div>
</div>
</div>
</div>
<div class="quiz__choice">
<label for="choice1${number}">
<input type="radio" id="choice1${number}" name="choice${number}" value="1">
<span>${question.infoChoice[1]}</span>
</label>
<label for="choice2${number}">
<input type="radio" id="choice2${number}" name="choice${number}" value="2">
<span>${question.infoChoice[2]}</span>
</label>
<label for="choice3${number}">
<input type="radio" id="choice3${number}" name="choice${number}" value="3">
<span>${question.infoChoice[3]}</span>
</label>
<label for="choice4${number}">
<input type="radio" id="choice4${number}" name="choice${number}" value="4">
<span>${question.infoChoice[4]}</span>
</label>
</div>
<div class="quiz__desc"><em>정답 : ${question.infoAnswer} 번</em><br>${question.infoDesc}</div>
</div>
</div>
`);
});
exam.push(`
<div class="quiz__info">점수</div>
<div class="quiz__check">정답 확인</div>
`)
quizWrap.innerHTML = exam.join("💢");
// 설명 숨기기
document.querySelectorAll(".quiz__desc").forEach(el => el.style.display = "none");
}
updateQuiz();
// 정답 확인
const answerQuiz = () => {
const quizChoices = document.querySelectorAll(".quiz__choice");
// 사용자의 답 == 문제 정답
quizInfo.forEach((question, number) => {
const userSelector = `input[name=choice${number}]:checked`;
const quizSelectorWrap = quizChoices[number];
const userAnswer = (quizSelectorWrap.querySelector(userSelector) || {}).value;
const dogWrap = quizWrap.querySelectorAll(".dog__wrap");
if(userAnswer == question.infoAnswer){
console.log("정답");
dogWrap[number].classList.add("like");
quizScore++;
} else {
console.log("오답");
dogWrap[number].classList.add("dislike");
};
});
// 정답 보이기
document.querySelectorAll(".quiz__desc").forEach(el => el.style.display = "block");
// 점수 보이기
document.querySelector(".quiz__info").innerHTML = Math.ceil((quizScore/quizInfo.length*100)) + "점";
alert(quizScore + "개 맞았습니다.");
// 정답 버튼 숨기기
document.querySelector(".quiz__check").style.display = "none";
}
// 정답 클릭
document.querySelector(".quiz__check").addEventListener("click", answerQuiz);
Javascript 정리해보기
- quizInfo 라는 변수를 만들어 출력하고자 하는 모든 문제의 정보를 배열 속 객체 형식으로 저장해 주었습니다.
- 문제를 출력할 때 사용할 quiz__wrap 부분도 quizWrap에 선택자로 저장하여주고 정답 개수를 세어 줄 quizScore 변수도 만들어 놓았습니다.
- updateQuiz 함수
- exam이라는 빈 배열을 하나 만들었습니다.
- quizInfo에 forEach문을 사용하여 요소의 개수만큼 exam에 기존에 사용하던 html구조의 quiz부분을 push() 해주었습니다.
- 기존에 각각의 선택자로 지정하여 텍스트를 넣어 주었던 곳에는 ${}을 사용해 직접 넣어주었습니다.
- 상당히 많은 보기가 존재하므로 quizInfo의 index 값(number)을 사용하여 radio 형식의 input태그의 name을 "choice${number}"로 저장했습니다.
- forEach문을 사용하여 모든 요소에 대해 실행 되었고 마지막으로 exam 배열에 점수를 확인하는 칸과 채점을 할 수 있는 정답확인 버튼을 다시 push() 해주었습니다.
- 이렇게 만들어진 exam 배열을 quizWrap에 innerHTML을 사용해 넣어줬습니다.
- (".quiz__desc") 의 모든 요소의 디스플레이 스타일을 none으로 설정해 주었습니다.
- 기본적으로 배열의 요소가 ","로 구분지어 나타나기 때문에 join(" ") //(빈문자열) 을 사용해 ","를 없애거나 다른 텍스트 혹은 이모지를 사용할 수 있습니다.
- answerQuiz 함수
- 4개의 보기가 들어있는 ".quiz__choice"를 quizChoices라는 변수로 선택자 지정을 하였습니다.
- 다시 quizInfo에 forEach문을 사용하고 요소(question)와 index (number)를 사용합니다.
- userSelector 라는 변수에 체크된 input박스를 저장합니다.
- quizChoices 배열 중 (여러개의 ".quiz__choice") [number] 번째를 선택자로 quizSelectorWrap에 저장합니다.
- quizSelectorWrap중 체크된 input박스 (userSelector) or { } (아무 것도 체크하지 않은 값)의 value 값을 받아와 userAnswer에 저장합니다.
- dogWrap을 ("dog__wrap")의 선택자로 저장합니다.
- userAnswer(체크된 보기의 value)와 question.infoAnswer(정해놓은 답)가 같다면,
- dogWrap의 [number] 번째의 classList에 "like"를 추가하고 quizScore++ 연산을 실행합니다.
- 아니라면 dogWrap의 [number] 번째의 classList에 "dislike"를 추가합니다.
- (forEach문 종료)
- (".quiz__desc)의 디스플레이 스타일을 모두 block으로 변경합니다.
- (".quiz__info")에 Math.ceil((quizScore/quizInfo.length)*100) 의 값을 넣어줍니다. (Math.ceil은 계산 값의 소수점을 올림하여 정수로 값을 받아옵니다.)
- quizScore의 값을 alert 해주며 맞은 개수를 알려줍니다.
- (".quiz__check")의 디스플레이 스타일을 none으로 바꾸어줍니다.
마지막으로 document.querySelector(".quiz__check").addEventListener("click", answerQuiz)로 quiz__check 버튼을 눌렀을 때 answerQuiz의 함수를 실행시키면 됩니다.
이상으로 다수의 문제를 출력하는 방법을 알아보았습니다 !
728x90
반응형