JS实现电脑虚拟键盘打字测试


Posted in Javascript onJune 24, 2020

这篇blog主要是结合前面两个知识点:JS实现电脑虚拟键盘的操作、JS实现简单打字测试

实现的效果如下:

JS实现电脑虚拟键盘打字测试

具体代码如下:

Html部分:

<!DOCTYPE html>
<html lang="en">

<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <link rel="stylesheet" href="./index.css" >
 <link rel="stylesheet" href="./keyBoard..css" >
 <title>打字测试</title>
</head>

<body>
 <div class="type_content">
  <h3>打字测试</h3>
  <ul class="type_box">
   <li class="error_box">
    <p class="error">错误</p>
    <p class="error_text">0</p>
   </li>
   <li class="time_box">
    <p style="margin: 10px;">时间</p>
    <p class="time_text">60s</p>
   </li>
   <li class="currcorrect_box">
    <p style="margin: 10px;">当前准确率%</p>
    <p class="currcorrect_text">100</p>
   </li>
   <li class="type_speed">
    <p style="margin: 10px;">打字速度</p>
    <p class="type_speed_text">30个/分</p>
   </li>
  </ul>
  <div class="text_box">点击下放文本输入框开始打字!!!</div>
  <div class="text_area">
  <textarea name="" id="textarea_box" placeholder="start typing here..."> </textarea>
  </div>
  <button class="restart" onclick="resetValues()">重新开始</button>
 </div>
 <div class="keyBoard">
 
 </div>
 <script src="./jquery-1.11.0.min.js"></script>
 <script src="./index.js"></script>
 <script src="./keyBoard.js"></script>

</body>

</html>

index.css:

*{
 margin: 0;
 padding: 0;
}
.type_content{
 width: 60%;
 /* height: 440px; */
 border: 1px solid #ccccff;
 max-width: 600px;
 margin: 10px auto;
 border-radius: 8px;
 position: relative;
 min-width: 500px;
}
.type_content h3{
 text-align: center;
 margin: 10px 0px;
}
.type_box{
 list-style: none;
 width: 90%;
 height: 100px;
 /* border: 1px solid black; */
 margin: 0 auto;
 margin-bottom: 10px;
 display: flex;
 align-items: center;
 justify-content: space-around;
}
.type_box li{
 width: 88px;
 height: 88px;
 /* border: 1px solid black; */
 text-align: center;
 font-size: 16px;
 border-radius: 8px;
 /* color: #fff; */
}
.error_box{
 background-color: #ccffcc;
 color: red;
}
.time_box{
 background-color: #66ffff;
 color: #000033;
}
.currcorrect_box{
 background-color: #FFC125;
 color: #fff;
}
.type_speed{
 background-color: #FF4040;
 color: #fff;
 display: none;
}
.final_correct{
 background-color: #E3E3E3;
 color: #555555;
 display: none;
}
.error{
 margin: 10px;
}
.text_box{
 width: 80%;
 /* height: 50px; */
 margin: 20px auto 40px auto;
 /* border: 1px solid black; */
 background-color: #D1EEEE;
 color: #000;
 border-radius: 6px;
 /* text-align: center; */
 line-height: 40px;
 padding: 0px 5px;
 /* box-sizing: border-box; */
}
.text_area{
 width: 80%;
 height: 50px;
 margin: 0px auto;
 padding-bottom: 50px;
 margin-bottom: 30px;
 
}
#textarea_box{
 resize:none;
 width: 100%;
 height: 100%;
 padding: 6px 10px;
 font-size: 16px;
 border-radius: 6px;
 outline: none;
 border: none;
 border: 2px solid #eee;
} 
.incorrect_char { 
 color: red; 
 text-decoration: underline; 
 } 
 
 .correct_char { 
 color: #9B30FF; 
 }
 .restart{
  width: 120px;
  height: 40px;
  display: none;
  border: none;
  outline: none;
  cursor: pointer;
  color: #fff;
  background-color: #9900ff;
  border-radius: 6px;
  position: absolute;
  bottom: 10px;
  left: 50%;
  margin-left: -60px;
  
}

keyboard.css:

/* body * {
 margin: 0;
 padding: 0;
 box-sizing: border-box;
 font-family: Arial, Helvetica, sans-serif;
} */
.keyBoard{
 max-width: 800px;
 padding: 20px;
 position: absolute;
 /* top: 50%;
 left: 50%;
 transform: translate(-50%, -50%); */
 background-color: rgb(197, 197, 197);
 border-radius: 10px;
 display: none;
 grid-template-columns: repeat(30, 20px);
 grid-template-rows: repeat(5, 30px);
 grid-gap: 5px;
 margin-left: 20%;

}
.key {
 background-color: rgb(243, 243, 243);
 border: 2px solid black;
 border-radius: 5px;
 grid-column: span 2;
 font-size: 12px;
 text-align: center;
 /* padding-top: 17px; */
 cursor: pointer;
 line-height: 30px;
 font-weight: 700;
}

.key:hover {
 border: 1px solid #eeeeee;
 
 
}

.backspace {
 grid-column: span 4;
}

.tab {
 grid-column: span 3;
}

.backslash {
 grid-column: span 3;
}

.capslock {
 grid-column: span 4;
}

.enter {
 grid-column: span 4;
}

.leftshift {
 grid-column: span 5;
}

.rightshift {
 grid-column: span 5;
}

.leftctrl {
 grid-column: span 3;
}

.microsoft {
 grid-column: span 3;
 font-size: 14px;
 
}

.space {
 grid-column: span 13;
}
.input_box{
 width: 400px;
 height: 60px;
 /* border: 1px solid black; */
 margin: auto;
 margin-top: 100px;
}
.input_box input{
 outline: none;
 border: none;
 width: 100%;
 height: 100%;
 border: 2px solid #ccc;
 border-radius: 8px;
 padding: 10px;
 font-size: 30px;
}

index.js:

//定义测试时间
var testTime = 60;
//定义测试的句子
var testSentence = [
 "Push yourself, because no one else is going to do it for you.",
 "Failure is the condiment that gives success its flavor.",
 // "Wake up with determination. Go to bed with satisfaction.",
 // "It's going to be hard, but hard does not mean impossible.",
 // "Learning never exhausts the mind.",
 // "The only way to do great work is to love what you do."
]
//定义dom
//1.错误dom
var error_text = document.querySelector('.error_text');
//2.时间dom
var time_text = document.querySelector('.time_text');
//3.当前正确率
var currcorrect_text = document.querySelector('.currcorrect_text');
//4.打字速度
var type_speed_text = document.querySelector('.type_speed_text');

//打字速度父dom
var type_speed = document.querySelector('.type_speed');


//句子dom
var text_box = document.querySelector('.text_box');
//输入
var textarea_box = document.querySelector('#textarea_box');
//按钮
var restart = document.querySelector('.restart')
var timeLeft = testTime;
//当前句子
var currentSentence = "";
//默认开始是索引为0
var startIndex = 0;
//错误统计
var errors = 0;
var characterTyped = 0;
//总错误
var total_errors = 0; 
var timer = null;
var timeElapsed = 0; //已用时间
var accuracy = 0;//正确个数
//更新渲染句子
function updateSentence(){
 text_box.textContent = null;
 currentSentence = testSentence[startIndex];
 //句子拆分
 var newChar = currentSentence.split('');
 for(var i = 0; i < newChar.length; i++){
  var charSpan = document.createElement('span');
  charSpan.innerText = newChar[i];
  text_box.appendChild(charSpan)
 }
 if(startIndex < testSentence.length - 1){
  startIndex++;
 }else{
  startIndex = 0
 }
}
//输入当前正确的句子
function processCurrentText(){
 curr_input = textarea_box.value;
 curr_input_array = curr_input.split('');
 // console.log(curr_input_array);
 characterTyped++;
 errors = 0;
 quoteSpanArray = text_box.querySelectorAll('span');
 // console.log(quoteSpanArray);
 quoteSpanArray.forEach((char,index)=>{
  var typeChar = curr_input_array[index];
  //当前没有输入
  if(typeChar == null){
   char.classList.remove('correct_char'); 
   char.classList.remove('incorrect_char'); 
  }else if(typeChar === char.innerText){
   //正确的输入
   char.classList.add('correct_char'); 
   char.classList.remove('incorrect_char'); 
  }else{
   //不正确的输入
   char.classList.add('incorrect_char'); 
    char.classList.remove('correct_char');
    errors++; 
  }
 })
 error_text.textContent = total_errors + errors; 
 console.log(characterTyped)
 console.log(error_text.textContent)
 var correctCharacters = (characterTyped - (total_errors + errors)); 
 var accuracyVal = ((correctCharacters / characterTyped) * 100); 
 console.log(accuracyVal)
 currcorrect_text.textContent = Math.round(accuracyVal); 
 //输入结束
 if(curr_input.length == currentSentence.length){
  updateSentence(); 
  total_errors += errors; 
  textarea_box.value = ""
 }
}
//开始游戏
function startGame(){
 resetValues(); 
 updateSentence(); 
 
 // clear old and start a new timer 
 clearInterval(timer); 
 timer = setInterval(updateTimer, 1000); 
}
//重新开始
function resetValues(){
 timeLeft = testTime;
 timeElapsed = 0;
 errors = 0;
 total_errors = 0;
 accuracy = 0;
 characterTyped = 0;
 startIndex = 0;
 textarea_box.disabled = false;
 textarea_box.value = "";
 text_box.textContent = 'Click on the area below to start the game.'; 
 currcorrect_text.textContent = 100;
 time_text.textContent = timeLeft + 's';
 type_speed.style.display = 'none';
 
}
//更新时间
function updateTimer() { 
 if (timeLeft > 0) { 
  // decrease the current time left 
  timeLeft--; 
 
  // increase the time elapsed 
  timeElapsed++; 
 
  // update the timer text 
  time_text.textContent = timeLeft + "s"; 
 } 
 else { 
  // finish the game 
  finishGame(); 
 } 
 } 
 //游戏结束
 function finishGame() { 
 // stop the timer 
 clearInterval(timer); 
 
 // disable the input area 
 textarea_box.disabled = true; 
 
 // show finishing text 
 text_box.textContent = "可点击下方按钮重新开始!!!"; 
 
 // display restart button 
 restart.style.display = "block"; 
 
 // calculate cpm and wpm 
 console.log(characterTyped,timeElapsed)
 cpm = Math.round(((characterTyped / timeElapsed) * 60)); 
 
 // update cpm and wpm text 
 
 type_speed_text.textContent = cpm + '个/分'; 
 
 // display the cpm and wpm 
 type_speed.style.display = "block"; 
 
 }

keyboard.js:

var keyArray = [
 { 'key_name': '`', 'key_val': '192' },
 { 'key_name': '1', 'key_val': '49' },
 { 'key_name': '2', 'key_val': '50' },
 { 'key_name': '3', 'key_val': '51' },
 { 'key_name': '4', 'key_val': '52' },
 { 'key_name': '5', 'key_val': '53' },
 { 'key_name': '6', 'key_val': '54' },
 { 'key_name': '7', 'key_val': '55' },
 { 'key_name': '8', 'key_val': '56' },
 { 'key_name': '9', 'key_val': '57' },
 { 'key_name': '0', 'key_val': '48' },
 { 'key_name': '-', 'key_val': '189' },
 { 'key_name': '=', 'key_val': '187' },
 { 'key_name': 'Backspace', 'key_val': '8' },

 { 'key_name': 'Tab', 'key_val': '9' },
 { 'key_name': 'Q', 'key_val': '81' },
 { 'key_name': 'W', 'key_val': '87' },
 { 'key_name': 'E', 'key_val': '69' },
 { 'key_name': 'R', 'key_val': '82' },
 { 'key_name': 'T', 'key_val': '84' },
 { 'key_name': 'Y', 'key_val': '89' },
 { 'key_name': 'U', 'key_val': '85' },
 { 'key_name': 'I', 'key_val': '73' },
 { 'key_name': 'O', 'key_val': '79' },
 { 'key_name': 'P', 'key_val': '80' },
 { 'key_name': '[', 'key_val': '219' },
 { 'key_name': ']', 'key_val': '221' },
 { 'key_name': "\\ ", 'key_val': '220' },

 { 'key_name': 'CapsLock', 'key_val': '20' },
 { 'key_name': 'A', 'key_val': '65' },
 { 'key_name': 'S', 'key_val': '83' },
 { 'key_name': 'D', 'key_val': '68' },
 { 'key_name': 'F', 'key_val': '70' },
 { 'key_name': 'G', 'key_val': '71' },
 { 'key_name': 'H', 'key_val': '72' },
 { 'key_name': 'J', 'key_val': '74' },
 { 'key_name': 'K', 'key_val': '75' },
 { 'key_name': 'L', 'key_val': '76' },
 { 'key_name': ';', 'key_val': '186' },
 { 'key_name': "'", 'key_val': '222' },
 { 'key_name': 'Enter', 'key_val': '13' },

 { 'key_name': 'Shift', 'key_val': '16' },
 { 'key_name': 'Z', 'key_val': '90' },
 { 'key_name': 'X', 'key_val': '88' },
 { 'key_name': 'C', 'key_val': '67' },
 { 'key_name': 'V', 'key_val': '86' },
 { 'key_name': 'B', 'key_val': '66' },
 { 'key_name': 'N', 'key_val': '78' },
 { 'key_name': 'M', 'key_val': '77' },
 { 'key_name': ',', 'key_val': '188' },
 { 'key_name': '.', 'key_val': '190' },
 { 'key_name': '/', 'key_val': '191' },
 { 'key_name': 'Shift', 'key_val': '16' },

 { 'key_name': 'Ctrl', 'key_val': '17' },
 { 'key_name': 'Alt', 'key_val': '18' },
 { 'key_name': 'Home', 'key_val': '36 ' },
 { 'key_name': 'Space', 'key_val': '32' },
 { 'key_name': 'Home', 'key_val': '36' },
 { 'key_name': 'Alt', 'key_val': '18' },
 { 'key_name': 'Ctrl', 'key_val': '17' },
 { 'key_name': 'Fn', 'key_val': '00' },

]
var keyBoard = document.getElementsByClassName('keyBoard')[0]
function renderKeyBoard(keyArray) {
 var template = '';
 for (var i = 0; i < keyArray.length; i++) {
  if (keyArray[i].key_val == '8') {
   template += "<div class='key backspace' data-key='" + keyArray[i].key_val + "'>" + keyArray[i].key_name + "</div>";
  } else if (keyArray[i].key_val == '9') {
   template += "<div class='key tab' data-key='" + keyArray[i].key_val + "'>" + keyArray[i].key_name + "</div>";
  } else if (keyArray[i].key_val == '220') {
   template += "<div class='key backslash' data-key='" + keyArray[i].key_val + "'>" + keyArray[i].key_name + "</div>";
  } else if (keyArray[i].key_val == '20') {
   template += "<div class='key capslock' data-key='" + keyArray[i].key_val + "'>" + keyArray[i].key_name + "</div>";
  } else if (keyArray[i].key_val == '13') {
   template += "<div class='key enter' data-key='" + keyArray[i].key_val + "'>" + keyArray[i].key_name + "</div>";
  } else if (keyArray[i].key_val == '16') {
   template += "<div class='key leftshift' data-key='" + keyArray[i].key_val + "'>" + keyArray[i].key_name + "</div>";
  } else if (keyArray[i].key_val == '16') {
   template += "<div class='key rightshift' data-key='" + keyArray[i].key_val + "'>" + keyArray[i].key_name + "</div>";
  } else if (keyArray[i].key_val == '17') {
   template += "<div class='key leftctrl' data-key='" + keyArray[i].key_val + "'>" + keyArray[i].key_name + "</div>";
  } else if (keyArray[i].key_val == '36') {
   template += "<div class='key microsoft' data-key='" + keyArray[i].key_val + "'>" + keyArray[i].key_name + "</div>";
  }
  else if (keyArray[i].key_val == '32') {
   template += "<div class='key space' data-key='" + keyArray[i].key_val + "'>" + keyArray[i].key_name + "</div>";
  }
  else {
   template += "<div class='key' data-key='" + keyArray[i].key_val + "'>" + keyArray[i].key_name + "</div>";
  }


 }
 // console.log(template)
 keyBoard.innerHTML = template;
}
renderKeyBoard(keyArray)
var key_div = document.getElementsByClassName('key');
// console.log(key_div)
$("#textarea_box").on("input", function (e) {
 // console.log(e.keyCode)
 keyBoard.style.display = 'grid'
 processCurrentText()

});
$("#textarea_box").on("focus", function (e) {
 // console.log(e.keyCode)
 keyBoard.style.display = 'grid';
 startGame();

});
$("#textarea_box").on("keydown", function (e) {
  console.log(e.target.value)
 if(e.target.value != ''){
 for (var i = 0; i < key_div.length; i++) {
  var key_val = Number(key_div[i].getAttribute('data-key'));
  if (key_val === e.keyCode) {
   key_div[i].style.color = '#fff';
   key_div[i].style.backgroundColor = '#9F79EE'
  } else {
   key_div[i].style.color = ''
   key_div[i].style.backgroundColor = ''
  }
 }
 }

});
$("#textarea_box").on("keyup", function (e) {
 for (var i = 0; i < key_div.length; i++) {
  key_div[i].style.color = ''
  key_div[i].style.backgroundColor = ''
 }

});
$("#textarea_box").on("blur", function (e) {
 // console.log(e.keyCode)
 keyBoard.style.display = 'none'

});

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js文件中调用js的实现方法小结
Oct 23 Javascript
jQuery UI AutoComplete 使用说明
Jun 20 Javascript
基于OO的动画附加插件,可以实现弹跳、渐隐等动画效果 分享
Jun 24 Javascript
js截取小数点后几位的写法
Nov 14 Javascript
js ajaxfileupload.js上传报错的解决方法
May 05 Javascript
js实现当鼠标移到表格上时显示这一格全部内容的代码
Jun 12 Javascript
Node.js开启Https的实践详解
Oct 25 Javascript
JS实现焦点图轮播效果的方法详解
Dec 19 Javascript
JS表格组件神器bootstrap table使用指南详解
Apr 12 Javascript
微信小程序显示倒计时功能示例【测试可用】
Dec 03 Javascript
JavaScript实现获取两个排序数组的中位数算法示例
Feb 26 Javascript
layer.alert回调函数执行关闭弹窗的实例
Sep 11 Javascript
JS实现简单打字测试
Jun 24 #Javascript
微信小程序实现多选框功能的实例代码
Jun 24 #Javascript
JS实现电脑虚拟键盘的操作
Jun 24 #Javascript
基于PHP pthreads实现多线程代码实例
Jun 24 #Javascript
js实现html滑动图片拼图验证
Jun 24 #Javascript
微信小程序的引导页实现代码
Jun 24 #Javascript
微信小程序仿抖音短视频切换效果的实例代码
Jun 24 #Javascript
You might like
php a simple smtp class
2007/11/26 PHP
PHP写的获取各搜索蜘蛛爬行记录代码
2012/08/21 PHP
VIM中设置php自动缩进为4个空格的方法详解
2013/06/14 PHP
php计算当前程序执行时间示例
2014/04/24 PHP
php读取出一个文件夹及其子文件夹下所有文件的方法示例
2017/06/15 PHP
阿里对象存储OSS在laravel框架中的使用方法
2019/10/13 PHP
JS Array对象入门分析
2008/10/30 Javascript
js的写法基础分析
2011/01/17 Javascript
jquery操作对象数组元素方法详解
2014/11/26 Javascript
JavaScript Window浏览器对象模型方法与属性汇总
2015/04/20 Javascript
自定义Angular指令与jQuery实现的Bootstrap风格数据双向绑定的单选与多选下拉框
2015/12/12 Javascript
jQuery原理系列-常用Dom操作详解
2016/06/07 Javascript
自动适应iframe右边的高度
2016/12/22 Javascript
BootStrap+Mybatis框架下实现表单提交数据重复验证
2017/03/23 Javascript
vue中的event bus非父子组件通信解析
2017/10/27 Javascript
从vue基础开始创建一个简单的增删改查的实例代码(推荐)
2018/02/11 Javascript
关于单文件组件.vue的使用
2018/09/20 Javascript
[02:14]2016国际邀请赛中国区预选赛Ehome晋级之路
2016/07/01 DOTA
Python中zip()函数用法实例教程
2014/07/31 Python
基于Python的接口测试框架实例
2016/11/04 Python
Python实现线程状态监测简单示例
2018/03/28 Python
对python自动生成接口测试的示例讲解
2018/11/30 Python
使用python进行拆分大文件的方法
2018/12/10 Python
Python自动化之数据驱动让你的脚本简洁10倍【推荐】
2019/06/04 Python
python根据字典的键来删除元素的方法
2020/08/16 Python
python如何调用php文件中的函数详解
2020/12/29 Python
利用CSS3动画实现圆圈由小变大向外扩散的效果实例
2018/09/10 HTML / CSS
社团招新策划书
2014/02/04 职场文书
2014年幼儿园重阳节活动方案
2014/09/16 职场文书
房屋产权证明书
2014/10/15 职场文书
2014年档案室工作总结
2014/12/01 职场文书
2015年个人审计工作总结
2015/04/07 职场文书
建国大业电影观后感
2015/06/01 职场文书
2016高校自主招生自荐信范文
2016/01/28 职场文书
商业计划书如何写?关键问题有哪些?
2019/07/11 职场文书
nginx代理实现静态资源访问的示例代码
2022/07/07 Servers