Construct English dictation App for learners with JavaScript and Vue
We will create a web application for English learners to do dictation.
code
See the Pen English Dictation App by Masato Takamaru (@masato-takamaru) on CodePen.
You can click on an English sentence to hear it as audio.
<html>
<head>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
</html>
const en = "In recent years, governments around the world have been working to raise awareness about oral health. While many people have heard their teeth multiple times per day is a good habit, they most likely have not considered the reasons why this is crucial."
const RootComponent = {
data () { return {
sentence: en,
text: setData(), //initialization
p: [], //correct and incorrect
showBackward: true, //show/hide the Back to previous button
message: '' //response
}},
template: `
<p>Click the sentence, and you can listen to it:</p>
<div @click="speak(sentence)">
<p>
<span v-for="word in text.words">
{{word+" "}}
</span>
</p>
</div>
<div>
<button
v-for="(option, index) in text.opt"
v-show="text.optShow[index]"
@click="input(index)">
{{option}}
</button>
</div>
<button v-show="showBackward" @click="backward">Back to previous</button>
<div>{{message}}</div>`,
methods: {
input(index) {
this.text.optShow[index] = false; //Hide the pressed button.
//Replace the masked underline with the word you chose from the choices.
this.text.words[this.text.mask[this.p.length]] = this.text.opt[index];
this.text.record.push(index); //Record the number of the button pressed.
//If the string of the choice matches the that of the text, the answer is correct.
if(this.text.optMask[index] == this.text.mask[this.p.length]) {
//Add the string 'correct' to the array if it is correct
this.p.push('correct');
} else {
//If the answer is incorrect, add the string 'incorrect' to the array
this.p.push('incorrect');
}
if(this.p.length == this.text.mask.length) {
this.showBackward = false; //Hide the "Back to previous" button.
//Check if all elements of an array are correct.
if(this.p.every(value => value == 'correct')) {
this.message = 'All correct';
} else {
this.message = 'There are some errors.';
}
}
},
speak(elem) {
speechSynthesis.cancel(); //Cancel any audio that is playing.
let uttr = new SpeechSynthesisUtterance(); //instance
const voices = speechSynthesis.getVoices(); //Retrieving the voice list
let voice;
voices.forEach((elem) => {
if(elem.name == 'Google US English') voice = elem;
});
uttr.voice = voice; //Women's Voices
uttr.volume = 1.0; //Volume
uttr.rate = 0.8; //Reading speed
uttr.pitch = 1.05; //pitch
uttr.lang = 'en-US'; //language
uttr.text = elem; //text
speechSynthesis.speak(uttr); //play
},
backward() {
if(this.p.length > 0) {
//Delete the last element of the array and go back one.
this.p.pop();
//Restore underlined words as they are entered
this.text.words[this.text.mask[this.p.length]] = ' ____ ';
//Show the button again.
this.text.optShow[this.text.record.pop()] = true;
}
}
},
mounted() {
const uttr = new SpeechSynthesisUtterance();
const voices = window.speechSynthesis.getVoices();
}
}
function setData() {
let obj = {
words: en.split(' '), //Split the text into words.
record: [], //Record the order in which buttons are pressed.
mask: [], //Position of the word to mask
opt: [], //strings of buttons
optMask: [], //Position of the word the choice represents
optShow: [] //Show/hide buttons
}
let n = Array.from(Array(obj.words.length).keys()); //Array of sequential numbers
//shuffle
for(let i = 0; i < 100; i++) {
let a = Math.floor(Math.random() * n.length);
let b = Math.floor(Math.random() * n.length);
[n[a], n[b]] = [n[b], n[a]];
}
//Number of words to mask: 1 word + 25% of the total
let amount = 1 + Math.round(obj.words.length * 0.15);
for(let i = 0; i < amount; i++) {
obj.mask.push(n[i]); //Add the position of the word to be masked
obj.opt.push(obj.words[n[i]]); //Add a string of choices.
obj.optMask.push(n[i]); //Add the position of the word the choice represents
obj.optShow.push('true'); //Add button display
}
obj.mask.sort((a, b) => a - b);
//Replace masked words with underlines
for(let i = 0; i < obj.opt.length; i++) {
obj.words[obj.mask[i]] = ' ____ ';
}
return obj;
}
const app = Vue.createApp(RootComponent);
app.mount('#root');
Initially, execute the instance of speechsynthesis with mounted()
. This is because the first getvoice()
will fail. When you run getvoice()
for the first time, you will get an empty array.
Words in a sentence have a 15% chance of being masked. The masked words will be displayed as buttons, and pressing them will replace the underlined words.
When you press the “back to previous” button, you will be taken back to the previous state. The buttons you press are recorded and the information is used to return to the previous state.
SNSでシェア