Webbteknik 2

Laboration 5A

Tid och tidtagning

I webbutveckling är tid en viktig faktor. Vi kanske vill visa ett meddelande efter några sekunder, uppdatera en klocka varje sekund, eller mäta hur snabbt användaren klickar på en knapp. JavaScript har inbyggda funktioner för allt detta.

0 - Förberedelser

Skapa en ny mapp lab-5a.

  1. Skapa index.html och script.js.
  2. Länka in scriptet i HTML-filen.

1 - Fördröjning med setTimeout

Funktionen setTimeout används för att köra en given funktion en gång efter en viss tid.

  1. I index.html, skapa en knapp “Starta timer” och en paragraf med id=“message” (<p id="message"></p>) för meddelanden.
  2. I script.js, koppla en klick-lyssnare till knappen.
  3. I lyssnaren, indikera att timern är igång, starta den sedan genom att anropa setTimeout på följande sätt:
    1. Skriv ut “Väntar…” eller liknande i meddelandelementet (använd exempelvis msg.textContent).
    2. Anropa setTimeout. Den tar två argument: en funktion som ska köras, och tiden i millisekunder.
    3. Låt funktionen skriva ut “3 sekunder har gått!” i p-elementet efter 3000 ms.

Förslag på lösning HTML:

<button id="start-timer">Starta timer</button>
<p id="message"></p>

javascript:

const btn = document.getElementById("start-timer");
const msg = document.getElementById("message");

btn.addEventListener("click", function() {
  msg.textContent = "Väntar...";
  setTimeout(function() {
    msg.textContent = "3 sekunder har gått!";
  }, 3000);
});

Testa själv:

  • Vad händer om du klickar på knappen igen, efter tiden gått ut?
  • Vad händer om du klickar på knappen igen, innan tiden gått ut?
    • Tips: Lägg till console.log('Timer startad') i lyssnaren, och console.log('Timer klar') i funktionen för att verkligen kunna följa vad som händer.

2 - Upprepa med setInterval

Funktionen setInterval liknar setTimeout, men den kör funktionen om och om igen med det angivna intervallet.

  1. Skapa en ny knapp i html, “Starta intervall”.
  2. I script.js, koppla en click-lyssnare till knappen.
  3. I lyssnaren, indikera att timern är igång, starta den sedan genom att anropa setInterval på följande sätt:
    1. Skriv ut “Väntar: ” eller liknande i meddelandelementet.
    2. Anropa setInterval. Den tar två argument, precis som setTimeout: en funktion som ska köras, och tiden i millisekunder.
    3. Låt funktionen Lägga till ett “x” i textContent på meddelande-elementet varje sekund (1000 ms).

Förslag på lösning HTML:

<button id="start-interval">Starta intervall</button>

javascript:

const btnInterval = document.querySelector("#start-interval");

btnInterval.addEventListener("click", function() {
  msg.textContent = "Väntar: ";
  setInterval(function() {
    msg.textContent += "x";
  }, 1000);
});

Testa själv:

  • Vad händer om du klickar på knappen igen?
    • Tips: Lägg till motsvarande console.log som för timeout: console.log('Intervall startad') i lyssnaren, och console.log('Intervall passerat') i funktionen du skickar till setInterval.
  • Kommer det någonsin att sluta?

3 - Stoppa intervall

Ibland vill vi stoppa en timer. Både setTimeout och setInterval returnerar ett ID som vi kan använda för att stoppa dem med clearTimeout respektive clearInterval.

  1. Lägg till en knapp “Stoppa interval” i HTML.
  2. I script.js, skapa en variabel intervalId högst upp i filen (utanför alla funktioner).
  3. Spara ID:t från setInterval i intervalId.
  4. När man klickar på stopp-knappen, anropa clearInterval(id).

Förslag på lösning HTML:

<button id="stop-interval">Stoppa intervall</button>

javascript (inkl. lite återupprepning av tidigare kod):

let intervalId;
const btnStopInterval = document.querySelector("#stop-interval");
const btnInterval = document.querySelector("#start-interval");

btnInterval.addEventListener("click", function() {
  msg.textContent = "Väntar: ";
  intervalId = setInterval(function() {
    msg.textContent += "x";
  }, 1000);
});

btnStopInterval.addEventListener("click", function() {
  clearInterval(intervalId);
});

4 - Mäta tid med Date.now()

För att mäta hur lång tid något tar kan vi använda Date.now(), som returnerar antalet millisekunder sedan 1 januari 1970. Genom att spara starttiden och sedan subtrahera den från sluttiden får vi skillnaden.

  1. Skapa en knapp “Starta stoppur” och en knapp “Stoppa stoppur”.
  2. Skapa en variabel startTime.
  3. När man klickar på start, sätt startTime = Date.now().
  4. När man klickar på stopp, räkna ut const elapsed = Date.now() - startTime;.
  5. Visa resultatet (i millisekunder eller sekunder) på sidan.
Förslag på lösning

HTML:

<button id="start-stopwatch">Starta stoppur</button>
<button id="stop-stopwatch">Stoppa stoppur</button>

javascript:

let startTime;
const btnStartStopwatch = document.querySelector("#start-stopwatch");
const btnStopStopwatch = document.querySelector("#stop-stopwatch");

btnStartStopwatch.addEventListener("click", function() {
  startTime = Date.now();
  msg.textContent = "Stoppur startat...";
});

btnStopStopwatch.addEventListener("click", function() {
  if (startTime) {
    const elapsed = Date.now() - startTime;
    msg.textContent = `Tid: ${elapsed} ms`;
  }
});

5 - Utmaning: Reaktionstest

Bygg ett spel som testar din reaktionsförmåga!

Skapa en en helt ny sida, med ny script-fil och stylesheet. I användargränssnittet behöver du en knapp för att starta spelet, och ett element för meddelanden.

Spelet skall fungera såhär: När användaren klickar på start-knappen, skall en timeout startas med en slumpmässig tid. När tiden gått, skall du indikera för användaren att det är dags att klicka. När användaren klickar på sidan skall reaktionstiden räknas ut och visas. Därefter skall spelet kunnas startas på nytt.

Börja med följande html- och csskod. Men lägg gärna lite tid på att stilsätta sidan så att den ser bra ut.

<button id="start">Start</button>
<div id="output">Reaktionstest, klicka på Start för att börja</div>

CSS:

body {
  /* Viktigt för att användaren skall kunna klicka i hela fönstret*/
  min-height: 100vh; 
}

Försök nu själv att implementera spelet i javascript.

Steg för steg tips 2. När man klickar på knappen:

  • Ändra texten till “Vänta…”.
  • Använd setTimeout med en slumpmässig tid (t.ex. mellan 2000 och 5000 millisekunder) för att starta testet.
  1. När tiden gått:
    • Skriv i meddelandet: “Klicka nu!”
    • Ändra bakgrundsfärgen på sidan till grön för att indikera att det är dags att klicka.
      • Tips: Använd en CSS-klass istället för att ändra färgen direkt. På så sätt kan du återställa färgen efter att testet är slut så att användaren kan spela igen.
    • Spara Date.now() i en variabel startTime.
    • Gör så att nästa klick på sidan (eller en knapp) stoppar testet.
  2. När användaren klickar (efter att det blivit grönt):
    • Räkna ut tiden det tog (Date.now() - startTime).
    • Visa resultatet: “Din reaktionstid var X ms!. Klicka på Start för att spela igen”.
    • Återställ bakgrundsfärgen till originalfärg.

Tips: Se upp så att användaren inte klickar för tidigt! Du kan behöva en variabel som håller koll på om testet är aktivt eller inte.

Förslag på lösning javascript:

const btnStart = document.querySelector("#start");
const output = document.querySelector("#output");
let reactionStartTime;
let active = false;

btnStart.addEventListener("click", function() {
  btnStart.disabled = true;

  output.textContent = "Vänta...";

  const randomTime = Math.random() * 3000 + 2000; // 2-5 sekunder

  setTimeout(function () {
    active = true;
  output.textContent = "Klicka!";
    document.body.classList.add("active"); // Antag klass i CSS
    reactionStartTime = Date.now();
  }, randomTime);
});

document.body.addEventListener("click", function () {
  if(active) {
    const reactionTime = Date.now() - reactionStartTime;
    output.textContent = `Din reaktionstid var ${reactionTime} ms!`;
    document.body.classList.remove("active");
    active = false;
    btnStart.disabled = false;
  }
});

Förslag på vidareutveckling

  • Visa texten “Tjuvstart!” om användaren klickar för tidigt och avbryt spelet.
  • Lägg in en lista där du visar alla reaktionstider.
  • Lägg till en “Visa medelvärde”-knapp som visar medelvärdet av alla reaktionstider.