如何在打字速度测试中实现文本遍历与光标移动?
解决打字速度测试的光标移动与WPM统计问题
看起来你已经搭好了不错的基础框架,我来帮你梳理实现思路,解决光标移动和WPM计算的核心问题,同时修正你之前尝试代码里的小错误。
核心需求拆解
你需要实现两个关键功能:
- 仅在输入正确字符时,让闪烁光标在目标文本中逐步移动
- 统计用时并计算标准的WPM(每分钟字数)
一步步实现解决方案
1. 调整HTML结构(优化光标与文本的关联)
首先,我们把目标文本和光标分开,这样更容易精准控制光标的位置:
<body> <div class="jumbotron title-of-page container-fluid"> <h1>Typing Counter</h1> </div> <nav class="navbar navigation-bar container-fluid"> <div class=""> <ul class="nav navbar-nav"> <li><a href="#">Home</a></li> <li><a href="#">Contest</a></li> <li><a href="#">About</a></li> <li><a href="#">Leaderboard</a></li> </ul> </div> </nav> <div> <div id="timer"> <button type="button" class="btn">Start</button> </div> <div class="typing-field"> <p id="display-text"> <span class="typed-cursor">|</span> <span id="target-text">This is to test your typing speed. So type like you'll never type again.</span> </p> </div> <div class="user-input"> <input type="text" name="user-input-text-box" id="user-input" /> </div> </div> </body>
2. 重写JavaScript逻辑(实现光标移动与WPM计算)
替换你现有的JS代码,这个版本会处理输入校验、光标移动、倒计时和WPM计算:
// 全局状态变量,跟踪测试进度 let targetText = ''; let currentInputIndex = 0; let testStartTime = null; let countdownInterval = null; window.onload = function() { // 获取DOM元素 const userInputBox = document.getElementById('user-input'); const timerDisplay = document.getElementById('timer'); const targetTextElement = document.getElementById('target-text'); const startButton = timerDisplay.querySelector('button'); // 初始化目标文本 targetText = targetTextElement.textContent.trim(); // 绑定开始按钮点击事件 startButton.addEventListener('click', initTest); // 监听用户输入(用input事件比keyup更可靠,支持粘贴等操作) userInputBox.addEventListener('input', handleUserInput); // 初始化测试状态 function initTest() { // 重置所有状态 currentInputIndex = 0; testStartTime = Date.now(); userInputBox.value = ''; userInputBox.disabled = false; userInputBox.focus(); resetTextStyling(); // 启动倒计时 let remainingSeconds = 3; clearInterval(countdownInterval); countdownInterval = setInterval(() => { if (remainingSeconds === -1) { clearInterval(countdownInterval); timerDisplay.textContent = "Time Up"; userInputBox.disabled = true; calculateAndShowWPM(); } else { timerDisplay.textContent = `Time Left: ${remainingSeconds} seconds`; remainingSeconds--; } }, 1000); } // 处理用户输入校验 function handleUserInput() { if (!testStartTime || userInputBox.disabled) return; const inputValue = this.value; // 只校验最新输入的字符 const latestChar = inputValue[inputValue.length - 1]; const expectedChar = targetText[currentInputIndex]; if (latestChar === expectedChar) { // 输入正确:移动光标,高亮已输入文本 currentInputIndex++; updateTextStyling(); // 如果完成所有文本,提前结束测试 if (currentInputIndex >= targetText.length) { clearInterval(countdownInterval); timerDisplay.textContent = "Completed!"; userInputBox.disabled = true; calculateAndShowWPM(); } } else { // 输入错误:删除错误字符,给出视觉提示 this.value = inputValue.slice(0, -1); this.classList.add('input-error'); setTimeout(() => this.classList.remove('input-error'), 500); } } // 更新文本样式:高亮已输入内容,移动光标 function updateTextStyling() { const typedPart = targetText.slice(0, currentInputIndex); const remainingPart = targetText.slice(currentInputIndex); targetTextElement.innerHTML = ` <span style="color: green;">${typedPart}</span> <span class="typed-cursor">|</span> ${remainingPart} `; } // 重置文本样式到初始状态 function resetTextStyling() { targetTextElement.innerHTML = `<span class="typed-cursor">|</span>${targetText}`; } // 计算并显示WPM function calculateAndShowWPM() { if (!testStartTime) return; // 计算用时(转换为分钟) const timeElapsed = (Date.now() - testStartTime) / 1000 / 60; // 标准WPM计算:每5个字符(含空格)算一个单词 const totalTypedChars = currentInputIndex; const typedWords = totalTypedChars / 5; const wpm = Math.round(typedWords / timeElapsed); // 在页面显示结果 const resultElement = document.createElement('div'); resultElement.style.cssText = ` margin-top: 2em; font-size: 1.5em; text-align: center; color: #2ecc71; `; resultElement.textContent = `你的打字速度:${wpm} WPM`; document.body.appendChild(resultElement); } };
3. 补充CSS样式(优化错误提示)
在你的CSS里添加这行,给错误输入一个清晰的视觉提示:
#user-input.input-error { border-color: #e74c3c; outline-color: #e74c3c; }
你之前代码的问题说明
你尝试的JS代码有几个小错误,我帮你指出来:
document.getElementById('user-input').innerHTML:input元素的内容要通过value获取,不是innerHTML- 目标文本应该是
#display-text里的内容,而不是输入框的内容 letter.style.color="green":letter是字符串,不是DOM元素,不能直接设置样式- 使用
keyup事件:不如input事件可靠,input能捕获粘贴、长按输入等场景
内容的提问来源于stack exchange,提问作者3.14159
相关产品推荐
相关产品推荐

