打字软件带倒计时
Introduction In Part 1 - Create a Typing Speed Effect with VueJS We saw how to create a Typing Speed Effect. We are going to extend what we built previously, and include a timer and a score board, so that users can type and see the times they typed in faster.
简介在第1部分中-使用VueJS创建打字速度效果我们看到了如何创建打字速度效果。 我们将扩展以前构建的内容,包括一个计时器和一个计分板,以便用户可以更快地键入和查看输入时间。
In order to follow along, you must have read through part 1. Logic Since we already have the typing effect covered, we need to do the following.
为了继续学习,您必须已经阅读了第1部分 。 逻辑由于已经涵盖了打字效果,因此我们需要执行以下操作。
The Complete App will look something close to this. Here's a link to a deployed version: https://ganga.dev/vue-typer/
完整版应用程序看起来与此相似。 这是已部署版本的链接: https : //ganga.dev/vue-typer/
Project Setup Since this is a continuation from part 1, I created a repository that starts at the stage we left part 1 in.
项目设置由于这是第1部分的继续,因此我创建了一个存储库,该存储库从第1部分进入的阶段开始。
Clone this repository. https://github.com/gangachris/vue\-typer, and run the existing app.
克隆此存储库。 https://github.com/gangachris/vue\-typer ,然后运行现有的应用程序。
git clone https://github.com/gangachris/vue-typer
cd vue-typer
npm install
npm start
The repository has some slight modifications from where we left part 1. We now have a package.json, which installs httpster, and adds a start script npm start
to start the app.
该存储库从第1部分开始进行了一些修改。现在,我们有一个package.json,它安装了httpster ,并添加了一个启动脚本npm start
来启动该应用程序。
{
"name": "vuetyper",
"version": "1.0.0",
"main": "script.js",
"scripts": {
"start": "httpster"
},
"license": "MIT",
"devDependencies": {
"httpster": "^1.0.3"
}
}
At this point, after running npm start
, you should see the following in your browser when you visit localhost:3333
.
此时,运行npm start
,当您访问localhost:3333
时,应在浏览器中看到以下内容。
You can type in the text area to see the typing speed and typos effect. We explained how this was achieved in part 1 of this article. Timer UI We're going to add a digital timer, which is just a countdown. Let's add some html where the timer will be.
您可以在文本区域中键入以查看键入速度和错别字效果。 我们在本文的第1部分中解释了如何实现这一点。 计时器用户界面我们将添加一个数字计时器,这只是一个倒计时。 让我们在计时器所在的位置添加一些html。
First of all add some styling.
首先添加一些样式。
index.html
index.html
<html lang="en">
<head>
<style>
.timer {
font-size: 100px;
text-align: center;
color: white;
border-radius: 100;
background-color: green;
}
style>
head>
html>
The styles above adds a timer
which will style our timer div.
上面的样式添加了一个timer
,它将为我们的计时器div设置样式。
Next, let's add in the relevant html for the timer.
接下来,让我们为计时器添加相关的html。
index.html
index.html
<html lang="en">
<head>
head>
<body>
<div id="app"
class="container mt-2">
<h1>{{ title }}h1>
<div class="row">
<div class="col-8">
<div class="typer mt-3">
div>
div>
<div class="col-4">
<div class="timer">
60
div>
div>
div>
div>
body>
html>
We've added a 我们添加了一个 Let's add the countdown logic. 让我们添加倒数逻辑。 We'll start by adding a state variable called 我们将从添加一个名为 script.js script.js Next bind the timer to the html. 接下来将计时器绑定到html。 Next, we'll use the JavaScript function setInterval, which allows us to run a function at intervals. 接下来,我们将使用JavaScript函数setInterval ,它使我们能够定期运行一个函数。 The setInterval() method of the WindowOrWorkerGlobalScope mixin repeatedly calls a function or executes a code snippet, with a fixed time delay between each call. It returns an interval ID which uniquely identifies the interval, so you can remove it later by calling clearInterval(). This method is offered on the Window and Worker interfaces. WindowOrWorkerGlobalScope mixin的setInterval()方法重复调用函数或执行代码段,每次调用之间有固定的时间延迟。 它返回一个唯一标识该间隔的间隔ID,因此您以后可以通过调用clearInterval()将其删除。 在Window和Worker界面上提供此方法。 script.js script.js We have three methods. 我们有三种方法。 We can now trigger the timer to start when we start typing. To do this, we'll add another state variable called 现在,我们可以在开始打字时触发计时器开始计时。 为此,我们将添加另一个名为 NOTE While making this, I ran into a bug that seasonal javascript developers might be aware of. If you look at this part of the code. 注意进行此操作时,我遇到了一个季节性JavaScript开发人员可能会意识到的错误。 如果您看一下这部分代码。 Notice we have a the main function 注意,我们有一个主要函数 There are two ways to solve this problem. 有两种方法可以解决此问题。 This is from Mozilla Developer Network on arrow functions 这是来自Mozilla开发人员网络上的箭头功能 An arrow function does not have its own this; the this value of the enclosing execution context is used. Thus, in the following code, the this within the function that is passed to setInterval has the same value as this in the enclosing function: 箭头函数没有它自己的; 使用封闭执行上下文的this值。 因此,在以下代码中,传递给setInterval的函数中的this与封闭函数中的this具有相同的值: I decide to go with arrow functions. This is the new script.js 我决定使用箭头功能。 这是新的script.js I've made comments on every new thing changed in the codebase. 我已经对代码库中发生的每项新变化发表了评论。 Another change that needs to be explained is addition of another state variable 需要说明的另一个更改是添加了另一个状态变量 If we run the app again, and start typing, we'll see the timer counting down. 如果我们再次运行该应用程序并开始输入,我们将看到计时器递减计数。 The final step here is to add a reset button, so that a user can start a bew session. The logic for this has already been implemented in the 这里的最后一步是添加一个重置按钮,以便用户可以启动bew会话。 So we only need to add in the button. Let's add it on top of the timer. 所以我们只需要添加按钮。 让我们将其添加到计时器顶部。 index.html index.html VueJS uses VueJS使用 The page should now look like below 该页面现在应如下所示 You can start typing, and test it out. Score Board UI Since the idea is that you can type as many times as you want, we're adding in a score board. 您可以开始输入并进行测试。 记分板用户界面由于想法是您可以输入任意多次,因此我们添加了一个记分板。 Add the following html, below the timer div. 在timer div下面添加以下html。 The page should now look like this. Forgive my design skills ;-) 该页面现在应如下所示。 原谅我的设计技巧;-) Here's the logic for the Score Board. 这是计分板的逻辑。 First of all, let's add in a score state variable, and a typos state variable, since we will be counting typos, which will be an array. 首先,让我们添加一个得分状态变量和一个错别字状态变量,因为我们将要计算错别字,它是一个数组。 Next, let's count the typos in the 接下来,让我们计算 Withing the loop, when we find a typo we increase the typo value by one. 随着循环的进行,当我们发现错字时,我们会将错字值增加一。 Next, We'll get the total number of correct values typed. The logic here is to get the 接下来,我们将获得键入的正确值的总数。 这里的逻辑是获取 We get the correctly typed text by taking a substring of the original text, and the typo index, then we spit it by spaces to get the words with split method for javascript strings. If we do not have a typo, then we take the existing typed in text. 我们通过获取原始文本的子字符串和错字索引来获得正确键入的文本,然后将其吐入空格以使用split方法获取用于javascript字符串的单词。 如果我们没有错字,那么我们将使用现有的键入文本。 We then just do a count, and create a score object, which we push into the existing scores state variable. 然后,我们只做一个计数,并创建一个得分对象,将其推入现有的得分状态变量中。 Next, add this function after the endTypingSpeed function is called, within the startTimer function. 接下来,在startTimer函数内调用endTypingSpeed函数后添加此函数。 We now have to display the typing speed result on the score board. We do this by using a 现在,我们必须在记分板上显示打字速度结果。 我们通过使用如下所示的 vue的 Run the app, and type in a few times, you should see the results. 运行该应用程序,然后输入几次,您应该会看到结果。 The last step for this article is to sort/rank the results in the score board. We'll do this again using computed properties, so that the logic is clear. Add a computed property to the VueJS instance 本文的最后一步是在计分板上对结果进行排序/排名。 我们将使用计算属性再次进行此操作,以使逻辑清晰。 将计算的属性添加到VueJS实例 Then replace the 然后替换html中的 The app should be running well if you check it in the browsers. Bugs/Cheats Like any other game out there, there are a couple of ways people can cheat the game. Here are a few: 如果在浏览器中检查该应用程序,则该应用程序应运行良好。 错误/作弊就像其他任何游戏一样,人们可以通过多种方式欺骗游戏。 这里有一些: We are not really worried about this, because it's intended to run on a local machine. Can you think of ways to stop this, and leave a comment. Conclusion VueJS brings with it the purity of vanilla javascript and a bit of helpful tools. You can see that apart from the bindings, most of the code written is pure Javascript, with line by line thinking. 我们并不对此感到真正担心,因为它旨在在本地计算机上运行。 您能想到阻止这种情况的方法,并发表评论吗? 结束语VueJS带来了纯正的javascript JavaScript和一些有用的工具。 您可以看到,除了绑定之外,大多数编写的代码都是纯Javascript,而且是逐行思考的。 The full code can be found in the complete branch of the repository. 完整的代码可以在存储库的完整分支中找到。 I hope you enjoyed this, and Happy Coding. 希望您喜欢这个,并祝您编码愉快。 翻译自: https://scotch.io/tutorials/create-a-typing-speed-effect-with-vuejs-part-2-timer-and-score-board361 打字软件带倒计时div
that has the paragraph and the typing effect. We've also added the the class that we added earlier: .timer
. Refreshing the page should on the browser show this.
div
具有段落和打字的效果。 我们还添加了之前添加的类: .timer
。 刷新页面应在浏览器上显示出来。
倒计时器 ( Countdown Timer )
timer
.timer
的状态变量开始。 new Vue({
el: '#app',
data: {
title: 'Vue Typer',
originalText: PARAGRAPH,
typedText: '',
typoIndex: -1,
timer: 60 // add timer state variable
}
})
/// code commented out for brevity
<div class="col-4">
<div class="timer">
{{timer}}
div>
div>
// code commented out for brevity
new Vue({
el: '#app',
// code commented out for brevity
methods: {
startTypingSpeed: function () {
// start the typing speed
},
startTimer: function () {
setInterval(function () {
if (this.timer === 0) {
this.endTypingSpeed()
return;
}
this.timer--
}, 1000)
},
endTypingSpeed: function () {
// end the typing speed
},
reset: function() {
// reset everything
}
}
})
startTypingSpeed
: will be used to start the typing speed startTypingSpeed
:将用于启动打字速度 startTimer
: will be used to start the timer startTimer
:将用于启动计时器 endTypingSpeed
: will be used to end the typing speed endTypingSpeed
:将用于结束打字速度 typing
which is a boolean representing whether we have started typing.typing
状态变量,它是一个布尔值,表示我们是否已开始键入。 new Vue({
el: '#app',
data: {
// code commented out for brevity
typing: false
}
})
/// code commented out for brevity
startTimer: function () {
setInterval(function () {
if (this.timer === 0) {
this.endTypingSpeed()
return;
}
this.timer--
}, 1000)
},
startTimer
, and another function inside the setInterval
. This means that the second function creates it's own this
variable, and therefore replaces the VueJS instance this
.startTimer
,以及另一个在setInterval
内部的函数。 这意味着第二个函数创建了它自己的this
变量,因此替换了VueJS实例this
。
var self = this
- this allows us to save the Vue instance this into a new variable, and since objects are passed by reference in JavaScript, everything will work fine. 使用var self = this
this-这使我们可以将Vue实例保存到新变量中,并且由于对象是通过JavaScript中的引用传递的,因此一切正常。
function Person(){
this.age = 0;
setInterval(() => {
this.age++; // |this| properly refers to the Person object
}, 1000);
}
var p = new Person();
const PARAGRAPH = "..."
new Vue({
el: '#app',
data: {
// code commented out for brevity
typing: false,
timerInterval: {} // new timerInterval state variable to allow clearInterval
},
methods: {
// we start the typing speed here by changing typing to true
// and starting the timer
startTypingSpeed: function() {
this.typing = true
this.startTimer()
},
startTimer: function() {
// replace the timer function to use arrow functions
// because arrow functions use a `this` that belongs to the
// context wrapping it.
this.timerInterval = setInterval(() => {
if (this.timer === 0) {
this.endTypingSpeed()
return
}
this.timer--
}, 1000)
},
endTypingSpeed: function() {
// end the typing speed
// change typing back to false and
// blur the typing area
clearInterval(this.timerInterval);
this.typing = false;
this.timer = 60;
document.activeElement.blur();
},
reset: function() {
// reset everything
clearInterval(this.timerInterval);
this.typing = false;
this.typoIndex = -1;
this.typedText = '';
this.timer = 60;
}
},
computed: {
outputHTML: function() {
// code commented out for brevity
}
},
watch: {
typedText: function(value) {
// check if already typing, else start the timer.
if (!this.typing) {
this.startTypingSpeed()
}
for (let i = 0; i < value.length; i++) {
if (value[i] !== this.originalText[i]) {
this.typoIndex = i;
break;
}
this.typoIndex = -1;
}
}
}
});
timerInterval
. This is then assigned the setInterval
function value. The reason for this is so that at the end we can use clearInterval to stop the interval function from running forever.timerInterval
。 然后setInterval
分配setInterval
函数值。 这样做的原因是,最后我们可以使用clearInterval来阻止interval函数永远运行。 reset
function.reset
功能中已实现了此逻辑。 reset: function() {
// reset everything
clearInterval(this.timerInterval);
this.typing = false;
this.typoIndex = -1;
this.typedText = '';
this.timer = 60;
}
<div class="col-4">
<button class="btn btn-primary btn-block" @click="reset()">Resetbutton>
<div class="timer mt-3">
{{ timer }}
div>
div>
v-on
directive to register events. It has a short hand @
which can be used too, and that is what we've used here. The rest is standard CSS buttons.v-on
指令注册事件。 它有一个简写@
,也可以使用,这就是我们在这里使用的。 其余的是标准CSS按钮。 <div class="scoreboard mt-3">
<h2>Scoreboardh2>
<div class="scores">
<div class="alert-info mt-2">1. 20 WPM, 45 Typos div>
<div class="alert-info mt-2">2. 20 WPM, 45 Typos div>
<div class="alert-info mt-2">3. 20 WPM, 45 Typos div>
div>
div>
计分板逻辑 ( Score Board Logic )
new Vue({
el: '#app',
data: {
// code commented out for brevity
typos: 0,
scores: []
}
})
typedText
watcher.typedText
监视程序中的错别字。 // code commented out for brevity
watch: {
typedText: function(value) {
if (!this.typing) {
this.startTypingSpeed();
}
for (let i = 0; i < value.length; i++) {
if (value++[++i] !== this.originalText++[++i]) {
this.typoIndex = i;
this.typos++; // increase the typo count
break;
}
this.typoIndex = -1;
}
}
}
// code commented out for brevity
typoIndex
and use that to calculate the number of correct words typed. We'll add in a method called calculateScore
. Add this under the methods property of the VueJS instance.typoIndex
并使用它来计算输入的正确单词的数量。 我们将添加一个名为calculateScore
的方法。 将其添加到VueJS实例的methods属性下。 calculateScore: function() {
let score = {};
let correctlyTypedText = this.typedText
if (this.typoIndex != -1) {
correctlyTypedText = this.originalText.substring(0, this.typoIndex);
}
let words = correctlyTypedText.split(' ').length;
score = {
wpm: words,
typos: this.typos
};
// reset typos
this.typos = 0;
this.scores.push(score);
}
this.scores
. Remember to reset the typos back to 0.this.scores
。 记住将错别字重设为0。 startTimer: function() {
this.timerInterval = setInterval(() => {
if (this.timer === 0) {
this.endTypingSpeed();
this.calculateScore(); // calculate the typing speed
return;
}
this.timer--;
}, 1000);
},
v-for
directive like shown below.v-for
指令来做到这一点。 <div class="scoreboard mt-3">
<h2>Scoreboardh2>
<div class="scores">
<div class="alert-info mt-2"
v-for="(score, index) in scores">{{index + 1}}. {{score.wpm}} WPM, {{score.typos}} Typos div>
div>
div>
v-for
directive for vue allows us to loop over lists, and can take the form of v-for="item in items"
, or v-for="(item, index) in items"
when we need to access the indices.v-for
指令允许我们遍历列表,并v-for="(item, index) in items"
需要访问索引时可以采用v-for="item in items"
,或v-for="(item, index) in items"
的形式。 // code commented out for brevity
computed: {
outputHTML: function() {
// code commented out for brevity
},
sortedScores: function() {
return this.scores.sort((a, b) => {
return a.wpm + a.typos - (b.wpm + b.typos);
});
}
},
// code commented out for brevity
scores
list in the html to use sortedScores
scores
列表以使用sortedScores
<div class="alert-info mt-2"
v-for="(score, index) in sortedScores">{{index + 1}}. {{score.wpm}} WPM, {{score.typos}} Typos div>