본문 바로가기
이펙트 만들기/Quiz 이펙트 만들기

퀴즈 이펙트 만들기 06

by 코딩달림 2022. 8. 25.
728x90

퀴즈 만들기

자바스크립트 함수를 활용하여 퀴즈 만들기입니다.


퀴즈 만들기 06

이번 퀴즈는 객관식 슬라이드 유형입니다.

이번 유형은 보기를 선택시 바로 정답 여부를 알려주고 다음 화면으로 넘어가도록 하는 슬라이드 유형입니다.

1. 문제 정보


const quizInfo = [
    {
        answerType: "웹디자인기능사 2009년 05회",
        answerNum: "1",
        answerAsk: "다음 중 커뮤니케이션 디자인의 설명으로 틀린 것은?" ,
        answerChoice: [
            "라틴어 'Communicare'를 어원으로 한다.",
            "두 개 이상의 개체가 기호를 매개로 무언가를 공유하는 것이다.",
            "운동과 시선을 중시하는 디자인이다.",
            "사람과 사람사이에 기호에 의해서 의미를 전달하는 과정이다.",
        ],
        answerResult: "운동과 시선을 중시하는 디자인이다.",
        answerEx : "3번. 커뮤니케이션은 대화나 상호작용을 의미합니다. 따라서 3번은 커뮤니케이션으로 보기 힘듭니다."
    },
    {
        answerType: "웹디자인기능사 2009년 05회",
        answerNum: "2",
        answerAsk: "망막에서 일어나는 변화에 관계없이 그 사물에 대해 지속적으로 고정적인 인식을 하고 있는 현상은?" ,
        answerChoice: [
            "운동시",
            "형태시",
            "항상성",
            "지각성",
        ],
        answerResult: "항상성",
        answerEx : "3번. 항상성이란 생체가 여러 가지 환경 변화에 대응하여 생명 현상이 제대로 일어날 수 있도록 일정한 상태를 유지하는 성질. 또는 그런 현상을 말합니다."
    }
]

이번 문제 정보는 보기가 객체가 아닌 배열로 되어 있으며 정답 역시 번호 대신 보기의 답안으로 되어 있습니다.
이것은 답안 매칭을 번호가 아닌 답안 그대로 매칭해야 한다는 얘기가 됩니다. 따라서 이번엔 보기의 밸류값(1~4)은 사용하지 않습니다.

2. 문제 출력

//선택자
const quizType = document.querySelector(".quiz__type");
const quizQuestion = document.querySelector(".quiz__question");     //문제 번호, 질문
const quizSelects = document.querySelector(".quiz__selects");     //객관식 보기
const quizResult = document.querySelector(".quiz__answer .result");    //객관식
const quizConfirm = document.querySelector(".quiz__answer .confirm");
const quizView = document.querySelector(".quiz__view");                 //강아지

let quizCount = 0;


//문제 출력
const updateQuiz = (index) => {
    const questionTag = `
        <span class="number">${quizInfo[index].answerNum}</span>
        <div class="ask">${quizInfo[index].answerAsk}</div>
    `;
    const choiceTag = `
        <label for="select1">
            <input type="radio" id="select1" class="select" name="select" value="1">  
            <span class="choice">${quizInfo[index].answerChoice[0]}</span>
        </label>
        <label for="select2">
            <input type="radio" id="select2" class="select" name="select" value="2">   
            <span class="choice">${quizInfo[index].answerChoice[1]}</span>
        </label>
        <label for="select3">
            <input type="radio" id="select3" class="select" name="select" value="3">   
            <span class="choice">${quizInfo[index].answerChoice[2]}</span>
        </label>
        <label for="select4">
            <input type="radio" id="select4" class="select" name="select" value="4">   
            <span class="choice">${quizInfo[index].answerChoice[3]}</span>
        </label>
    `;

    //문제 출력
    quizType.innerHTML = quizInfo[index].answerType;
    quizQuestion.innerHTML = questionTag;
    quizSelects.innerHTML = choiceTag;
    quizResult.innerHTML = quizInfo[index].answerEx;

    const quizChoice = quizSelects.querySelectorAll(".choice");

    for(let i=0; i<quizChoice.length; i++){
        quizChoice[i].setAttribute("onclick", "choiceSelected(this)")
    }

    //문제, 해설 숨기기
    quizResult.style.display = "none";
    quizConfirm.style.display = "none";

이번 문제 유형의 틀은 바뀌는 부분만 스크립트로 처리했습니다.
이번 유형에서 눈에 띄는건 "index" 부분으로 변수가 0으로 시작하는 값을 넣고 for문을 통해 각 문제의 모든 보기에 클릭시 함수가 실행되는 "onclick" 속성을 부여합니다.

그 후 문제가 바뀌는 부분을 똑같이 index를 넣고 출력하면 간단히 모든 문제가 출력됩니다.

※ setAttribute/onclick/this

▶ setAttribute
element.setAttribute("name", "value")

▶ onclick
html 태그일 시 : onclick = function()
자바스크립트일 시 : func(onclick, function())

▶ this
단독/일반 함수에서 this = window
메서드 안에서 this = this를 포함하는 객체
이벤트 메서드 안에서 this = 이벤트를 받는 HTML 요소 생성자 안에서 this = 생성자 함수가 생성하는 객체

setAttribute는 요소에 속성과 그 속성의 값을 부여하며, onclick은 클릭시 함수를 불러오는 역할을 합니다.
따라서 여기서 쓰인 setAttribute는 quizChoice[i] 즉, 보기를 클릭(onclick)할 시 choiceSelected( ) 함수를 불러오는 역할을 합니다.
이 때 this는 quizChoice[i]인 .choice의 값이므로 클릭한 보기의 내용이 됩니다.

3. 정답 확인


    //문제 출력
    quizType.innerHTML = quizInfo[index].answerType;
    quizQuestion.innerHTML = questionTag;
    quizSelects.innerHTML = choiceTag;
    quizResult.innerHTML = quizInfo[index].answerEx;

    const quizChoice = quizSelects.querySelectorAll(".choice");

    for(let i=0; i<quizChoice.length; i++){
        quizChoice[i].setAttribute("onclick", "choiceSelected(this)")
    }

    //문제, 해설 숨기기
    quizResult.style.display = "none";
    quizConfirm.style.display = "none";
};
updateQuiz(quizCount);

const choiceSelected = (answer) => {
    let userAnswer = answer.textContent;                    //사용자가 체크한 정답
    let currentAnswer = quizInfo[quizCount].answerResult;   //문제 정답

    if(userAnswer == currentAnswer){
        console.log("정딥");
        quizView.classList.add("like");
    } else {
        console.log("오답");
        quizView.classList.add("dislike");
        quizResult.style.display = "block";
    }
    quizConfirm.style.display = "block";
};

보기 클릭으로 실행된 choiceSelected( )함수의 answer는 this이며 이것은 클릭한 보기의 텍스트를 의미합니다.
따라서 보기의 텍스트와 같은 텍스트 내용을 정답으로 설정하고 if문으로 매칭하면 정답과 오답을 구분할 수 있습니다.

4. 슬라이드 기능

let quizCount = 0;
let quizScore = 0;

const choiceSelected = (answer) => {
    let userAnswer = answer.textContent;                    //사용자가 체크한 정답
    let currentAnswer = quizInfo[quizCount].answerResult;   //문제 정답

    if(userAnswer == currentAnswer){
        console.log("정딥");
        quizView.classList.add("like");
        quizScore++
    } else {
        console.log("오답");
        quizView.classList.add("dislike");
        quizResult.style.display = "block";
    }
    quizConfirm.style.display = "block";
};

// 정답 확인 버튼
const answerQuiz = () => {
    //마지막 문제
    if(quizInfo.length -1 == quizCount){
            quizConfirm.textContent = `총 ${quizInfo.length}문제 중에 ${quizScore}문제를 맞추었습니다.`
    };
    quizCount++;
    updateQuiz(quizCount);
    quizView.classList.remove("like", "dislike");
};

quizConfirm.addEventListener("click", answerQuiz);

1번 문제를 풀었으면 2번 문제로 넘어 가야겠죠. 마지막으로 다음 문제로 넘가도록 슬라이드 기능을 넣는 방법입니다.
함수로 index 값인 quizCount의 수 증가와 문제 출력 함수인 updateQuiz( )를 실행하도록 한 후 이벤트 함수 addEventListener로 클릭 시 이 함수를 실하도록 설정하면 끝입니다.

마지막 문제를 풀면 전체 문항수와 맞은 문항 수가 나오도록 하기 위해선 if문을 사용해 마지막 문제 번호가 될 시 실행하도록 하면 됩니다.
이 때 quizInfo의 length 값이 0부터 시작하는 변수인 quizCount보다 1 크므로 -1을 해야 값을 일치시킬 수 있습니다.

댓글


광고 준비중입니다.