上周我们实通过前端基础实现了名言生成器,当然很多伙伴再评论区提出了想法,后续我们会考虑实现的,今天还是继续按照我们原定的节奏来带领大家完成一个打字通的小游戏,功能也比较简单简单,也是想借助这样一个简单的功能,然后来帮助大家了解我们JavaScript在前端中的作用, 在前面的文章当中我们也提及到我们在本系列的专栏是循序渐进从简单到复杂的过程,后续会带领大家用前端实现猜数字、翻卡片、扫雷、贪吃蛇等有趣的小游戏,纯前端语言实现,都会陆续带给大家。欢迎大家订阅我们这份前端小游戏的专栏。
我们中间白色区域就是我们文本域,用户可以在里面输入内容,我们点击开始按钮后我们下面的倒计时就会启动,这里我们是以60秒倒计时,与此同时上面的你准备好了吗?将变成我们的文案内容,我们需要照着文案内容再文本域中进行输入,倒计时结束后我们的我们上面将变成最终的得分,然后用户可以重新点击开始,又是同样的倒计时,当然我们可以自己规定规则,大家可以自己修改变成更棒的小游戏!下面我们就按照前面的思路先来实现一下吧!
创建文件
首先呢我们创建我们的HTML文件,这里我就直接命名为 打字通.html
了,大家可以随意命名, 文件创建生成后我们通过编辑器打开,这里我用的是VScode, 然后初始化我们的代码结构,那在这里告诉大家一个快捷键,就是我们敲上我们英文的一个 !
我们敲击回车直接就会给我们生成基础版本的前端代码结构。
搭建DOM结构
我们现在就可以再body中对着我们的效果图开始搭建我们的DOM结构了,首先的话,我们可以看到我们肯定是有一个大的盒子,我们就先来定义这个盒子我们设置类名就为bigBox
,然后我们上面的你准备好了吗?我们也放一个盒子我们设置类名为container
,盒子的下面是一个文本域,这个文本域我们前端可以使用 textarea
标签,标签中有一些属性,在下面我们可以看到我们用到了几个属性,首先placeholder
的作用是提示文字,我们可以看没有输入内容的时候看到开始输入…字样,我们style是设置样式这里我是通过resize:none
来禁止我们文本域的拖拽,大家可以先不设置这个属性然后感受一下我们文本域的右下角是有一个三角是可以对文本域进行拖拽的,这里呢我们禁止拖拽,为了保护我们后续的布局,这是我们的文本域,再往下面就是我们的按钮跟倒计时的内容,这里我们的首先添加一个盒子类名叫做operate
,然后盒子里面我们添加一个按钮跟一个类名叫做timer
的div,就是下面这些代码,我们可以保存代码然后看一下页面。
<div class="bigBox">
<div class="container">
你准备好了吗?
div>
<textarea name="" placeholder="开始输入..."
id="" style="resize:none" cols="30"
rows="10">textarea>
<div class="operate">
<button>开始button>
<div id="timer">60div>
div>
div>
大盒子样式
上面的框架我们已经搭建出来了,其实在我们的开发过程中我们是肯定搭建一个DOM元素然后就开始编写样式的,但是这里为了方便给大家展示我们只能先搭建完所有的元素统一来配置样式,首先呢我们还是一样在我们的head中添加style标签,在里面编写我们的样式代码,老规矩先为我们的body设置上margin: 0; padding: 0;font-family: Arial, sans-serif;
,内外边距都为0还有我们的字体;在我们的bigBox设置宽度50%,背景颜色,外边距上下为40px,然后水平居中,设置盒子模型为标准盒子,内边距为20px,边框圆角30px,然后盒子阴影,这个每个值什么意思我们再上篇文章中为大家讲解了,大家可以看一下;最后我们看一下效果
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
}
.bigBox {
width: 50%;
background-color: #ac8c3e;
margin: 40px auto;
box-sizing: border-box;
padding: 20px;
border-radius: 30px;
box-shadow: 0px 0px 30px 9px #939393;
}
盒子内部布局
为我们类名为container
的盒子也就是上面的你准备好了吗?盒子设置居中,然后通过text-align: center;
设置文字居中,内边距为20px,大家可以保存看一下效果;这里就不一一展示效果了,然后我们为中间的文本域,设置宽度100%,高度200px,外边距上下位20px左右为0,然后我们设置他的边框为none,不展示边框,下面就是文本域下面的区域,我们用了一个类名叫做operate
的盒子来包裹按钮跟倒计时,我们为这个盒子设置宽度为20%,然后水平居中,字体居中,继续设置里面的botton按钮,字体大小24px,内边距上下为10px,左右为20px,背景颜色为 #007bff
字体颜色白色,边框设置为none不展示,圆角为5px,在通过cursor: pointer;
鼠标悬浮为手状;最后在设置我们id为timer
的倒计时,字体大小为48px,然后外边距上下左右都是20px;保存代码我们看一下效果;
.container {
margin: 0 auto;
text-align: center;
padding: 20px;
}
textarea {
width: 100%;
height: 200px;
margin: 20px 0;
font-size: 20px;
border: none;
}
.operate {
width: 20%;
margin: 0 auto;
text-align: center;
}
button {
font-size: 24px;
padding: 10px 20px;
background-color: #007bff;
color: #fff;
border: none;
border-radius: 5px;
cursor: pointer;
}
#timer {
font-size: 48px;
margin: 20px;
}
那么代码写到这里呢,其实我们页面已经搭建完整了,但是我们的页面现在处于纯静态页面,也就是说仅仅用于展示, 现在还没有任何的效果,我们想要实现动态的一些交互效果就需要用到我们的JS来完成,下面呢我们就从几个方面来实现我们整体的效果;
获取所需元素和内容
首先呢我们知道点击开始之后,上面的你准备好了吗就要换成我们的范文,首先我们先声明变量来放我们的范文,我们声明变量text值就是我们的范文内容,这给大家找了一段英文的;我们还要通过document.querySelector
先获取我们的元素后面会使用;然后我们先为我们的文本域设置内容为空;
const text =
"Believe in yourself and all that you are. Know that there is something inside you that is greater than any obstacle. This quote by Christian D. Larson reminds us that we all have the power within us to overcome any obstacle we may face. When we have confidence in ourselves and our abilities, we can achieve great things. So, let's trust ourselves, believe in our dreams, and work hard to make them a reality.";
const container = document.querySelector(".container");
const input = document.querySelector("textarea");
const button = document.querySelector("button");
const timer = document.getElementById("timer");
input.value = "";
为按钮注册事件
通过addEventListener
为按钮注册时间,我们在函数中首先把倒计时设置为60秒,然后清空我们输入框和范文的内容,然后我们调用startGame
函数。
// 添加按钮点击事件监听器
button.addEventListener("click", () => {
// 设置倒计时时间
timer.textContent = "60";
// 清空输入框和输出文本区域
input.value = "";
container.textContent = "";
// 启动游戏
startGame();
});
启动游戏
上面的代码我们是通过点击按钮然后来用到我们下面的startGame
函数,我们在这个函数的前面的首先要声明一个变量countdown
用来承接定时器的销毁,在函数中首先呢我们要将按钮禁用,倒计时期间不能重复点击,然后我们将范文展示再我们的container
元素中,然后我们运用定时器setInterval
,第一参数是一个函数,第二个参数是隔多少秒,下面的意思就是每秒执行一次函数,在函数中我们首先获取到倒计时现在的数值,第一次这里肯定为60,然后这里我们申明常量remainingTime
来接受当前秒数-1,我们还有一个判断就是如果当前描述是0那么我们就执行endGame
函数,然后我们对描述进行赋值就完成了我们的倒计时效果;下面呢我们继续写endGame
函数。
let countdown;
function startGame () {
// 游戏开始后,禁用按钮
button.disabled = true;
// 显示文本
container.textContent = text;
// 启动倒计时
countdown = setInterval(() => {
const remainingTime = parseInt(timer.textContent) - 1;
if (remainingTime === 0) {
// 时间用完,游戏结束
endGame();
}
timer.textContent = remainingTime;
}, 1000);
}
暂停游戏
endGame
函数中我们首先就是停止倒计时,也就是销毁定时器,我们刚才说到了我们申明了一个变量用来承接定时器,这里的销魂我们就可以通过变量来;然后我们要计算得分,计算得分的函数呢我们下面讲解,首先这里你要知道计算得分的函数是调用后返回分数即可,然后我们将分数显示再范文区域,并且取消按钮的禁用;
function endGame () {
// 停止倒计时
clearInterval(countdown);
// 计算得分
const score = calculateScore();
const scoreMessage = `你的得分是 ${score} 分!`;
container.textContent = scoreMessage;
// 显示按钮和计时器
// button.style.display = "block";
// timer.style.display = "block";
button.disabled = false;
}
分数的计算
在上面我们结束游戏的函数中调用了计算分数的calculateScore
函数,在这个函数中我们需要按照规则生成分数并且返回,看下面首先我们将文本域、范文内容通过.trim()
移除两端的空格,并且赋值给变量,然后我们通过split
将所有内容按照空格进行拆分,然后我们进行循环每个单词进行一一对应如果相等则分数++,最后将分数return出去,调用的地方就可以直接拿到了。
function calculateScore () {
const userText = input.value.trim();
const correctText = text.trim();
const userWords = userText.split(" ");
const correctWords = correctText.split(" ");
let score = 0;
for (let i = 0; i < userWords.length; i++) {
console.log(userWords[i], correctWords[i])
if (userWords[i] === correctWords[i]) {
score++;
}
}
return score;
}
上面这些就是我们实现的整体思路跟代码,当然这里你完全可以按照自己的私聊来编写逻辑,上面也只是完成小小的功能,大家可以结合自己的想法编写,然后在这里呢有个小小的点,就是我是为了大家能够跟得上逻辑然后按照用户行为的先后顺序来介绍的,当然这样写也没有问题,但是还是建议大家函数要写在调用的前面,比如我们的启动游戏的函数是再按钮点击的时候调用的,那我们可以把启动游戏的函数代码写在点击事件的前面会更好以写;下面的完整代码也给到大家了哦!还有一点就是为了用户体验我们可以禁止用户复制,直接把范文复制到文本域好像不太好,我们可以再css代码的body中添以下代码;
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
-moz-user-select: none;
/*火狐*/
-webkit-user-select: none;
/*webkit浏览器*/
-ms-user-select: none;
/*IE10*/
-khtml-user-select: none;
/*早期浏览器*/
-o-user-select: none;
user-select: none;
}
完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
-moz-user-select: none;
/*火狐*/
-webkit-user-select: none;
/*webkit浏览器*/
-ms-user-select: none;
/*IE10*/
-khtml-user-select: none;
/*早期浏览器*/
-o-user-select: none;
user-select: none;
}
.bigBox {
width: 50%;
background-color: #ac8c3e;
margin: 40px auto;
box-sizing: border-box;
padding: 20px;
border-radius: 30px;
box-shadow: 0px 0px 30px 9px #939393;
}
.container {
margin: 0 auto;
text-align: center;
padding: 20px;
}
textarea {
width: 100%;
height: 200px;
margin: 20px 0;
font-size: 20px;
border: none;
}
.operate {
width: 20%;
margin: 0 auto;
text-align: center;
}
button {
font-size: 24px;
padding: 10px 20px;
background-color: #007bff;
color: #fff;
border: none;
border-radius: 5px;
cursor: pointer;
}
#timer {
font-size: 48px;
margin: 20px;
}
</style>
</head>
<body>
<div class="bigBox">
<div class="container">
你准备好了吗?
</div>
<textarea name="" placeholder="开始输入..." id="" style="resize:none" cols="30" rows="10"></textarea>
<div class="operate">
<button>开始</button>
<div id="timer">60</div>
</div>
</div>
<script>
const text =
"Believe in yourself and all that you are. Know that there is something inside you that is greater than any obstacle. This quote by Christian D. Larson reminds us that we all have the power within us to overcome any obstacle we may face. When we have confidence in ourselves and our abilities, we can achieve great things. So, let's trust ourselves, believe in our dreams, and work hard to make them a reality.";
const container = document.querySelector(".container");
const input = document.querySelector("textarea");
const button = document.querySelector("button");
const timer = document.getElementById("timer");
input.value = "";
let countdown;
function startGame () {
// 游戏开始后,禁用按钮
button.disabled = true;
// 显示文本
container.textContent = text;
// 启动倒计时
countdown = setInterval(() => {
const remainingTime = parseInt(timer.textContent) - 1;
if (remainingTime === 0) {
// 时间用完,游戏结束
endGame();
}
timer.textContent = remainingTime;
}, 1000);
}
function endGame () {
// 停止倒计时
clearInterval(countdown);
// 计算得分
const score = calculateScore();
const scoreMessage = `你的得分是 ${score} 分!`;
container.textContent = scoreMessage;
button.disabled = false;
}
function calculateScore () {
const userText = input.value.trim();
const correctText = text.trim();
const userWords = userText.split(" ");
const correctWords = correctText.split(" ");
let score = 0;
for (let i = 0; i < userWords.length; i++) {
console.log(userWords[i], correctWords[i])
if (userWords[i] === correctWords[i]) {
score++;
}
}
return score;
}
// 添加按钮点击事件监听器
button.addEventListener("click", () => {
// 设置倒计时时间
timer.textContent = "60";
// 清空输入框和输出文本区域
input.value = "";
container.textContent = "";
// 启动游戏
startGame();
});
</script>
</body>
</html>
本期推荐
✨ 原创不易,还希望各位大佬支持一下 \textcolor{blue}{原创不易,还希望各位大佬支持一下} 原创不易,还希望各位大佬支持一下
点赞,你的认可是我创作的动力! \textcolor{green}{点赞,你的认可是我创作的动力!} 点赞,你的认可是我创作的动力!
⭐️ 收藏,你的青睐是我努力的方向! \textcolor{green}{收藏,你的青睐是我努力的方向!} 收藏,你的青睐是我努力的方向!
✏️ 评论,你的意见是我进步的财富! \textcolor{green}{评论,你的意见是我进步的财富!} 评论,你的意见是我进步的财富!