ijsbreker/app.js

238 lines
7 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');
const counterDisplay = document.getElementById('counterDisplay');
const fullscreenButton = document.getElementById('fullscreenButton');
// 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');
counterDisplay.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;
// Update counter (1-based index)
counterDisplay.textContent = `${index + 1}/${config.stellingen.length}`;
counterDisplay.classList.remove('hidden');
// 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();
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');
counterDisplay.classList.add('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);
}
}
// Toggle fullscreen modus
function toggleFullscreen() {
if (!document.fullscreenElement) {
// Ga naar fullscreen
document.documentElement.requestFullscreen().then(() => {
fullscreenButton.classList.add('is-fullscreen');
}).catch((error) => {
console.error('Fout bij activeren fullscreen:', error);
});
} else {
// Verlaat fullscreen
document.exitFullscreen().then(() => {
fullscreenButton.classList.remove('is-fullscreen');
}).catch((error) => {
console.error('Fout bij verlaten fullscreen:', error);
});
}
}
// Event listeners
startButton.addEventListener('click', () => {
startGame();
});
nextButton.addEventListener('click', () => {
if (currentIndex === config.stellingen.length - 1) {
showFinish();
} else {
showStatement(currentIndex + 1);
}
});
fullscreenButton.addEventListener('click', () => {
toggleFullscreen();
});
// Luister naar fullscreen veranderingen (bijv. via ESC toets)
document.addEventListener('fullscreenchange', () => {
if (document.fullscreenElement) {
fullscreenButton.classList.add('is-fullscreen');
} else {
fullscreenButton.classList.remove('is-fullscreen');
}
});
// 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')) {
if (currentIndex === config.stellingen.length - 1) {
showFinish();
} else {
showStatement(currentIndex + 1);
}
}
}
});
// Start de app
loadConfig();