You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Web-Dev-For-Beginners/translations/nl/4-typing-game/typing-game/README.md

18 KiB

Een spel maken met behulp van events

Quiz voorafgaand aan de les

Quiz voorafgaand aan de les

Event-driven programmeren

Bij het maken van een browsergebaseerde applicatie bieden we een grafische gebruikersinterface (GUI) aan waarmee de gebruiker kan interageren met wat we hebben gebouwd. De meest gebruikelijke manier om met de browser te interageren is door te klikken en te typen in verschillende elementen. De uitdaging voor ons als ontwikkelaars is dat we niet weten wanneer ze deze acties gaan uitvoeren!

Event-driven programmeren is de naam voor het type programmeren dat we moeten gebruiken om onze GUI te maken. Als we deze term een beetje ontleden, zien we dat het kernwoord hier event is. Event, volgens Merriam-Webster, wordt gedefinieerd als "iets dat gebeurt". Dit beschrijft onze situatie perfect. We weten dat er iets gaat gebeuren waarvoor we code willen uitvoeren als reactie, maar we weten niet wanneer het zal plaatsvinden.

De manier waarop we een stuk code markeren dat we willen uitvoeren, is door een functie te maken. Als we denken aan procedureel programmeren, worden functies in een specifieke volgorde aangeroepen. Ditzelfde geldt voor event-driven programmeren. Het verschil zit in hoe de functies worden aangeroepen.

Om events te verwerken (knopklikken, typen, enz.), registreren we event listeners. Een event listener is een functie die luistert naar een event dat plaatsvindt en code uitvoert als reactie. Event listeners kunnen de UI bijwerken, serveraanroepen doen, of wat er ook nodig is als reactie op de actie van de gebruiker. We voegen een event listener toe met behulp van addEventListener en geven een functie op die moet worden uitgevoerd.

NOTE: Het is belangrijk om te benadrukken dat er verschillende manieren zijn om event listeners te maken. Je kunt anonieme functies gebruiken of benoemde functies maken. Je kunt verschillende snelkoppelingen gebruiken, zoals het instellen van de click-eigenschap of het gebruik van addEventListener. In onze oefening gaan we ons richten op addEventListener en anonieme functies, omdat dit waarschijnlijk de meest gebruikte techniek is onder webontwikkelaars. Het is ook de meest flexibele, omdat addEventListener werkt voor alle events en de eventnaam als parameter kan worden opgegeven.

Veelvoorkomende events

Er zijn tientallen events beschikbaar die je kunt gebruiken bij het maken van een applicatie. In principe roept alles wat een gebruiker op een pagina doet een event op, wat je veel mogelijkheden geeft om ervoor te zorgen dat ze de ervaring krijgen die je wenst. Gelukkig heb je meestal maar een klein aantal events nodig. Hier zijn een paar veelvoorkomende (inclusief de twee die we gaan gebruiken bij het maken van ons spel):

  • click: De gebruiker heeft ergens op geklikt, meestal een knop of hyperlink
  • contextmenu: De gebruiker heeft met de rechtermuisknop geklikt
  • select: De gebruiker heeft tekst gemarkeerd
  • input: De gebruiker heeft tekst ingevoerd

Het spel maken

We gaan een spel maken om te ontdekken hoe events werken in JavaScript. Ons spel zal de typevaardigheid van een speler testen, wat een van de meest onderschatte vaardigheden is die alle ontwikkelaars zouden moeten hebben. We zouden allemaal onze typevaardigheid moeten oefenen! De algemene flow van het spel ziet er als volgt uit:

  • De speler klikt op de startknop en krijgt een quote te zien om te typen
  • De speler typt de quote zo snel mogelijk in een tekstvak
    • Elke keer dat een woord is voltooid, wordt het volgende woord gemarkeerd
    • Als de speler een typefout maakt, wordt het tekstvak rood
    • Wanneer de speler de quote voltooit, wordt een succesbericht weergegeven met de verstreken tijd

Laten we ons spel bouwen en meer leren over events!

Bestandsstructuur

We hebben in totaal drie bestanden nodig: index.html, script.js en style.css. Laten we die opzetten om het onszelf wat makkelijker te maken.

  • Maak een nieuwe map voor je werk door een console- of terminalvenster te openen en het volgende commando uit te voeren:
# Linux or macOS
mkdir typing-game && cd typing-game

# Windows
md typing-game && cd typing-game
  • Open Visual Studio Code
code .
  • Voeg drie bestanden toe aan de map in Visual Studio Code met de volgende namen:
    • index.html
    • script.js
    • style.css

De gebruikersinterface maken

Als we de vereisten bekijken, weten we dat we een aantal elementen nodig hebben op onze HTML-pagina. Dit is een beetje zoals een recept, waarbij we enkele ingrediënten nodig hebben:

  • Een plek om de quote weer te geven die de gebruiker moet typen
  • Een plek om berichten weer te geven, zoals een succesbericht
  • Een tekstvak om te typen
  • Een startknop

Elk van deze elementen heeft ID's nodig zodat we ermee kunnen werken in onze JavaScript. We zullen ook verwijzingen toevoegen naar de CSS- en JavaScript-bestanden die we gaan maken.

Maak een nieuw bestand genaamd index.html. Voeg de volgende HTML toe:

<!-- inside index.html -->
<html>
<head>
  <title>Typing game</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <h1>Typing game!</h1>
  <p>Practice your typing skills with a quote from Sherlock Holmes. Click **start** to begin!</p>
  <p id="quote"></p> <!-- This will display our quote -->
  <p id="message"></p> <!-- This will display any status messages -->
  <div>
    <input type="text" aria-label="current word" id="typed-value" /> <!-- The textbox for typing -->
    <button type="button" id="start">Start</button> <!-- To start the game -->
  </div>
  <script src="script.js"></script>
</body>
</html>

De applicatie starten

Het is altijd het beste om iteratief te ontwikkelen om te zien hoe dingen eruitzien. Laten we onze applicatie starten. Er is een geweldige extensie voor Visual Studio Code genaamd Live Server die zowel je applicatie lokaal host als de browser ververst elke keer dat je opslaat.

  • Installeer Live Server door de link te volgen en op Install te klikken
    • Je wordt door de browser gevraagd om Visual Studio Code te openen, en vervolgens door Visual Studio Code om de installatie uit te voeren
    • Start Visual Studio Code opnieuw op als daarom wordt gevraagd
  • Zodra het is geïnstalleerd, klik je in Visual Studio Code op Ctrl-Shift-P (of Cmd-Shift-P) om de commandopalet te openen
  • Typ Live Server: Open with Live Server
    • Live Server begint je applicatie te hosten
  • Open een browser en navigeer naar https://localhost:5500
  • Je zou nu de pagina moeten zien die je hebt gemaakt!

Laten we wat functionaliteit toevoegen.

Voeg de CSS toe

Met onze HTML gemaakt, laten we de CSS toevoegen voor de kernstyling. We moeten het woord markeren dat de speler moet typen en het tekstvak kleuren als wat ze hebben getypt onjuist is. We doen dit met twee klassen.

Maak een nieuw bestand genaamd style.css en voeg de volgende syntax toe.

/* inside style.css */
.highlight {
  background-color: yellow;
}

.error {
  background-color: lightcoral;
  border: red;
}

Als het gaat om CSS kun je je pagina indelen zoals je wilt. Neem wat tijd om de pagina aantrekkelijker te maken:

  • Kies een ander lettertype
  • Geef de koppen een kleur
  • Pas de grootte van items aan

JavaScript

Met onze UI gemaakt, is het tijd om ons te richten op de JavaScript die de logica zal bieden. We gaan dit opsplitsen in een aantal stappen:

Maar eerst, maak een nieuw bestand genaamd script.js.

Voeg de constanten toe

We hebben een paar items nodig om het programmeren wat makkelijker te maken. Opnieuw, vergelijkbaar met een recept, hier is wat we nodig hebben:

  • Een array met de lijst van alle quotes
  • Een lege array om alle woorden van de huidige quote op te slaan
  • Een plek om de index van het woord dat de speler momenteel typt op te slaan
  • De tijd waarop de speler op start heeft geklikt

We willen ook verwijzingen naar de UI-elementen:

  • Het tekstvak (typed-value)
  • De quoteweergave (quote)
  • Het bericht (message)
// inside script.js
// all of our quotes
const quotes = [
    'When you have eliminated the impossible, whatever remains, however improbable, must be the truth.',
    'There is nothing more deceptive than an obvious fact.',
    'I ought to know by this time that when a fact appears to be opposed to a long train of deductions it invariably proves to be capable of bearing some other interpretation.',
    'I never make exceptions. An exception disproves the rule.',
    'What one man can invent another can discover.',
    'Nothing clears up a case so much as stating it to another person.',
    'Education never ends, Watson. It is a series of lessons, with the greatest for the last.',
];
// store the list of words and the index of the word the player is currently typing
let words = [];
let wordIndex = 0;
// the starting time
let startTime = Date.now();
// page elements
const quoteElement = document.getElementById('quote');
const messageElement = document.getElementById('message');
const typedValueElement = document.getElementById('typed-value');

Voeg meer quotes toe aan je spel

NOTE: We kunnen de elementen altijd ophalen in de code door document.getElementById te gebruiken. Omdat we regelmatig naar deze elementen gaan verwijzen, vermijden we typefouten met string literals door constanten te gebruiken. Frameworks zoals Vue.js of React kunnen je helpen bij het beter beheren van het centraliseren van je code.

Neem een minuut om een video te bekijken over het gebruik van const, let en var.

Soorten variabelen

🎥 Klik op de afbeelding hierboven voor een video over variabelen.

Voeg startlogica toe

Om het spel te beginnen, klikt de speler op start. Natuurlijk weten we niet wanneer ze op start gaan klikken. Dit is waar een event listener van pas komt. Een event listener stelt ons in staat om te luisteren naar iets dat gebeurt (een event) en code uit te voeren als reactie. In ons geval willen we code uitvoeren wanneer de gebruiker op start klikt.

Wanneer de gebruiker op start klikt, moeten we een quote selecteren, de gebruikersinterface instellen en de tracking voor het huidige woord en de timing instellen. Hieronder staat de JavaScript die je moet toevoegen; we bespreken het direct na het scriptblok.

// at the end of script.js
document.getElementById('start').addEventListener('click', () => {
  // get a quote
  const quoteIndex = Math.floor(Math.random() * quotes.length);
  const quote = quotes[quoteIndex];
  // Put the quote into an array of words
  words = quote.split(' ');
  // reset the word index for tracking
  wordIndex = 0;

  // UI updates
  // Create an array of span elements so we can set a class
  const spanWords = words.map(function(word) { return `<span>${word} </span>`});
  // Convert into string and set as innerHTML on quote display
  quoteElement.innerHTML = spanWords.join('');
  // Highlight the first word
  quoteElement.childNodes[0].className = 'highlight';
  // Clear any prior messages
  messageElement.innerText = '';

  // Setup the textbox
  // Clear the textbox
  typedValueElement.value = '';
  // set focus
  typedValueElement.focus();
  // set the event handler

  // Start the timer
  startTime = new Date().getTime();
});

Laten we de code opsplitsen!

  • Stel de woordtracking in
    • Door Math.floor en Math.random te gebruiken, kunnen we willekeurig een quote selecteren uit de quotes-array
    • We converteren de quote naar een array van words zodat we het woord kunnen volgen dat de speler momenteel typt
    • wordIndex wordt ingesteld op 0, omdat de speler begint met het eerste woord
  • Stel de UI in
    • Maak een array van spanWords, die elk woord bevat binnen een span-element
      • Dit stelt ons in staat om het woord op de weergave te markeren
    • join de array om een string te maken die we kunnen gebruiken om de innerHTML op quoteElement bij te werken
      • Dit toont de quote aan de speler
    • Stel de className van het eerste span-element in op highlight om het geel te markeren
    • Maak het messageElement schoon door innerText in te stellen op ''
  • Stel het tekstvak in
    • Wis de huidige value op typedValueElement
    • Stel de focus in op typedValueElement
  • Start de timer door getTime aan te roepen

Voeg typelogica toe

Terwijl de speler typt, wordt een input-event opgewekt. Deze event listener controleert of de speler het woord correct typt en behandelt de huidige status van het spel. Ga terug naar script.js en voeg de volgende code toe aan het einde. We zullen het daarna opsplitsen.

// at the end of script.js
typedValueElement.addEventListener('input', () => {
  // Get the current word
  const currentWord = words[wordIndex];
  // get the current value
  const typedValue = typedValueElement.value;

  if (typedValue === currentWord && wordIndex === words.length - 1) {
    // end of sentence
    // Display success
    const elapsedTime = new Date().getTime() - startTime;
    const message = `CONGRATULATIONS! You finished in ${elapsedTime / 1000} seconds.`;
    messageElement.innerText = message;
  } else if (typedValue.endsWith(' ') && typedValue.trim() === currentWord) {
    // end of word
    // clear the typedValueElement for the new word
    typedValueElement.value = '';
    // move to the next word
    wordIndex++;
    // reset the class name for all elements in quote
    for (const wordElement of quoteElement.childNodes) {
      wordElement.className = '';
    }
    // highlight the new word
    quoteElement.childNodes[wordIndex].className = 'highlight';
  } else if (currentWord.startsWith(typedValue)) {
    // currently correct
    // highlight the next word
    typedValueElement.className = '';
  } else {
    // error state
    typedValueElement.className = 'error';
  }
});

Laten we de code opsplitsen! We beginnen met het ophalen van het huidige woord en de waarde die de speler tot nu toe heeft getypt. Vervolgens hebben we een watervallogica, waarbij we controleren of de quote compleet is, het woord compleet is, het woord correct is, of (ten slotte) of er een fout is.

  • De quote is compleet, aangegeven door typedValue gelijk te zijn aan currentWord en wordIndex gelijk te zijn aan één minder dan de length van words
    • Bereken elapsedTime door startTime af te trekken van de huidige tijd
    • Deel elapsedTime door 1.000 om van milliseconden naar seconden te converteren
    • Toon een succesbericht
  • Het woord is compleet, aangegeven door typedValue te eindigen met een spatie (het einde van een woord) en typedValue gelijk te zijn aan currentWord
    • Stel value op typedElement in op '' om het volgende woord te kunnen typen
    • Verhoog wordIndex om naar het volgende woord te gaan
    • Loop door alle childNodes van quoteElement om className in te stellen op '' om terug te keren naar de standaardweergave
    • Stel className van het huidige woord in op highlight om het te markeren als het volgende woord om te typen
  • Het woord is momenteel correct getypt (maar niet compleet), aangegeven door currentWord te beginnen met typedValue
    • Zorg ervoor dat typedValueElement wordt weergegeven als standaard door className te wissen
  • Als we zover zijn gekomen, is er een fout
    • Stel className op typedValueElement in op error

Test je applicatie

Je bent aan het einde gekomen! De laatste stap is om ervoor te zorgen dat onze applicatie werkt. Probeer het uit! Maak je geen zorgen als er fouten zijn; alle ontwikkelaars hebben fouten. Onderzoek de berichten en debug indien nodig.

Klik op start en begin met typen! Het zou een beetje moeten lijken op de animatie die we eerder zagen.

Animatie van het spel in actie


🚀 Uitdaging

Voeg meer functionaliteit toe

  • Schakel de input-event listener uit bij voltooiing en schakel deze opnieuw in wanneer de knop wordt ingedrukt
  • Schakel het tekstvak uit wanneer de speler de quote voltooit
  • Toon een modaal dialoogvenster met het succesbericht
  • Sla topscores op met behulp van localStorage

Quiz na de les

Quiz na de les

Herhaling & Zelfstudie

Lees meer over alle beschikbare events voor ontwikkelaars via de webbrowser, en denk na over de scenario's waarin je elk event zou gebruiken.

Opdracht

Maak een nieuw toetsenbordspel


Disclaimer:
Dit document is vertaald met behulp van de AI-vertaalservice Co-op Translator. Hoewel we streven naar nauwkeurigheid, dient u zich ervan bewust te zijn dat geautomatiseerde vertalingen fouten of onnauwkeurigheden kunnen bevatten. Het originele document in de oorspronkelijke taal moet worden beschouwd als de gezaghebbende bron. Voor kritieke informatie wordt professionele menselijke vertaling aanbevolen. Wij zijn niet aansprakelijk voor misverstanden of verkeerde interpretaties die voortvloeien uit het gebruik van deze vertaling.