Abstraktes Header-Bild in den Farben von tsjdev apps

Blogbeitrag

Flags Quiz - Ein interaktives Flaggen-Quiz mit HTML, JavaScript und Bulma

Flaggen sind mehr als nur bunte Stofffetzen – sie erzählen Geschichten von Ländern, Kulturen und Geschichte. Aber wie gut kennst du eigentlich die Flaggen der Welt? Mit meinem neuen Projekt Flags Quiz kannst du dein Wissen auf die Probe stellen!

🎮 Das Projekt

Flags Quiz ist eine kleine, aber feine Web-Anwendung, die es ermöglicht, spielerisch die Flaggen von 248 Ländern und Territorien zu lernen. Das Besondere: Die App ist komplett responsiv, funktioniert auf allen Geräten und kommt mit coolen Features wie Sound-Effekten, mehrsprachiger Unterstützung und einem Timer.

🌐 Live Demo: https://tsjdev-apps.github.io/flagsquiz-web/

📦 GitHub Repository: https://github.com/tsjdev-apps/flagsquiz-web

✨ Features

  • 🎯 Interaktives Quiz: Flaggen erkennen mit Multiple-Choice-Fragen
  • ⏱️ Timer-Challenge: 10 Sekunden pro Frage
  • 🏆 Punktesystem: 5 Punkte für jede richtige Antwort
  • 🔊 Sound-Effekte: Akustisches Feedback für richtige/falsche Antworten
  • 🌍 Mehrsprachig: Deutsch und Englisch (automatische Browser-Erkennung)
  • 📱 Responsive Design: Funktioniert perfekt auf Desktop und Mobile
  • 🎨 Modernes UI: Bulma CSS Framework mit Custom-Styling

🛠️ Technologie-Stack

Das Projekt setzt auf bewährte Web-Technologien:

  • HTML5 – Struktur und Layout
  • JavaScript (ES6+) – Spiellogik und Interaktivität
  • Bulma CSS – Modernes CSS-Framework
  • Lottie – Animationen auf der Startseite
  • FlagCDN – Flaggen-Bilder via API
  • Font Awesome – Icons

🎯 Wie funktioniert das Quiz?

1. Länder-Daten laden

Die Basis des Quiz bildet eine JSON-Datei mit allen Ländern, ihren Namen (Englisch und Deutsch) und ISO-Codes:

[
  {
    "countryEN": "Germany",
    "countryDE": "Deutschland",
    "code": "de"
  },
  {
    "countryEN": "United States of America",
    "countryDE": "Vereinigte Staaten",
    "code": "us"
  }
]

Beim Start der Anwendung werden diese Daten asynchron geladen:

async function loadCountries() {
    try {
        const response = await fetch('assets/data/countries.json');
        countries = await response.json();
        console.log(`Loaded ${countries.length} countries`);
    } catch (error) {
        console.error('Error loading countries:', error);
    }
}

2. Zufällige Fragen generieren

Für jede Frage wird ein zufälliges Land ausgewählt und drei zusätzliche falsche Antworten generiert:

function loadQuestion() {
    // Reset button states
    answerButtons.forEach(button => {
        button.classList.remove('is-success', 'is-danger', 'is-loading');
        button.disabled = false;
        button.blur();
    });

    // Wähle ein zufälliges Land
    currentCountry = countries[Math.floor(Math.random() * countries.length)];
    
    // Generiere 3 falsche Antworten
    const wrongAnswers = [];
    while (wrongAnswers.length < 3) {
        const randomCountry = countries[Math.floor(Math.random() * countries.length)];
        if (randomCountry.code !== currentCountry.code && 
            !wrongAnswers.includes(randomCountry)) {
            wrongAnswers.push(randomCountry);
        }
    }

    // Mische alle Antworten
    const allAnswers = [currentCountry, ...wrongAnswers];
    allAnswers.sort(() => Math.random() - 0.5);

    // Aktualisiere UI
    flagImage.src = `https://flagcdn.com/256x192/${currentCountry.code}.png`;
    flagImage.alt = currentCountry[`country${currentLanguage.toUpperCase()}`];
    
    answerButtons.forEach((button, index) => {
        const country = allAnswers[index];
        button.textContent = country[`country${currentLanguage.toUpperCase()}`];
        button.dataset.code = country.code;
    });

    startTimer();
}

3. Flaggen via API laden

Die Flaggen werden dynamisch über die FlagCDN-API geladen:

// URL-Format: https://flagcdn.com/256x192/{countrycode}.png
flagImage.src = `https://flagcdn.com/256x192/${currentCountry.code}.png`;

Dies ermöglicht hochqualitative Flaggen-Bilder ohne sie alle lokal speichern zu müssen.

4. Timer-Implementierung

Jede Frage hat ein 10-Sekunden-Zeitlimit:

function startTimer() {
    timeLeft = 10;
    updateTimerDisplay();
    
    if (timerInterval) {
        clearInterval(timerInterval);
    }
    
    timerInterval = setInterval(() => {
        timeLeft--;
        updateTimerDisplay();
        
        if (timeLeft <= 0) {
            clearInterval(timerInterval);
            handleTimeout();
        }
    }, 1000);
}

function updateTimerDisplay() {
    timerValue.textContent = timeLeft;
}

5. Antwort-Handling mit Feedback

Wenn der Spieler eine Antwort auswählt, wird visuelles und akustisches Feedback gegeben:

function handleAnswer(event) {
    if (answered) return;
    answered = true;
    
    clearInterval(timerInterval);
    
    const selectedButton = event.target;
    const selectedCode = selectedButton.dataset.code;
    const isCorrect = selectedCode === currentCountry.code;
    
    // Deaktiviere alle Buttons
    answerButtons.forEach(button => {
        button.disabled = true;
        button.blur();
    });
    
    if (isCorrect) {
        // Richtige Antwort
        selectedButton.classList.add('is-success');
        score += 5;
        scoreValue.textContent = score;
        playSound(correctSound);
        
        setTimeout(() => {
            loadQuestion();
        }, 3000);
    } else {
        // Falsche Antwort - Game Over
        selectedButton.classList.add('is-danger');
        playSound(wrongSound);
        
        // Zeige richtige Antwort
        answerButtons.forEach(button => {
            if (button.dataset.code === currentCountry.code) {
                button.classList.add('is-success');
            }
        });
        
        setTimeout(() => {
            showGameOver();
        }, 2000);
    }
}

6. Sound-Effekte

Sound-Effekte werden mit HTML5 Audio-API implementiert:

const correctSound = new Audio('assets/audio/answercorrect.mp3');
const wrongSound = new Audio('assets/audio/answerwrong.mp3');
let isSoundEnabled = true;

function playSound(sound) {
    if (isSoundEnabled) {
        sound.currentTime = 0;
        sound.play().catch(err => console.log('Audio play failed:', err));
    }
}

// Toggle Sound
soundToggle.addEventListener('click', () => {
    isSoundEnabled = !isSoundEnabled;
    soundIcon.className = isSoundEnabled ? 'fas fa-volume-up' : 'fas fa-volume-mute';
});

7. Mehrsprachigkeit

Die App unterstützt Deutsch und Englisch mit automatischer Browser-Erkennung:

let currentLanguage = 'en';

// Erkenne Browser-Sprache
function detectBrowserLanguage() {
    const savedLanguage = localStorage.getItem('flagsquiz-language');
    if (savedLanguage) {
        return savedLanguage;
    }
    
    const browserLang = navigator.language || navigator.userLanguage;
    return browserLang.startsWith('de') ? 'de' : 'en';
}

// Übersetzungen
const translations = {
    en: {
        welcomeTitle: 'Welcome to the Flags Quiz!',
        welcomeSubtitle: 'Test your knowledge about the flags of the world.',
        startButton: 'Start Quiz',
        questionText: 'Which country does this flag belong to?',
        scoreLabel: 'SCORE',
        timeLabel: 'TIME',
        gameOverTitle: 'Game Over',
        // ... weitere Übersetzungen
    },
    de: {
        welcomeTitle: 'Willkommen zum Flaggen-Quiz!',
        welcomeSubtitle: 'Teste dein Wissen über die Flaggen der Welt.',
        startButton: 'Quiz starten',
        questionText: 'Zu welchem Land gehört diese Flagge?',
        scoreLabel: 'PUNKTE',
        timeLabel: 'ZEIT',
        gameOverTitle: 'Spiel vorbei',
        // ... weitere Übersetzungen
    }
};

function updateLanguage() {
    document.querySelector('#welcomeTitle').textContent = translations[currentLanguage].welcomeTitle;
    document.querySelector('#welcomeSubtitle').textContent = translations[currentLanguage].welcomeSubtitle;
    // ... weitere UI-Updates
    
    // Speichere Auswahl
    localStorage.setItem('flagsquiz-language', currentLanguage);
}

🎨 Custom Design mit Bulma

Das Design basiert auf Bulma CSS, wurde aber mit einer eigenen Farbpalette angepasst:

:root {
    --color-dark-slate: #455054;
    --color-teal: #308695;
    --color-pink: #D45769;
    --color-orange: #E69D45;
    --color-light-gray: #D4CFC9;
}

.navbar {
    background-color: var(--color-teal) !important;
}

.button.is-primary {
    background-color: var(--color-teal);
    border-color: var(--color-teal);
}

.answer-button.is-success {
    background-color: var(--color-teal) !important;
    border-color: var(--color-teal) !important;
}

.answer-button.is-danger {
    background-color: var(--color-pink) !important;
    border-color: var(--color-pink) !important;
}

🎭 Lottie-Animation

Auf der Startseite wird eine Lottie-Animation verwendet, um das Quiz visuell ansprechender zu machen:

<!-- Lottie Player via CDN -->
<script src="https://unpkg.com/@lottiefiles/lottie-player@latest/dist/lottie-player.js"></script>

<!-- Animation -->
<lottie-player 
    src="assets/quiz.json" 
    background="transparent" 
    speed="1" 
    style="width: 300px; height: 300px; margin: 0 auto;" 
    loop 
    autoplay>
</lottie-player>

📊 Projekt-Struktur

flagsquiz-web/
├── assets/
│   ├── audio/
│   │   ├── answercorrect.mp3
│   │   └── answerwrong.mp3
│   ├── data/
│   │   └── countries.json
│   ├── favicon.ico
│   └── quiz.json
├── css/
│   └── styles.css
├── js/
│   └── app.js
├── index.html
└── README.md

🚀 Installation und Ausführung

Das Projekt ist super einfach zu starten:

# Repository klonen
git clone https://github.com/tsjdev-apps/flagsquiz-web.git
cd flagsquiz-web

# Lokalen Webserver starten
python -m http.server 8000

# Browser öffnen
# http://localhost:8000

🎓 Fazit

Das Flags Quiz Projekt zeigt, wie man mit einfachen Web-Technologien eine interaktive, responsive und benutzerfreundliche Anwendung erstellen kann. Besonders die Kombination aus Bulma CSS für schnelles Prototyping und Vanilla JavaScript für volle Kontrolle hat sich bewährt.

Das Projekt eignet sich perfekt für:

  • 📚 Lernen – Web-Entwicklung für Anfänger
  • 🎮 Spielen – Flaggen-Wissen testen
  • 🔧 Erweitern – Als Basis für eigene Quiz-Apps

Weiterempfehlen

Diesen Beitrag teilen

Wenn dir der Beitrag gefallen hat: gern weiterreichen. Gute Links dürfen sich ruhig schnell verbreiten.

Vorheriger/Nächster Beitrag

PicCaptionr erhält ein großes Update: Jetzt mit .NET 10 und den neuesten OpenAI-Modellen Vorheriger Beitrag PicCaptionr erhält ein großes Update: Jetzt mit .NET 10 und den neuesten OpenAI-Modellen Meine GitHub-Projekte – Innovation mit .NET, KI und Kreativität Nächster Beitrag Meine GitHub-Projekte – Innovation mit .NET, KI und Kreativität
Sicherheitslücken in verwendeten NuGet-Paketen finden Sicherheitslücken in verwendeten NuGet-Paketen finden Windows Terminal unter Windows 11 mit Oh-My-Posh einrichten Windows Terminal unter Windows 11 mit Oh-My-Posh einrichten Cronjobs in Azure Functions: Zeitgesteuerte Aufgaben mit dem TimerTrigger ausführen Cronjobs in Azure Functions: Zeitgesteuerte Aufgaben mit dem TimerTrigger ausführen GitHub Actions lokal testen mit Act GitHub Actions lokal testen mit Act
Lust auf ein kurzes digitales Hallo? Wenn du eine Idee teilen, eine Frage loswerden oder ein Projekt anschieben willst: mein Posteingang ist deutlich zuverlässiger als Brieftauben. apps@tsjdev-apps.de Mail schicken