Startscherm met groene "Start IJsbreker" knop geïmplementeerd. Timer begint nu pas na klik op startknop in plaats van automatisch bij laden. Facilitator heeft volledige controle over startmoment van de presentatie. Wijzigingen: - index.html: Startscherm HTML toegevoegd - style.css: Styling voor start-screen en start-button - app.js: Flow aangepast met showStartScreen() en startGame() - Spatiebalk werkt op startscherm voor snelle start - Documentatie geüpdatet in CLAUDE.md, gemini.md en agents.md 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
195 lines
5.6 KiB
JavaScript
195 lines
5.6 KiB
JavaScript
// Globale state
|
|
let config = null;
|
|
let currentIndex = 0;
|
|
let audioContext = null;
|
|
|
|
// DOM elementen
|
|
const timerBorder = document.querySelector('.timer-border');
|
|
const startScreen = document.getElementById('startScreen');
|
|
const statementScreen = document.getElementById('statementScreen');
|
|
const overlay = document.getElementById('overlay');
|
|
const finishScreen = document.getElementById('finishScreen');
|
|
const leftStatement = document.getElementById('leftStatement');
|
|
const rightStatement = document.getElementById('rightStatement');
|
|
const leftText = document.getElementById('leftText');
|
|
const rightText = document.getElementById('rightText');
|
|
const startButton = document.getElementById('startButton');
|
|
const nextButton = document.getElementById('nextButton');
|
|
const finishText = document.getElementById('finishText');
|
|
|
|
// Laad configuratie bij start
|
|
async function loadConfig() {
|
|
try {
|
|
const response = await fetch('config.json');
|
|
config = await response.json();
|
|
initializeApp();
|
|
} catch (error) {
|
|
console.error('Fout bij laden config:', error);
|
|
alert('Kan config.json niet laden. Zorg dat alle bestanden in dezelfde map staan.');
|
|
}
|
|
}
|
|
|
|
// Initialiseer app met config
|
|
function initializeApp() {
|
|
// Stel CSS variabelen in
|
|
document.documentElement.style.setProperty('--timer-duration', `${config.timer}s`);
|
|
|
|
// Pas font grootte toe
|
|
document.querySelectorAll('.statement p').forEach(el => {
|
|
el.style.fontSize = config.fontSize;
|
|
});
|
|
finishText.style.fontSize = config.fontSize;
|
|
|
|
// Pas kleuren toe
|
|
leftStatement.style.backgroundColor = config.colors.left;
|
|
rightStatement.style.backgroundColor = config.colors.right;
|
|
|
|
// Zet knop tekst
|
|
nextButton.textContent = config.buttonText;
|
|
finishText.textContent = config.finishText;
|
|
|
|
// Toon startscherm (niet direct beginnen)
|
|
showStartScreen();
|
|
}
|
|
|
|
// Toon startscherm
|
|
function showStartScreen() {
|
|
startScreen.classList.remove('hidden');
|
|
statementScreen.classList.add('hidden');
|
|
overlay.classList.add('hidden');
|
|
finishScreen.classList.add('hidden');
|
|
}
|
|
|
|
// Start het spel
|
|
function startGame() {
|
|
startScreen.classList.add('hidden');
|
|
showStatement(0);
|
|
}
|
|
|
|
// Toon stelling op index
|
|
function showStatement(index) {
|
|
currentIndex = index;
|
|
|
|
// Check of we klaar zijn
|
|
if (index >= config.stellingen.length) {
|
|
showFinish();
|
|
return;
|
|
}
|
|
|
|
const stelling = config.stellingen[index];
|
|
|
|
// Update teksten
|
|
leftText.textContent = stelling.links;
|
|
rightText.textContent = stelling.rechts;
|
|
|
|
// Toon stellingen scherm, verberg overlay en finish
|
|
statementScreen.classList.remove('hidden');
|
|
overlay.classList.add('hidden');
|
|
finishScreen.classList.add('hidden');
|
|
|
|
// Start timer
|
|
startTimer();
|
|
}
|
|
|
|
// Start timer animatie
|
|
function startTimer() {
|
|
// Reset timer
|
|
timerBorder.classList.remove('timer-active');
|
|
void timerBorder.offsetWidth; // Force reflow
|
|
|
|
// Start timer
|
|
timerBorder.classList.add('timer-active');
|
|
|
|
// Wacht tot timer klaar is
|
|
setTimeout(() => {
|
|
playBeep();
|
|
// Bij laatste stelling: toon direct finish scherm
|
|
if (currentIndex === config.stellingen.length - 1) {
|
|
showFinish();
|
|
} else {
|
|
showOverlay();
|
|
}
|
|
}, config.timer * 1000);
|
|
}
|
|
|
|
// Toon overlay met knop (stellingen blijven zichtbaar)
|
|
function showOverlay() {
|
|
overlay.classList.remove('hidden');
|
|
timerBorder.classList.remove('timer-active');
|
|
}
|
|
|
|
// Toon eind scherm
|
|
function showFinish() {
|
|
statementScreen.classList.add('hidden');
|
|
overlay.classList.add('hidden');
|
|
finishScreen.classList.remove('hidden');
|
|
timerBorder.classList.remove('timer-active');
|
|
}
|
|
|
|
// Initialiseer audio context (herbruikbaar)
|
|
function initAudioContext() {
|
|
if (!audioContext) {
|
|
try {
|
|
audioContext = new (window.AudioContext || window.webkitAudioContext)();
|
|
} catch (error) {
|
|
console.error('Fout bij initialiseren audio context:', error);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Speel beep geluid via Web Audio API
|
|
function playBeep() {
|
|
try {
|
|
// Zorg dat audioContext bestaat
|
|
initAudioContext();
|
|
if (!audioContext) return;
|
|
|
|
const oscillator = audioContext.createOscillator();
|
|
const gainNode = audioContext.createGain();
|
|
|
|
// Configureer oscillator (beep geluid)
|
|
oscillator.type = 'sine';
|
|
oscillator.frequency.setValueAtTime(800, audioContext.currentTime); // 800 Hz
|
|
|
|
// Configureer volume (fade out)
|
|
gainNode.gain.setValueAtTime(0.3, audioContext.currentTime);
|
|
gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 0.3);
|
|
|
|
// Verbind nodes
|
|
oscillator.connect(gainNode);
|
|
gainNode.connect(audioContext.destination);
|
|
|
|
// Speel beep (300ms)
|
|
oscillator.start(audioContext.currentTime);
|
|
oscillator.stop(audioContext.currentTime + 0.3);
|
|
} catch (error) {
|
|
console.error('Fout bij afspelen geluid:', error);
|
|
}
|
|
}
|
|
|
|
// Event listeners
|
|
startButton.addEventListener('click', () => {
|
|
startGame();
|
|
});
|
|
|
|
nextButton.addEventListener('click', () => {
|
|
showStatement(currentIndex + 1);
|
|
});
|
|
|
|
// Spatiebalk voor volgende stelling EN startscherm
|
|
document.addEventListener('keydown', (e) => {
|
|
if (e.code === 'Space') {
|
|
e.preventDefault();
|
|
// Start spel als we op startscherm zijn
|
|
if (!startScreen.classList.contains('hidden')) {
|
|
startGame();
|
|
}
|
|
// Volgende stelling als overlay zichtbaar is
|
|
else if (!overlay.classList.contains('hidden')) {
|
|
showStatement(currentIndex + 1);
|
|
}
|
|
}
|
|
});
|
|
|
|
// Start de app
|
|
loadConfig();
|