the-clock / index.html
ThetaPhiPsi's picture
Add 2 files
8c7ffd5 verified
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Uhrzeit lernen - Spiel für Kinder</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
@keyframes bounce {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-20px); }
}
@keyframes confetti {
0% { transform: translateY(0) rotate(0deg); opacity: 1; }
100% { transform: translateY(100vh) rotate(360deg); opacity: 0; }
}
.confetti {
position: absolute;
width: 15px;
height: 15px;
background-color: #f00;
animation: confetti 3s ease-out forwards;
}
.clock-face {
background-color: #FFFAF0;
border: 8px solid #4B5563;
box-shadow: 0 0 20px rgba(0,0,0,0.2);
}
.hour-hand {
background-color: #EF4444; /* Rot für den Stundenzeiger */
height: 8px;
width: 30%;
top: 50%;
left: 20%;
transform-origin: 100%;
border-radius: 6px;
transform: rotate(90deg);
z-index: 2;
}
.minute-hand {
background-color: #3B82F6; /* Blau für den Minutenzeiger */
height: 6px;
width: 40%;
top: 50%;
left: 10%;
transform-origin: 100%;
border-radius: 4px;
transform: rotate(90deg);
z-index: 3;
}
.correct-answer {
animation: bounce 0.5s ease infinite;
background-color: #10B981 !important;
color: white !important;
}
.wrong-answer {
background-color: #EF4444 !important;
color: white !important;
}
.hint-bubble {
position: absolute;
background-color: #3B82F6;
color: white;
padding: 10px;
border-radius: 10px;
animation: float 3s ease-in-out infinite;
z-index: 10;
}
@keyframes float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-10px); }
}
/* Präzise Positionierung der Ziffern auf einem Kreis */
.clock-number {
position: absolute;
font-size: 1.5rem;
font-weight: bold;
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
transform: translate(-50%, -50%);
color: #4B5563;
background-color: #FFFAF0;
border-radius: 50%;
z-index: 1;
}
/* Ticks für die Minuten */
.clock-tick {
position: absolute;
background-color: #4B5563;
width: 2px;
height: 8px;
transform-origin: 50% 100%;
left: 50%;
top: 10px;
}
</style>
</head>
<body class="bg-blue-50 min-h-screen flex flex-col items-center justify-center p-4">
<div class="max-w-2xl w-full bg-white rounded-2xl shadow-xl p-6">
<h1 class="text-3xl font-bold text-center text-blue-600 mb-2">Lerne die Uhrzeit!</h1>
<p class="text-center text-gray-600 mb-6">Schau auf die Uhr und wähle die richtige Zeit aus.</p>
<div class="flex flex-col md:flex-row items-center justify-between gap-8 mb-8">
<!-- Analog Clock -->
<div class="relative w-64 h-64 mx-auto md:mx-0 clock-face rounded-full">
<!-- Clock center -->
<div class="absolute w-4 h-4 bg-blue-600 rounded-full" style="top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 4;"></div>
<!-- Clock hands -->
<div class="hour-hand absolute"></div>
<div class="minute-hand absolute"></div>
<!-- Minute ticks -->
<div id="clock-ticks"></div>
<!-- Clock numbers 1-12 - mathematically precise circular positioning -->
<!-- Using polar coordinates with radius 42% of clock diameter -->
<div class="clock-number" style="top: 13.4%; left: 75%;">1</div>
<div class="clock-number" style="top: 7.5%; left: 50%;">12</div>
<div class="clock-number" style="top: 13.4%; left: 25%;">11</div>
<div class="clock-number" style="top: 25%; left: 7.5%;">10</div>
<div class="clock-number" style="top: 50%; left: 13.4%;">9</div>
<div class="clock-number" style="top: 75%; left: 7.5%;">8</div>
<div class="clock-number" style="top: 86.6%; left: 25%;">7</div>
<div class="clock-number" style="top: 92.5%; left: 50%;">6</div>
<div class="clock-number" style="top: 86.6%; left: 75%;">5</div>
<div class="clock-number" style="top: 75%; left: 92.5%;">4</div>
<div class="clock-number" style="top: 50%; left: 86.6%;">3</div>
<div class="clock-number" style="top: 25%; left: 92.5%;">2</div>
</div>
<!-- Game info -->
<div class="flex-1">
<div class="bg-blue-100 rounded-lg p-4 mb-4">
<h2 class="font-bold text-blue-800 mb-2">Punkte: <span id="score">0</span></h2>
<div class="w-full bg-gray-200 rounded-full h-4">
<div id="progress-bar" class="bg-blue-600 h-4 rounded-full" style="width: 0%"></div>
</div>
</div>
<button id="hint-btn" class="bg-yellow-400 hover:bg-yellow-500 text-white font-bold py-2 px-4 rounded-full mb-4 transition-all flex items-center justify-center">
<i class="fas fa-lightbulb mr-2"></i> Tipp anzeigen
</button>
<div id="hint-container" class="hidden bg-blue-100 p-3 rounded-lg mb-4">
<p class="text-blue-800 font-medium" id="hint-text"></p>
</div>
</div>
</div>
<!-- Answer options -->
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6" id="options-container">
<!-- Options will be inserted here by JavaScript -->
</div>
<!-- Feedback message -->
<div id="feedback" class="text-center text-xl font-bold py-4 hidden"></div>
<!-- Next button -->
<button id="next-btn" class="hidden w-full bg-green-500 hover:bg-green-600 text-white font-bold py-3 px-4 rounded-lg transition-all">
Weiter <i class="fas fa-arrow-right ml-2"></i>
</button>
</div>
<!-- Audio elements -->
<audio id="correct-sound" src="https://assets.mixkit.co/sfx/preview/mixkit-correct-answer-tone-2870.mp3"></audio>
<audio id="wrong-sound" src="https://assets.mixkit.co/sfx/preview/mixkit-wrong-answer-fail-notification-946.mp3"></audio>
<script>
document.addEventListener('DOMContentLoaded', function() {
// DOM elements
const clockFace = document.querySelector('.clock-face');
const hourHand = document.querySelector('.hour-hand');
const minuteHand = document.querySelector('.minute-hand');
const optionsContainer = document.getElementById('options-container');
const feedbackElement = document.getElementById('feedback');
const nextButton = document.getElementById('next-btn');
const hintButton = document.getElementById('hint-btn');
const hintContainer = document.getElementById('hint-container');
const hintText = document.getElementById('hint-text');
const scoreElement = document.getElementById('score');
const progressBar = document.getElementById('progress-bar');
const correctSound = document.getElementById('correct-sound');
const wrongSound = document.getElementById('wrong-sound');
const clockTicks = document.getElementById('clock-ticks');
// Game variables
let currentHour = 0;
let currentMinute = 0;
let correctAnswer = '';
let score = 0;
let questionsAnswered = 0;
const totalQuestions = 10;
let hintUsed = false;
// Initialize game
initGame();
function initGame() {
// Create minute ticks
createMinuteTicks();
generateRandomTime();
updateClock();
generateOptions();
updateScore();
questionsAnswered = 0;
updateProgressBar();
hintContainer.classList.add('hidden');
hintUsed = false;
}
function createMinuteTicks() {
clockTicks.innerHTML = '';
for (let i = 0; i < 60; i++) {
const tick = document.createElement('div');
tick.className = 'clock-tick';
tick.style.transform = `rotate(${i * 6}deg)`;
// Make the 5-minute ticks longer
if (i % 5 === 0) {
tick.style.height = '12px';
}
clockTicks.appendChild(tick);
}
}
function generateRandomTime() {
// Generate random hour (1-12) and minute (0-55, in 5-minute increments)
currentHour = Math.floor(Math.random() * 12) + 1;
currentMinute = Math.floor(Math.random() * 12) * 5;
// Format the correct answer
const formattedHour = currentHour < 10 ? `0${currentHour}` : currentHour;
const formattedMinute = currentMinute < 10 ? `0${currentMinute}` : currentMinute;
correctAnswer = `${formattedHour}:${formattedMinute}`;
console.log(`Correct time set to: ${currentHour}:${currentMinute}`);
}
function updateClock() {
// Calculate angles for clock hands
// Hour hand moves 30 degrees per hour + 0.5 degrees per minute
const hourAngle = (currentHour % 12) * 30 + (currentMinute / 2) + 90;
// Minute hand moves 6 degrees per minute
const minuteAngle = currentMinute * 6 + 90;
// Apply rotation to clock hands
hourHand.style.transform = `rotate(${hourAngle}deg)`;
minuteHand.style.transform = `rotate(${minuteAngle}deg)`;
console.log(`Clock updated - Hour: ${currentHour}, Minute: ${currentMinute}`);
console.log(`Hour angle: ${hourAngle}°, Minute angle: ${minuteAngle}°`);
}
function generateOptions() {
optionsContainer.innerHTML = '';
// Create 3 options (1 correct, 2 incorrect)
const options = [correctAnswer];
// Generate 2 incorrect options
while (options.length < 3) {
let wrongHour = Math.floor(Math.random() * 12) + 1;
let wrongMinute = Math.floor(Math.random() * 12) * 5;
// Make sure wrong time is different from correct time
if (wrongHour === currentHour && wrongMinute === currentMinute) {
wrongHour = (wrongHour % 12) + 1;
}
const formattedWrongHour = wrongHour < 10 ? `0${wrongHour}` : wrongHour;
const formattedWrongMinute = wrongMinute < 10 ? `0${wrongMinute}` : wrongMinute;
const wrongOption = `${formattedWrongHour}:${formattedWrongMinute}`;
// Make sure all options are unique
if (!options.includes(wrongOption)) {
options.push(wrongOption);
}
}
// Shuffle options
options.sort(() => Math.random() - 0.5);
// Create buttons for each option
options.forEach(option => {
const button = document.createElement('button');
button.textContent = option;
button.className = 'bg-blue-100 hover:bg-blue-200 text-blue-800 font-bold py-4 px-4 rounded-lg text-xl transition-all';
button.addEventListener('click', () => checkAnswer(option));
optionsContainer.appendChild(button);
});
// Generate hint text
generateHint();
}
function generateHint() {
const hourText = currentHour === 1 ? 'Stunde' : 'Stunden';
const minuteText = currentMinute === 1 ? 'Minute' : 'Minuten';
hintText.textContent = `Der große Zeiger (blau) zeigt auf ${currentMinute} ${minuteText} und der kleine Zeiger (rot) zeigt auf ${currentHour} ${hourText}.`;
}
function checkAnswer(selectedAnswer) {
// Disable all option buttons
const optionButtons = document.querySelectorAll('#options-container button');
optionButtons.forEach(button => {
button.disabled = true;
button.classList.remove('hover:bg-blue-200');
if (button.textContent === correctAnswer) {
button.classList.add('correct-answer');
} else if (button.textContent === selectedAnswer && selectedAnswer !== correctAnswer) {
button.classList.add('wrong-answer');
}
});
// Check if answer is correct
if (selectedAnswer === correctAnswer) {
// Correct answer
feedbackElement.textContent = 'Richtig! 🎉';
feedbackElement.className = 'text-center text-xl font-bold py-4 text-green-600';
correctSound.play();
score += hintUsed ? 5 : 10; // Give less points if hint was used
createConfetti();
} else {
// Wrong answer
feedbackElement.textContent = `Falsch! Die richtige Antwort ist ${correctAnswer}.`;
feedbackElement.className = 'text-center text-xl font-bold py-4 text-red-600';
wrongSound.play();
}
feedbackElement.classList.remove('hidden');
nextButton.classList.remove('hidden');
questionsAnswered++;
updateScore();
updateProgressBar();
}
function createConfetti() {
const colors = ['#EF4444', '#3B82F6', '#10B981', '#F59E0B', '#8B5CF6'];
for (let i = 0; i < 50; i++) {
const confetti = document.createElement('div');
confetti.className = 'confetti';
confetti.style.left = Math.random() * 100 + 'vw';
confetti.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)];
confetti.style.animationDuration = Math.random() * 2 + 2 + 's';
confetti.style.animationDelay = Math.random() * 2 + 's';
// Random shape (circle or square)
if (Math.random() > 0.5) {
confetti.style.borderRadius = '50%';
}
document.body.appendChild(confetti);
// Remove confetti after animation
setTimeout(() => {
confetti.remove();
}, 5000);
}
}
function updateScore() {
scoreElement.textContent = score;
}
function updateProgressBar() {
const progress = (questionsAnswered / totalQuestions) * 100;
progressBar.style.width = `${progress}%`;
if (questionsAnswered >= totalQuestions) {
// Game over
setTimeout(() => {
alert(`Spiel beendet! Dein Punktestand: ${score}`);
initGame(); // Restart game
}, 1000);
}
}
// Event listeners
nextButton.addEventListener('click', function() {
feedbackElement.classList.add('hidden');
nextButton.classList.add('hidden');
generateRandomTime();
updateClock();
generateOptions();
hintContainer.classList.add('hidden');
hintUsed = false;
});
hintButton.addEventListener('click', function() {
hintContainer.classList.toggle('hidden');
if (!hintContainer.classList.contains('hidden')) {
hintUsed = true;
}
});
// Make clock draggable for fun
let isDragging = false;
let startX, startY, initialX, initialY;
clockFace.addEventListener('mousedown', function(e) {
isDragging = true;
startX = e.clientX;
startY = e.clientY;
initialX = clockFace.offsetLeft;
initialY = clockFace.offsetTop;
clockFace.style.cursor = 'grabbing';
clockFace.style.transition = 'none';
document.addEventListener('mousemove', dragClock);
document.addEventListener('mouseup', stopDrag);
});
function dragClock(e) {
if (!isDragging) return;
const dx = e.clientX - startX;
const dy = e.clientY - startY;
clockFace.style.left = `${initialX + dx}px`;
clockFace.style.top = `${initialY + dy}px`;
}
function stopDrag() {
isDragging = false;
clockFace.style.cursor = 'grab';
clockFace.style.transition = 'all 0.3s ease';
document.removeEventListener('mousemove', dragClock);
document.removeEventListener('mouseup', stopDrag);
// Snap back to original position after a delay
setTimeout(() => {
clockFace.style.left = '';
clockFace.style.top = '';
}, 1000);
}
// Also make clock draggable on touch devices
clockFace.addEventListener('touchstart', function(e) {
isDragging = true;
startX = e.touches[0].clientX;
startY = e.touches[0].clientY;
initialX = clockFace.offsetLeft;
initialY = clockFace.offsetTop;
clockFace.style.cursor = 'grabbing';
clockFace.style.transition = 'none';
e.preventDefault();
});
clockFace.addEventListener('touchmove', function(e) {
if (!isDragging) return;
const dx = e.touches[0].clientX - startX;
const dy = e.touches[0].clientY - startY;
clockFace.style.left = `${initialX + dx}px`;
clockFace.style.top = `${initialY + dy}px`;
e.preventDefault();
});
clockFace.addEventListener('touchend', function() {
isDragging = false;
clockFace.style.cursor = 'grab';
clockFace.style.transition = 'all 0.3s ease';
// Snap back to original position after a delay
setTimeout(() => {
clockFace.style.left = '';
clockFace.style.top = '';
}, 1000);
});
});
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=ThetaPhiPsi/the-clock" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>