当前位置: 首页 > news >正文

JS+H5打字练习器

实现功能

1.导入.TXT文件到打字练习内容(部分浏览器可能出于安全问题限制了这一步操作)
2.输入文本到打字练习内(弹出输入框,将要练习的内容输入至输入框)
3. 开始练习,并根据正误在打字练习内容文本上修改颜色(某个字正确显示绿色,某个字错误,显示红色,某个字没有打显示灰色)
4.开始练习、结束练习,全部输入完成后自动结束练习,也可提前手动结束练习,结束练习后弹窗用显示时和正确率。(区别在于一个全部输入完成且全部正确,一个提前结束无其他条件)

效果图

在这里插入图片描述在这里插入图片描述

分析

HTML 结构解析

  1. 根元素<!DOCTYPE html> 声明文档类型为HTML。
  2. html 元素:包含整个页面的内容,并设置语言为中文(lang="zh-CN")。
  3. head 元素:包含页面的元数据,如字符集(charset="UTF-8")、视口设置(viewport)和标题(<title>)。
  4. style 元素:包含页面的CSS样式。
    • 设置页面背景颜色、字体、布局样式等。
  5. body 元素:包含页面的可见内容。
    • 使用Flexbox布局使内容居中。
  6. .container:包含文本输入框和按钮,并设置样式。
  7. .buttons:包含一组按钮,并设置布局样式。
  8. .text-to-type:包含待输入的文本,并设置样式。
  9. input 元素:一个文本输入框,用于用户输入。

JavaScript 解析

  1. 变量声明

    • textToType:获取待输入文本的DOM元素。
    • inputText:获取用户输入文本的DOM元素。
    • importTextBtnaddTextBtnstartPracticeBtnendPracticeBtn:获取按钮的DOM元素。
    • originalText:存储原始待输入的文本。
    • startTime:存储开始练习的时间。
    • alertCount:存储弹窗次数。
    • correctCount:存储正确的字符数。
  2. inputText 输入事件监听器

    • 当用户在输入框中输入时,会触发此事件。
    • 获取用户当前输入的文本。
    • 初始化一个空字符串updatedText用于构建更新后的文本。
    • 如果startTime已设置,遍历原始文本和用户输入的文本:
      • 如果字符匹配,将字符标记为correct
      • 如果字符不匹配,将字符标记为wrong
    • 更新textToType的HTML内容。
    • 如果用户输入的文本与原始文本完全匹配,计算总用时和正确率,并通过弹窗显示结果。
    • 重置输入框和startTime
  3. importTextBtn 点击事件监听器

    • 创建一个文件输入元素,允许用户选择.txt文件。
    • 当文件被选中后,使用FileReader读取文件内容。
    • 读取完成后,将文本内容赋值给originalText并更新textToType
  4. addTextBtn 点击事件监听器

    • 弹出一个输入框让用户输入文本。
    • 如果用户输入了文本,将其赋值给originalText并更新textToType
  5. startPracticeBtn 点击事件监听器

    • 设置startTime为当前时间。
    • 清空输入框。
    • 更新textToType的HTML内容为原始文本。
  6. endPracticeBtn 点击事件监听器

    • 如果startTime已设置,计算总用时和正确率,并通过弹窗显示结果。
    • 重置startTime和输入框。

完成源代码

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>打字练习</title><style>body {font-family: Arial, sans-serif;background-color: #f0f0f0;display: flex;justify-content: center;align-items: center;height: 100vh;margin: 0;}.container {background-color: white;padding: 20px;border-radius: 15px;box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);max-width: 600px;width: 100%;text-align: center;}.buttons {display: flex;justify-content: space-around;margin-bottom: 20px;}.buttons button {background-color: black;color: white;border: none;border-radius: 5px;box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);padding: 10px 20px;cursor: pointer;font-size: 14px;}.text-to-type {color: gray;margin-bottom: 20px;font-size: 20px;}.text-to-type span.correct {color: green;}.text-to-type span.wrong {color: red;}input[type="text"] {width: 100%;padding: 10px;border-radius: 5px;border: 1px solid #ccc;font-size: 18px;}</style>
</head>
<body><div class="container"><div class="buttons"><button id="importText">导入文本</button><button id="addText">添加文本</button><button id="startPractice">开始练习</button><button id="endPractice">结束练习</button></div><div class="text-to-type" id="textToType">这是一个打字练习的例子</div><input type="text" id="inputText" placeholder="开始打字..." /></div><script>const textToType = document.getElementById('textToType');const inputText = document.getElementById('inputText');const importTextBtn = document.getElementById('importText');const addTextBtn = document.getElementById('addText');const startPracticeBtn = document.getElementById('startPractice');const endPracticeBtn = document.getElementById('endPractice');let originalText = textToType.innerText;let startTime = null;let alertCount = 0;let correctCount = 0;inputText.addEventListener('input', () => {const typedText = inputText.value;let updatedText = '';correctCount = 0;if (startTime) {for (let i = 0; i < originalText.length; i++) {if (i < typedText.length) {if (typedText[i] === originalText[i]) {updatedText += `<span class="correct">${originalText[i]}</span>`;correctCount++;} else {updatedText += `<span class="wrong">${originalText[i]}</span>`;}} else {updatedText += originalText[i];}}textToType.innerHTML = updatedText;}if (typedText === originalText && startTime) {const endTime = new Date();const timeTaken = ((endTime - startTime) / 1000).toFixed(2);const accuracy = ((correctCount / originalText.length) * 100).toFixed(2);alert(`总用时间: ${timeTaken} 秒\n正确率: ${accuracy}%`);alertCount++;if (alertCount < 3) {alert(`这是第 ${alertCount} 次弹窗`);}inputText.value = '';startTime = null;}});importTextBtn.addEventListener('click', () => {const fileInput = document.createElement('input');fileInput.type = 'file';fileInput.accept = '.txt';fileInput.onchange = e => {const file = e.target.files[0];const reader = new FileReader();reader.onload = event => {originalText = event.target.result.trim();textToType.innerText = originalText;};reader.readAsText(file);};fileInput.click();});addTextBtn.addEventListener('click', () => {const userInput = prompt('请输入要练习的文本:');if (userInput) {originalText = userInput.trim();textToType.innerText = originalText;}});startPracticeBtn.addEventListener('click', () => {startTime = new Date();inputText.value = '';textToType.innerHTML = originalText;});endPracticeBtn.addEventListener('click', () => {if (startTime) {const endTime = new Date();const timeTaken = ((endTime - startTime) / 1000).toFixed(2);const accuracy = ((correctCount / originalText.length) * 100).toFixed(2);alert(`练习结束\n总用时间: ${timeTaken} 秒\n正确率: ${accuracy}%`);startTime = null;inputText.value = '';} else {alert('请先开始练习!');}});</script>
</body>
</html>

相关文章:

JS+H5打字练习器

实现功能 1.导入.TXT文件到打字练习内容&#xff08;部分浏览器可能出于安全问题限制了这一步操作&#xff09; 2.输入文本到打字练习内&#xff08;弹出输入框&#xff0c;将要练习的内容输入至输入框&#xff09; 3. 开始练习&#xff0c;并根据正误在打字练习内容文本上修…...

windows系统关闭开机自检硬盘

效果&#xff1a; 注册表关闭开机硬盘自检&#xff0c;你可以按照以下步骤操作&#xff1a; 打开注册表编辑器&#xff1a; 按 Win R 键打开“运行”对话框。输入 regedit 并按回车&#xff0c;打开注册表编辑器。 定位到自检相关的键&#xff1a; 依次展开以下路径&#x…...

【多线程开发 5】实践使用Lock和Condition

Lock和Condition Lock 线程之间同步或者竞争都需要锁这类结构&#xff0c;一般我们都会用Object的wait和signal搭配synchronized关键字进行多线程开发&#xff0c;但是很多时候会造成死锁的现象&#xff0c;这是因为synchroniezd无法破坏死锁的产生条件&#xff0c;但是Lock接…...

2.4-结构化并发:协程的结构化异常管理

文章目录 协程结构化异常流程协程结构化异常流程和取消流程的区别子协程异常为什么要连带取消父协程&#xff1f; CoroutineExceptionHandler异常协程异常的最后一道拦截&#xff1a;CoroutineExceptionHandlerCoroutineExceptionHandler 为什么只能设置给最外层协程才有效&…...

Android 12.0 debug版本打开OEM解锁开关功能实现

通常为了方便push在debug版本会采用如下命令 adb root adb disable-verity 提示&#xff1a; Device is locked. Please unlock the device first. 查找日志可以发现system/core/set-verity-state/set-verity-state.cpp文件中is_avb_device_locked方法里 这个获取ro.boot…...

linux用户组练习

准备工作 [rootlocalhost ~]# watch -n 1 tail -n 5 /etc/group使用watch 动态监控 1.建立用户组 shengcan&#xff0c;其id 为2000 2.建立用户组 caiwu&#xff0c;其id 为 2001 3.足建立用户组 jishu&#xff0c;其id 为 2002 4.建立用户lee&#xff0c;指定其主组id为sh…...

[Docker][Docker Container]详细讲解

目录 1.什么是容器&#xff1f;2.容器命令1.docker creatre2.docker run3.docker ps4.docker logs5.docker attach6.docker exec7.docker start8.docker stop9.docker restart10.docker kill11.docker top12.docker stats13.docker container inspect14.docker port15.docker c…...

塑造美好心灵,激发创造活力|第三届瓷艺中华“陶溪川杯”儿童青少年陶瓷作品展开展

第三届瓷艺中华“陶溪川杯”儿童青少年陶瓷作品展 展览现场 由中央美术学院、景德镇陶瓷大学、景德镇陶文旅控股集团共同主办&#xff0c;由中国非物质文化遗产保护协会陶瓷分会、中国文化艺术发展促进会陶瓷专业委员会、中央美术学院陶瓷艺术研究院、中央美术学院少儿美术教…...

鸿蒙开发刷新单个item会闪一下处理

鸿蒙开发刷新单个item会闪一下 首先我用的是懒加载方式,改变某位数据后我调listener.onDataChange(index),发现item的改动是变了,但是item也闪了一下。 先分析为什么item会闪一下 其他是因为item上有图片,加载的网络图。你onDataChange(index)时,它会重新加载这一item,…...

您需要了解的有关 5G 的一切。

转载 https://www.qualcomm.com/5g/what-is-5g 在这里&#xff0c;您可以找到 5G 技术的解释——5G 的工作原理、5G 的重要性以及它如何改变世界连接和沟通的方式。在 Qualcomm&#xff0c;我们发明了使 5G 成为可能的根本性突破。 问&#xff1a;什么是 5G&#xff1f; 答&…...

【redis】初识redis入门,基础部署以及介绍

本站以分享各种运维经验和运维所需要的技能为主 《python零基础入门》&#xff1a;python零基础入门学习 《python运维脚本》&#xff1a; python运维脚本实践 《shell》&#xff1a;shell学习 《terraform》持续更新中&#xff1a;terraform_Aws学习零基础入门到最佳实战 《k8…...

数据库基础 -- 数据库约束

数据库基础 – 数据库约束 1.约束 1.1 概念 约束是用于强制数据库中数据 完整性 和 一致性 的规则。它们定义了对表中数据的限制&#xff0c;确保数据的有效性和正确性&#xff0c;实际上就是表中数据的限制条件。 1.2 分类 1.2.1 完整性约束 主键约束(Primary Key Const…...

U盘文件或目录损坏无法读取?专业恢复策略全解析

U盘困境&#xff1a;文件目录的隐形危机 在日常的数字生活中&#xff0c;U盘作为便捷的数据存储与传输工具&#xff0c;扮演着至关重要的角色。然而&#xff0c;当U盘中的文件或目录突然遭遇损坏&#xff0c;导致无法被正常读取时&#xff0c;这无疑给用户带来了极大的困扰。这…...

dpdk实现udp协议栈

使用DPDK实现UDP用户态协议栈&#xff0c;实现流程中包括&#xff1a; 三类线程 1、收发包线程 2、用户态协议栈线程 3、udp服务端线程 两类缓冲区&#xff1a; 1、协议栈收包缓冲区和协议栈发包缓冲区 2、udp收包缓冲区和udp发包缓冲区 协议栈缓冲区中存储的数据是str…...

Shell编程——基础语法(2)和 Shell流程控制

文章目录 基础语法&#xff08;2&#xff09;echo命令read命令printf命令test命令 Shell流程控制if-else语句for 循环while 语句until 循环case ... esac跳出循环 基础语法&#xff08;2&#xff09; echo命令 Shell 的 echo 指令与 PHP 的 echo 指令类似&#xff0c;都是用于…...

Python基础教程(二)字符串和函数

6.字符串 6.1 字符串的表示方式 6.1.1 普通字符串 普通字符串指用单引号()或双引号(”")括起来的字符串。例如:Hello或"Hello" >>> Hello Hello >>> "Hello" Hello >>> s\u0048\u0065\u006c\u006c\u006f >>> …...

智算新风向丨趋动科技获中国信通院泰尔实验室首张智算资源池化能力泰尔测评证书

近日&#xff0c;趋动科技“OrionX AI算力资源池化软件”经中国泰尔实验室依据《FG-Z14-0172-01智算资源池化平台测试方案》评估测试&#xff0c;获得智算资源池化能力泰尔测评证书&#xff0c;成为该领域首个完成此评价的产品。 图1.OrionX通过智算资源池化平台评测 随着AI大…...

计算机基础(Windows 10+Office 2016)教程 —— 第4章 计算机网络与Internet(上)

第4章 计算机网络与Internet 4.1 计算机网络概述4.1.1 计算机网络的定义4.1.2 计算机网络的发展4.1.3 计算机网络的功能4.1.4 计算机网络体系结构和TCP/IP 参考模型 4.2 计算机网络的组成和分类4.2.1 计算机网络的组成4.2.2 计算机网络的分类 4.3 网络传输介质和通信设备4.3.1 …...

MES系统在数字化转型中的核心作用与影响

数字化转型是企业利用数字技术改变其业务模式、运营方式、组织结构、产品服务等方面的过程&#xff0c;旨在提高效率、降低成本、增强竞争力并实现可持续发展。数字化转型涉及多个层面&#xff0c;主要包括以下几个方面&#xff1a; 数字化转型转什么 转战略&#xff1a;由构…...

装修施工注意事项

1 地漏保护 咋墙拆改时&#xff0c;一定要用保护盖把所有的地漏下水管道都拧紧 2 卫生间防水做完&#xff0c;必须要先用水泥砂浆做好保护层再贴&#xff0c;不然后续施工&#xff0c;不小心破坏防水层&#xff0c;以后漏水后悔都晚了。 3 入户门口处&#xff0c;一定要用…...

QMC5883L的驱动

简介 本篇文章的代码已经上传到了github上面&#xff0c;开源代码 作为一个电子罗盘模块&#xff0c;我们可以通过I2C从中获取偏航角yaw&#xff0c;相对于六轴陀螺仪的yaw&#xff0c;qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八

现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet&#xff0c;点击确认后如下提示 最终上报fail 解决方法 内核升级导致&#xff0c;需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指&#xff1a;像函数调用/返回一样轻量地完成任务切换。 举例说明&#xff1a; 当你在程序中写一个函数调用&#xff1a; funcA() 然后 funcA 执行完后返回&…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版​分享

平时用 iPhone 的时候&#xff0c;难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵&#xff0c;或者买了二手 iPhone 却被原来的 iCloud 账号锁住&#xff0c;这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...

页面渲染流程与性能优化

页面渲染流程与性能优化详解&#xff08;完整版&#xff09; 一、现代浏览器渲染流程&#xff08;详细说明&#xff09; 1. 构建DOM树 浏览器接收到HTML文档后&#xff0c;会逐步解析并构建DOM&#xff08;Document Object Model&#xff09;树。具体过程如下&#xff1a; (…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制

在数字化浪潮席卷全球的今天&#xff0c;数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具&#xff0c;在大规模数据获取中发挥着关键作用。然而&#xff0c;传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时&#xff0c;常出现数据质…...

C# 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列&#xff0c;以便知晓哪些列包含有价值的数据&#xff0c;…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

【JavaSE】多线程基础学习笔记

多线程基础 -线程相关概念 程序&#xff08;Program&#xff09; 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序&#xff0c;比如我们使用QQ&#xff0c;就启动了一个进程&#xff0c;操作系统就会为该进程分配内存…...