5.1.3 键盘指法练习器
在本节中,我们实现一个复杂且很实用的Web应用—键盘指法练习器。这个Web应用的基本功能就是帮用户练习指法。从页面上方不断向下方随机移动各种颜色的字母,然后用户根据这些字母按键盘上的按键,如果按键恰好与屏幕上正在移动的字母相同,那么该字母就会消失,更好的效果是做一些特效,以及配上音乐。
这个Web应用还是比较复杂的,难点是如何用文字将这个Web应用的功能描述清楚。这个描述的关键点如下。
· 页面上有多个随机字母,移动方向从屏幕上方到下方,直至消失。
· 字母使用不同的随机颜色。
· 字母要快速从页面顶端移动到底端,移动要快,否则就起不到练习指法的目的,可以通过规定移动的最大时长来解决这个问题。
· 页面同时存在的字母不能太多,否则看着太乱了,不知道该敲击哪一个按键。
· 页面接收按键动作,如果按的键与当前页面上显示的字母相同,则该字母消失,并配有音效。
· 页面左上角是计分系统,每消失一个字母计分加1。这个功能不是必需的,但可以增加Web应用的趣味性。
·随着时间的推移,新产生的字母向下移动的速度会越来越快。增加这个功能是让键盘指法练习器更具有可玩性,玩的时间越久,难度越大。
根据上面的这些关键点,可以写出如下文本,并提交给ChatGPT。
使用HTML、CSS、JavaScript等实现键盘指法练习器的代码,页面背景色是黑色。屏幕上有多个不断快速移动的、随机出现的字母,移动方向从屏幕上方到下方,直至消失。字母要用不同的随机颜色,从页面顶端移动到底端的时间不能超过8秒,而且页面同时存在的字母不能超过10个。页面接收按键,如果用户按的键正好与当前页面上显示的字母相同,则该字母会消失,并配有音效,页面左上角是计分系统,每消失一个字母,计分加1。随着时间的推移,字母向下移动的速度会越来越快,随机产生的字母和已经存在的字母都是匀速运动的。将CSS和JavaScript代码都放到.html文件中,给出完整的实现代码和中文注释。
ChatGPT会回复如下代码。
代码位置:src/web/keyboard-practice.html
<!DOCTYPE html>
<html>
<head>
<title>键盘指法练习器</title>
<style>
/* 设置页面背景色为黑色 */
body {
background-color: black;
margin: 0;
padding: 0;
}
/* 设置字母的样式 */
.letter {
position: absolute;
font-size: 24px;
font-weight: bold;
user-select: none;
}
/* 设置计分系统样式 */
#score {
color: white;
font-size: 18px;
font-weight: bold;
position: fixed;
top: 10px;
left: 10px;
}
</style>
</head>
<body>
<!-- 计分系统 -->
<div id="score">得分: 0</div>
<script>
// 存储当前得分和已存在的字母数量
let score = 0;
let letterCount = 0;
// 获取页面宽度和高度
const pageWidth = window.innerWidth;
const pageHeight = window.innerHeight;
// 创建字母元素并设置初始样式
function createLetter() {
// 生成随机字母
const letter = String.fromCharCode(65 + Math.floor(Math.random() * 26));
// 创建字母元素
const letterElement = document.createElement('div');
letterElement.className = 'letter';
letterElement.innerText = letter;
// 随机设置字母的位置和颜色
const x = Math.random() * (pageWidth - 50);
const y = 0;
const color = getRandomColor();
letterElement.style.left = x + 'px';
letterElement.style.top = y + 'px';
letterElement.style.color = color;
// 将字母添加到页面中
document.body.appendChild(letterElement);
// 字母下落动画
animateLetter(letterElement);
}
// 生成随机颜色
function getRandomColor() {
const letters = '0123456789ABCDEF';
let color = '#';
for (let i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
// 字母下落动画
function animateLetter(letterElement) {
let top = 0;
const speed = Math.random() * 2 + 1; // 设置字母下落速度
// 更新字母位置
function update() {
top += speed;
letterElement.style.top = top + 'px';
// 如果字母超出页面底部,移除字母元素并减少字母数量
if (top > pageHeight) {
document.body.removeChild(letterElement);
letterCount--;
}
}
// 使用 requestAnimationFrame()更新字母位置,实现平滑动画
function step() {
update();
// 判断是否还存在字母,存在则继续更新位置
if (letterCount > 0) {
requestAnimationFrame(step);
}
}
requestAnimationFrame(step);
}
// 监听键盘按键事件
document.addEventListener('keydown', function (event) {
const keyPressed = String.fromCharCode(event.keyCode);
// 遍历页面上的字母元素,与按下的键进行比较
const letters = document.getElementsByClassName('letter');
for (let i = 0; i < letters.length; i++) {
const letterElement = letters[i];
const letter = letterElement.innerText;
// 如果按下的键与字母相同,移除字母元素,增加得分,并更新计分系统
if (keyPressed === letter) {
document.body.removeChild(letterElement);
letterCount--;
score++;
document.getElementById('score').innerText = '得分: ' + score;
playSound(); // 播放音效
break;
}
}
});
// 播放音效
function playSound() {
// 在这里添加你自己的音效播放代码
// 例如:使用 HTML5 <audio> 元素或 Web Audio API
}
// 定时生成新的字母
setInterval(function () {
if (letterCount < 10) {
createLetter();
letterCount++;
}
}, 1000);
// 每隔一段时间加快字母下落速度
setInterval(function () {
const letters = document.getElementsByClassName('letter');
for (let i = 0; i < letters.length; i++) {
const letterElement = letters[i];
const currentTop = parseInt(letterElement.style.top, 10);
letterElement.style.top = (currentTop + 10) + 'px';
}
}, 2000);
</script>
</body>
</html>
下面是对键盘指法练习器的实现原理的详细讲解。
· 在页面布局和样式方面,设置页面背景色为黑色,通过CSS样式对字母和计分系统进行样式设置。
· 在字母的生成和移动方面,使用createLetter()函数生成随机字母的HTML元素,并设置其样式;使用animateLetter()函数实现字母的下落动画效果。
· 在字母消失和得分增加方面,如果按下的键与字母相同,则移除字母元素、增加得分,并更新计分系统的显示。
· 在新字母的生成和下落速度递增方面,使用定时器定时生成新的字母,控制页面上同时存在的字母数量,通过定时器逐渐加快页面上已存在字母的下落速度。
· 通过以上操作,实现了键盘指法练习器,其中页面背景色为黑色,页面上有快速移动的随机字母,按对应键消除字母并增加得分,随着时间的推移字母下落速度递增。
· 这段代码已经可以实现键盘指法练习器的基本功能,但有如下两个效果没有实现:
· 字母消失时的音效;
·字母消失时的特效。
现在使用GitHub Copilot对这段代码进行微调。
1.字母消失时的音效
这个功能在描述中提到过,不过ChatGPT只给了一个playSound()函数,并没有具体的代码,可以在该函数中输入如下注释。
// 使用JavaScript播放MP3
不断按Enter键和Tab键后,GitHub Copilot会自动生成使用Audio对象播放MP3文件的代码,我们需要将MP3文件改成自己机器上存在的MP3文件。
var audio = new Audio();
audio.src = "../slice_sound.mp3";
audio.play();
2.字母消失时的特效
这个要求在描述文字中完全就没提,不过我们可以自己实现这个特效。当然,还使用GitHub Copilot。我们可以做一个简单的特效,就是要消除某一个字母之前,先将字母放大,然后再让字母消失,并且配有音效。
在上面的代码中找到如下代码。
if (keyPressed === letter) {
document.body.removeChild(letterElement);
letterCount--;
score++;
document.getElementById('score').innerText = '得分: ' + score;
playSound(); // 播放音效
break;
}
在if语句下面一行中,输入如下注释。
// 先将字母的尺寸放大,然后再移除字母元素
不断按Enter键和Tab键(可能需要按多次),会生成使用setTimeout()函数延迟消除的代码,然后将if语句中的代码全部移到setTimeout()的回调函数中,会得到如下代码。
if (keyPressed === letter) {
// 先将字母的尺寸放大,然后再移除字母元素
letterElement.style.fontSize = '80px';
setTimeout(function () {
document.body.removeChild(letterElement);
letterCount--;
score++;
document.getElementById('score').innerText = '得分: ' + score;
playSound(); // 播放音效
}, 100);
}
在浏览器中打开keyboard-practice.html文件,并且根据下落的字母按对应的键。如果按下的键与正在下落的字母相同,就先将正在下落的字母放大,100ms后,下落的字母就会被移除,如图5-3所示。
图5-3 键盘指法练习器