使用 HTML + JavaScript 实现在线知识挑战

文章目录

一、在线知识挑战

在线知识挑战系统为用户提供了一个互动性强、反馈及时的学习体验平台。通过倒计时机制增加紧张感,即时结果显示正确答案帮助用户学习,得分统计激发用户的竞争心理。这种系统特别适用于教育应用、技能评估或娱乐类游戏。

本文将介绍如何使用 HTML、CSS 和 JavaScript 实现一个完整的知识挑战系统。

二、效果演示

这个知识挑战系统具有完整的交互流程:用户点击"开始答题"按钮进入挑战界面,系统展示第一道题目并启动 30 秒倒计时。用户可以选择答案选项,系统立即显示正确或错误状态,并在 1 秒后自动跳转到下一题。当时间耗尽而未作答时,系统会标记正确答案并自动跳转。完成后,系统显示总得分和鼓励信息,用户可以选择重新挑战。


三、系统分析

1、页面结构

页面主要包括以下部分:

1.1 开始界面

包含标题、说明文字和开始按钮,引导用户进入挑战。

html 复制代码
<div class="start-screen" id="startScreen">
    <h2>欢迎参加在线知识挑战</h2>
    <p>本挑战包含 <span id="totalQuestions">0</span> 道题目,每题100金币</p>
    <p>每题限时30秒,答对获得100金币,祝您好运!</p>
    <button class="btn" onclick="startQuiz()">开始答题</button>
</div>

1.2 题目容器

包含圆形倒计时器和题目卡片,显示当前题目和可选择的答案。

html 复制代码
<div class="quiz-container hidden" id="quizContainer">
    <div id="timer" class="circular-timer">
        <svg width="70" height="70" viewBox="0 0 70 70">
            <circle class="circle-bg" cx="35" cy="35" r="30"></circle>
            <circle class="circle" cx="35" cy="35" r="30" stroke-dasharray="188.5" stroke-dashoffset="0" id="timerCircle"></circle>
        </svg>
        <div class="timer-center" id="timerText">30</div>
    </div>

    <div class="question-card" id="questionCard">
        <div class="question-header">
            <div class="question-counter" id="questionCounter">1 / 10</div>
            <div class="question-text" id="questionText"></div>
        </div>
        <div class="options" id="optionsContainer"></div>
    </div>
</div>

1.3 结果界面

显示最终得分和鼓励信息,提供重新开始的选项。

html 复制代码
<div class="result-screen hidden" id="resultScreen">
    <h2>答题完成!</h2>
    <div class="score-display">
        <div class="score-number" id="finalScore">0金币</div>
        <div class="result-message" id="resultMessage"></div>
    </div>
    <button class="btn" onclick="restartQuiz()">重新答题</button>
</div>

2、核心功能实现

系统通过全局变量维护挑战状态,包括当前题目索引、得分、用户答案记录和计时器。startQuiz 函数负责重置这些变量并切换到题目界面。

javascript 复制代码
let currentQuestion = 0;
let score = 0;
let answers = [];
const timeLimit = 30;
let timer = null;
javascript 复制代码
function startQuiz() {
    startScreen.classList.add('hidden');
    quizContainer.classList.remove('hidden');
    currentQuestion = 0;
    score = 0;
    answers = new Array(questions.length).fill(null);

    displayQuestion();
    startTimer();
}

2.1 圆形倒计时实现

使用 SVG 圆形元素创建视觉化的倒计时效果,通过修改 stroke-dashoffset 属性控制圆弧长度,同时改变颜色以提示剩余时间。

javascript 复制代码
function startTimer() {
    clearInterval(timer);
    let timeLeft = timeLimit;
    const radius = 30;
    const circumference = 2 * Math.PI * radius;

    timerCircle.style.strokeDasharray = circumference;
    timerCircle.style.strokeDashoffset = 0;
    timerCircle.style.stroke = '#3b82f6';
    timerText.textContent = timeLeft.toString();

    const initialOffset = (timeLeft / timeLimit) * circumference;
    timerCircle.style.strokeDashoffset = circumference - initialOffset;

    timer = setInterval(() => {
        timeLeft--;

        if (timeLeft <= 0) {
            handleTimeout();
            return;
        }

        const offset = (timeLeft / timeLimit) * circumference;
        timerCircle.style.strokeDashoffset = circumference - offset;
        timerText.textContent = timeLeft.toString();

        if (timeLeft <= 10) {
            timerCircle.style.stroke = '#ef4444';
            timerText.style.color = '#ef4444';
        }
    }, 1000);
}

2.2 题目渲染与交互

displayQuestion 函数根据当前题目数据渲染选项,并处理用户交互逻辑。它会根据用户是否已作答来决定显示样式和交互行为。

javascript 复制代码
function displayQuestion() {
    const q = questions[currentQuestion];
    const userAnswer = answers[currentQuestion];

    questionText.textContent = q.question;
    questionCounter.textContent = `${currentQuestion + 1} / ${questions.length}`;

    optionsContainer.innerHTML = '';
    q.options.forEach((option, index) => {
        const el = document.createElement('div');
        el.className = 'option';

        if (userAnswer === null) {
            el.onclick = () => selectOption(index);
        }

        if (userAnswer !== null) {
            if (userAnswer === index) {
                el.classList.add('selected');
                if (userAnswer === q.correct) el.classList.add('correct');
                else el.classList.add('incorrect');
            }
            if (index === q.correct && userAnswer !== q.correct) {
                el.classList.add('correct');
            }
        }

        el.innerHTML = `<span class="option-letter">${String.fromCharCode(65 + index)}</span>${option}`;
        optionsContainer.appendChild(el);
    });
}

2.3 答案处理与导航

selectOption 函数处理用户选择,验证答案正确性并更新得分,然后延迟跳转到下一题。goToNextQuestion 函数管理题目间的导航逻辑。

javascript 复制代码
function selectOption(optionIndex) {
    if (answers[currentQuestion] !== null) return;

    clearInterval(timer);
    answers[currentQuestion] = optionIndex;
    const q = questions[currentQuestion];
    const options = optionsContainer.querySelectorAll('.option');

    options.forEach((el, index) => {
        el.classList.remove('selected', 'correct', 'incorrect');

        if (index === optionIndex) {
            el.classList.add('selected');
            if (optionIndex === q.correct) {
                el.classList.add('correct');
                score += 100;
            } else {
                el.classList.add('incorrect');
            }
        }
        if (index === q.correct && optionIndex !== q.correct) {
            el.classList.add('correct');
        }
    });

    setTimeout(goToNextQuestion, 1000);
}
javascript 复制代码
function goToNextQuestion() {
    if (currentQuestion < questions.length - 1) {
        currentQuestion++;
        displayQuestion();
        startTimer();
    } else {
        endQuiz();
    }
}

四、扩展建议

  • 添加难度等级选择功能,调整题目数量和时间限制
  • 实现用户登录系统,保存历史得分和排名
  • 增加音效反馈,提升用户体验的沉浸感

五、源码地址

git地址:https://gitee.com/ironpro/hjdemo/blob/master/quiz/index.html

相关推荐
pe7er14 小时前
window管理开发环境篇 - 持续更新
前端·后端
We་ct15 小时前
LeetCode 5. 最长回文子串:DP + 中心扩展
前端·javascript·算法·leetcode·typescript
陈随易19 小时前
有生之年系列,Nodejs进程管理pm2 v7.0发布
前端·后端·程序员
冰暮流星19 小时前
javascript之事件代理/事件委托
前端
陈随易21 小时前
AI时代,你还在坚持手搓文章吗
前端·后端·程序员
里欧跑得慢1 天前
17. Flutter Hero动画实现:让界面过渡更加优雅
前端·css·flutter·web
IT_陈寒1 天前
Vue的这个响应式陷阱,我debug了一整天才爬出来
前端·人工智能·后端
cn_mengbei1 天前
用React Native开发OpenHarmony应用:Reanimated共享元素过渡
javascript·react native·react.js
kyriewen1 天前
前端测试:别为了100%覆盖率而写测试,那是自欺欺人
前端·javascript·单元测试
去伪存真1 天前
我自己写的第一个skills--project-core-standards
前端·agent