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 相关文章推荐
取得父标签
Nov 14 Javascript
EditPlus注册码生成器(js代码实现)
Mar 25 Javascript
使用jquery实现div的tab切换实例代码
May 27 Javascript
用Javascript来生成ftp脚本的小例子
Jul 03 Javascript
JS、DOM和JQuery之间的关系示例分析
Apr 09 Javascript
JavaScript匿名函数与委托使用示例
Jul 22 Javascript
JavaScript多图片上传案例
Sep 28 Javascript
WordPress中鼠标悬停显示和隐藏评论及引用按钮的实现
Jan 12 Javascript
JS异步文件上传(兼容IE8+)
Apr 02 Javascript
基于Vue2x的图片预览插件的示例代码
May 14 Javascript
vue单页面在微信下只能分享落地页的解决方案
Apr 15 Javascript
uni app仿微信顶部导航条功能
Sep 17 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中Session引起的脚本阻塞问题解决办法
2014/04/08 PHP
PHP将数据导出Excel表中的实例(投机型)
2017/07/31 PHP
Laravel框架使用Redis的方法详解
2018/05/30 PHP
js+css实现导航效果实例
2015/02/10 Javascript
javascript生成不重复的随机数
2015/07/17 Javascript
ClearTimeout消除闪动实例代码
2016/02/29 Javascript
实例剖析AngularJS框架中数据的双向绑定运用
2016/03/04 Javascript
javascript中活灵活现的Array对象详解
2016/11/30 Javascript
jQuery Plupload上传插件的使用
2017/04/19 jQuery
nodeJS实现路由功能实例代码
2017/06/08 NodeJs
微信小程序如何获取openid及用户信息
2018/01/26 Javascript
react 国际化的实现代码示例
2018/09/14 Javascript
nodejs中用npm初始化来创建package.json的实例讲解
2018/10/10 NodeJs
Vue状态模式实现窗口停靠功能(灵动、自由, 管理后台Admin界面)
2020/03/06 Javascript
[02:21]DOTA2英雄基础教程 蝙蝠骑士
2013/12/16 DOTA
[07:49]2014DOTA2国际邀请赛 Newbee夺冠后采访xiao8坦言奖金会上交
2014/07/23 DOTA
跟老齐学Python之print详解
2014/09/28 Python
Python while、for、生成器、列表推导等语句的执行效率测试
2015/06/03 Python
利用Python2下载单张图片与爬取网页图片实例代码
2017/12/25 Python
Python+selenium实现截图图片并保存截取的图片
2018/01/05 Python
PyCharm配置mongo插件的方法
2018/11/30 Python
python 实现倒排索引的方法
2018/12/25 Python
Python datetime和unix时间戳之间相互转换的讲解
2019/04/01 Python
python pycharm的安装及其使用
2019/10/11 Python
Pandas时间序列基础详解(转换,索引,切片)
2020/02/26 Python
python“静态”变量、实例变量与本地变量的声明示例
2020/11/13 Python
python 录制系统声音的示例
2020/12/21 Python
马克华菲官方商城:Mark Fairwhale
2016/09/04 全球购物
巴基斯坦电子产品购物网站:Home Shopping
2017/09/14 全球购物
日本最大的药妆连锁店:Matsukiyo松本清药妆店
2017/11/23 全球购物
this关键字的作用
2016/01/30 面试题
驾驶员岗位职责
2014/01/29 职场文书
三问三解心得体会
2014/09/05 职场文书
印刷技术专业自荐信
2014/09/18 职场文书
2014年外联部工作总结
2014/11/17 职场文书
北京青年观后感
2015/06/15 职场文书