大家好,今天给大家分享一个在线答题的应用,这样的答题应用想必大家都玩过,比如常见电商平台答题领优惠券运营活动,就会用到类似的应用,如下图所示: 从上图示意,我们来分析下类似项目的需求,需求分析清楚,才能动手:
聊完需求,我们先从最基础的 HTML 结构开始做起,定义页面容器 container、题目容器 quiz、答题结果容器 score-container。
<div class="container"> <!-- 开始答题按钮 --> <div class="start"> <h1>Start</h1> </div> <!-- 题目容器 --> <div class="quiz"> <div class="question"></div> <!-- 题目选项 --> <div class="choices"> <div class="choice" id="A"></div> <div class="choice" id="B"></div> <div class="choice" id="C"></div> <div class="choice" id="D"></div> </div> <!-- 计时器容器 --> <div class="timer"> <div class="counter"></div> <div class="time-gauge-bg"></div> <div class="time-gauge"></div> </div> <!-- 答题进度和正确与否提示 --> <div class="progress-container"></div> </div> <!-- 答题进度和正确与否提示 --> <!-- Score Container --> <div class="score-container"></div> </div>
接下来定义相关的样式,由于非本文章重点的介绍内容,这里就不过多介绍
* { padding: 0; margin: 0; box-sizing: border-box; } body { font-family: Arial, Helvetica, sans-serif; background-repeat: no-repeat; background-size: cover; background-position: center; height: 100vh; display: flex; align-items: center; justify-content: center; line-height: 1.6; } .container { height: 700px; width: 1400px; position: relative; } .start h1 { font-weight: 100; font-size: 40px; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); cursor: pointer; background-color: #41444b; padding: 20px 50px; color: white; } .quiz { height: 100%; width: 100%; position: absolute; top: 0; left: 0; display: grid; grid-template-rows: repeat(4, 1fr); grid-row-gap: 20px; visibility: hidden; } .quiz > * { display: flex; align-items: center; justify-content: center; } .question { font-size: 35px; letter-spacing: 2px; background-color: rgba(247, 247, 247, 0.7); place-self: center; padding: 15px 30px; text-align: center; } .choices { width: 100%; justify-content: space-evenly; align-items: flex-end; } .choice { cursor: pointer; background-color: rgba(27, 118, 141, 0.7); padding: 7px 15px; text-align: center; color: white; font-size: 20px; height: 100px; width: 250px; display: flex; align-items: center; justify-content: center; } /* 计时器容器 */ .timer { align-self: flex-end; flex-direction: column; } .counter { font-size: 40px; color: rgb(27, 118, 141); } .time-gauge-bg, .time-gauge { position: absolute; top: 78%; left: 22%; } .time-gauge-bg { height: 10px; width: 800px; background-color: lightgrey; } .time-gauge { height: 10px; background-color: rgb(179, 6, 247); } /* 答题进度容器 */ .progress-box { height: 30px; width: 30px; background-color: lightgrey; margin-left: 15px; } /* 答题结果容器 */ .score-container { position: absolute; top: 0; left: 0; background-color: rgba(0, 0, 0, 0.85); height: 100%; width: 100%; display: flex; align-items: center; justify-content: center; flex-direction: column; padding: 50px 100px; visibility: hidden; } .score-container h2 { font-size: 30px; font-weight: 100; text-align: center; color: white; }
接下来,我们基于需求编写业务的核心代码文件 app.js 。
编写核心函数之前,我们先定义基础的变量和题目数据源。
首先定义 DOM 相关的变量,方便我们进行相关的 DOM 操作
const start = document.querySelector(".start"); const quiz = document.querySelector(".quiz"); const question = document.querySelector(".question"); const allAnswerChoices = document.querySelectorAll(".choice"); const answerChoiceA = document.querySelector("#A"); const answerChoiceB = document.querySelector("#B"); const answerChoiceC = document.querySelector("#C"); const answerChoiceD = document.querySelector("#D"); const counter = document.querySelector(".counter"); const timeGauge = document.querySelector(".time-gauge"); const progressContainer = document.querySelector(".progress-container"); const ScoreContainer = document.querySelector(".score-container");
定义问题数据源变量 questions
,结构如下所示:
let questions = [ { question: "How many different sounds can a cat make?", questionImg: "img/1.jpg", choiceA: "100", choiceB: "150", choiceC: "10", choiceD: "27", correctAnswer: "100", }, //...此处省略多条数据 { question: "If a wolf trespasses on the territory of other wolves, what will happen?", questionImg: "img/10.jpg", choiceA: "Nothing", choiceB: "It will be accepted into the pack", choiceC: "It will be chased or killed", choiceD: "It will be required to present prey to the pack", correctAnswer: "It will be chased or killed", }, ];
最后定义一些基础常量,比如问题的数量、当前问题的序号、定义每道题的作答时长等,相关变量如下:
const lastQuestion = questions.length - 1; let activeQuestion = 0; const questionTime = 10; // 10 秒作答时间 const gaugeWidth = 800;// 800 px const gaugeUnit = gaugeWidth / questionTime; //每秒进度 80px let count = 0; let Timer; //定时器 let score = 0; //分数(答对的题目数量)
接下来我们为 start 按钮添加 startQuiz
开始答题监听事件,以及为每个答案选项添加 checkAnswer
事件,确认用户选的答案是否正确。
//添加开始答题监听事件 start.addEventListener("click", startQuiz); allAnswerChoices.forEach(function (clickAnswer) { clickAnswer.addEventListener("click", function (e) { let userAnswer = e.target.innerText; checkAnswer(userAnswer); }) })
接下我们来定义 startQuiz()
开始答题函数:start
开始按钮隐藏,显示问题容器,加载当前的问题 renderQuestion()
、以及显示当前题目数量的小方格 renderProgress()
、答题时进行的计时函数renderCounter(),
及计时器 Timer,
定时刷新计时函数。
//开始答题函数 function startQuiz() { start.style.display = "none"; renderQuestion(); quiz.style.visibility = "visible"; renderProgress(); renderCounter(); Timer = setInterval(renderCounter,1000); } //渲染问题 function renderQuestion() { let q = questions[activeQuestion]; question.innerHTML = "<p>" + q.question + "</p>"; answerChoiceA.innerHTML = q.choiceA; answerChoiceB.innerHTML = q.choiceB; answerChoiceC.innerHTML = q.choiceC; answerChoiceD.innerHTML = q.choiceD; let bodyImg = `url('${q.questionImg}')`; document.body.style.background = bodyImg; } //计时器进度 function renderCounter() { if (count <= questionTime) { counter.innerHTML = count; timeGauge.style.width = count * gaugeUnit + "px"; count++ } else { answerIsIncorrect(); nextQuestion(); } } //加载目前答题数量 function renderProgress() { for (let questionIndex = 0; questionIndex <= lastQuestion; questionIndex++) { progressContainer.innerHTML += "<div class='progress-box' id=" + questionIndex + "></div>"; } }
最后我们来定义判断答案是否正确的函数 checkAnswer
,以及对应当前方格的颜色(正确显示绿色 answerIsCorrect()
,错误显示红色 answerIsIncorrect()
),加载下一题的函数 nextQuestion()
和汇总所有题目的结果renderScore()
:正确率和正确的题目数量。
//判断答案是否正确 function checkAnswer(answer) { if (answer === questions[activeQuestion].correctAnswer) { score++ answerIsCorrect(); } else { answerIsIncorrect(); } nextQuestion(); } //答案正确,对应进度背景方格显示绿色 function answerIsCorrect() { document.getElementById(activeQuestion).style.background = "green"; } //答案错误,对应进度背景方格显示红色 function answerIsIncorrect() { document.getElementById(activeQuestion).style.background = "red"; } //显示下一个题目 function nextQuestion(){ count = 0; if(activeQuestion<lastQuestion){ activeQuestion++ renderQuestion(); } else{ clearInterval(Timer); renderScore(); } } //加载目前答题的数量 function renderProgress() { for (let questionIndex = 0; questionIndex <= lastQuestion; questionIndex++) { progressContainer.innerHTML += "<div class='progress-box' id=" + questionIndex + "></div>"; } } //显示分数 function renderScore(){ ScoreContainer.style.visibility="visible"; let scorePercentage= Math.round((100*score)/questions.length); ScoreContainer.innerHTML+=`<h2>当前正确率:${scorePercentage}</h2>`; ScoreContainer.innerHTML+=`<h2>答对的题目数量:${score}</h2>`; }
到这里本案例就介绍完了,是不是很容易理解呢,小编建议大家亲自动手实践下,大家可以点击链接进行体验,https://darenqademo.netlify.app/,点击源码地址获取源码链接: https://pan.baidu.com/s/17c1GFVxnWp15dl1YjbRPfw?pwd=ifs5 提取码: ifs5
注:本文属于原创文章,版权属于「前端达人」公众号及 qianduandaren.com 所有,未经授权,谢绝一切形式的转载