Initial commit - Kinderspiele
This commit is contained in:
@@ -0,0 +1,246 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
|
||||
<title>Buchstaben nachmalen - KinderWelt</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; user-select: none; }
|
||||
body {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
min-height: 100vh; display: flex; flex-direction: column; align-items: center;
|
||||
font-family: 'Comic Sans MS', cursive, sans-serif; padding: 10px;
|
||||
}
|
||||
h1 { color: white; margin-bottom: 10px; font-size: 22px; }
|
||||
.instruction { color: white; font-size: 18px; margin-bottom: 10px; text-align: center; }
|
||||
.main-area {
|
||||
display: flex; flex-direction: column; align-items: center; gap: 15px;
|
||||
}
|
||||
.letter-section {
|
||||
display: flex; flex-direction: column; align-items: center; gap: 10px;
|
||||
}
|
||||
.target-letter {
|
||||
font-size: 80px; background: white; border-radius: 15px;
|
||||
padding: 10px 30px; box-shadow: 0 5px 15px rgba(0,0,0,0.2);
|
||||
}
|
||||
.arrow { font-size: 30px; color: white; }
|
||||
.drawing-area { position: relative; }
|
||||
#drawCanvas {
|
||||
background: white; border: 3px solid #4ade80; border-radius: 15px;
|
||||
box-shadow: 0 5px 15px rgba(0,0,0,0.2); touch-action: none;
|
||||
}
|
||||
.template-overlay {
|
||||
position: absolute; top: 0; left: 0; pointer-events: none;
|
||||
font-size: 200px; color: rgba(200,200,200,0.3); text-align: center;
|
||||
line-height: 300px; width: 300px; height: 300px;
|
||||
}
|
||||
.letter-grid {
|
||||
display: grid; grid-template-columns: repeat(10, 1fr);
|
||||
gap: 5px; max-width: 500px; width: 100%; margin: 10px 0;
|
||||
}
|
||||
.letter-btn {
|
||||
background: rgba(255,255,255,0.9); border: none; border-radius: 8px;
|
||||
padding: 10px 5px; font-size: 20px; cursor: pointer; font-family: inherit;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
.letter-btn:hover { background: white; transform: scale(1.1); }
|
||||
.letter-btn.active { background: #4ade80; color: white; }
|
||||
.controls { display: flex; gap: 15px; margin-top: 10px; flex-wrap: wrap; justify-content: center; }
|
||||
.btn {
|
||||
background: white; border: none; border-radius: 10px; padding: 12px 25px;
|
||||
font-size: 16px; cursor: pointer; font-family: inherit; font-weight: bold;
|
||||
}
|
||||
.btn-check { background: #4ade80; color: white; }
|
||||
.btn-clear { background: #feca57; }
|
||||
.btn-back { background: #ff6b6b; color: white; text-decoration: none; }
|
||||
.feedback {
|
||||
font-size: 24px; margin: 10px 0; min-height: 40px; font-weight: bold;
|
||||
color: white; text-align: center;
|
||||
}
|
||||
.score { color: white; font-size: 18px; margin-top: 5px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>🔤 Buchstaben nachmalen</h1>
|
||||
|
||||
<div class="instruction" id="instruction">Male den Buchstaben nach!</div>
|
||||
|
||||
<div class="main-area">
|
||||
<div class="letter-section">
|
||||
<div class="target-letter" id="targetLetter">A</div>
|
||||
<div class="arrow">⬇️</div>
|
||||
|
||||
<div class="drawing-area">
|
||||
<canvas id="drawCanvas" width="300" height="300"></canvas>
|
||||
<div class="template-overlay" id="templateOverlay">A</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="feedback" id="feedback"></div>
|
||||
<div class="score">Richtig: <span id="correctCount">0</span></div>
|
||||
|
||||
<div class="controls">
|
||||
<button class="btn btn-check" onclick="checkDrawing()">✓ Fertig!</button>
|
||||
<button class="btn btn-clear" onclick="clearCanvas()">🗑️ Löschen</button>
|
||||
<button class="btn" onclick="nextLetter()">🔄 Nächster</button>
|
||||
<a href="../index.html" class="btn btn-back">⬅️ Zurück</a>
|
||||
</div>
|
||||
|
||||
<div class="letter-grid" id="letterGrid"></div>
|
||||
|
||||
<script>
|
||||
const letters = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','Ä','Ö','Ü'];
|
||||
const synth = window.speechSynthesis;
|
||||
|
||||
let currentLetter = 'A';
|
||||
let currentIndex = 0;
|
||||
let isDrawing = false;
|
||||
let correctCount = 0;
|
||||
let hasDrawn = false;
|
||||
|
||||
const canvas = document.getElementById('drawCanvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
const templateOverlay = document.getElementById('templateOverlay');
|
||||
|
||||
// Setup canvas
|
||||
ctx.lineCap = 'round';
|
||||
ctx.lineJoin = 'round';
|
||||
ctx.lineWidth = 8;
|
||||
ctx.strokeStyle = '#333';
|
||||
|
||||
function initGrid() {
|
||||
const grid = document.getElementById('letterGrid');
|
||||
letters.forEach((letter, index) => {
|
||||
const btn = document.createElement('button');
|
||||
btn.className = 'letter-btn';
|
||||
btn.textContent = letter;
|
||||
btn.onclick = () => selectLetter(index);
|
||||
grid.appendChild(btn);
|
||||
});
|
||||
}
|
||||
|
||||
function selectLetter(index) {
|
||||
currentIndex = index;
|
||||
currentLetter = letters[index];
|
||||
updateDisplay();
|
||||
}
|
||||
|
||||
function updateDisplay() {
|
||||
document.getElementById('targetLetter').textContent = currentLetter;
|
||||
templateOverlay.textContent = currentLetter;
|
||||
document.getElementById('instruction').textContent = `Male den Buchstaben "${currentLetter}" nach!`;
|
||||
|
||||
// Highlight
|
||||
document.querySelectorAll('.letter-btn').forEach((btn, i) => {
|
||||
btn.classList.toggle('active', i === currentIndex);
|
||||
});
|
||||
|
||||
clearCanvas();
|
||||
speak(`Male den Buchstaben ${currentLetter}`);
|
||||
}
|
||||
|
||||
function nextLetter() {
|
||||
currentIndex = (currentIndex + 1) % letters.length;
|
||||
selectLetter(currentIndex);
|
||||
}
|
||||
|
||||
// Drawing functions
|
||||
function getPos(e) {
|
||||
const rect = canvas.getBoundingClientRect();
|
||||
const clientX = e.touches ? e.touches[0].clientX : e.clientX;
|
||||
const clientY = e.touches ? e.touches[0].clientY : e.clientY;
|
||||
return {
|
||||
x: clientX - rect.left,
|
||||
y: clientY - rect.top
|
||||
};
|
||||
}
|
||||
|
||||
function startDraw(e) {
|
||||
isDrawing = true;
|
||||
hasDrawn = true;
|
||||
const pos = getPos(e);
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(pos.x, pos.y);
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
function draw(e) {
|
||||
if (!isDrawing) return;
|
||||
const pos = getPos(e);
|
||||
ctx.lineTo(pos.x, pos.y);
|
||||
ctx.stroke();
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
function stopDraw() {
|
||||
isDrawing = false;
|
||||
}
|
||||
|
||||
function clearCanvas() {
|
||||
ctx.fillStyle = 'white';
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
hasDrawn = false;
|
||||
document.getElementById('feedback').textContent = '';
|
||||
}
|
||||
|
||||
function checkDrawing() {
|
||||
if (!hasDrawn) {
|
||||
document.getElementById('feedback').textContent = '⚠️ Male erst etwas!';
|
||||
return;
|
||||
}
|
||||
|
||||
// Einfache Prüfung: Hat der Benutzer genug gezeichnet?
|
||||
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||
const pixels = imageData.data;
|
||||
let drawnPixels = 0;
|
||||
|
||||
// Zähle nicht-weiße Pixel
|
||||
for (let i = 3; i < pixels.length; i += 4) {
|
||||
if (pixels[i] > 0) drawnPixels++;
|
||||
}
|
||||
|
||||
// Mindestens 500 Pixel müssen gezeichnet sein
|
||||
const threshold = 500;
|
||||
|
||||
if (drawnPixels > threshold) {
|
||||
correctCount++;
|
||||
document.getElementById('correctCount').textContent = correctCount;
|
||||
document.getElementById('feedback').textContent = '🌟 Sehr gut! Super gemalt!';
|
||||
document.getElementById('feedback').style.color = '#4ade80';
|
||||
speak(`Sehr gut! Du hast den Buchstaben ${currentLetter} toll gemalt!`);
|
||||
|
||||
// Automatisch nächster nach 2 Sekunden
|
||||
setTimeout(nextLetter, 2000);
|
||||
} else {
|
||||
document.getElementById('feedback').textContent = '✏️ Versuch es nochmal! Male den Buchstaben größer.';
|
||||
document.getElementById('feedback').style.color = '#feca57';
|
||||
speak('Versuch es nochmal. Male den Buchstaben größer und deutlicher.');
|
||||
}
|
||||
}
|
||||
|
||||
function speak(text) {
|
||||
if (!synth) return;
|
||||
const utterance = new SpeechSynthesisUtterance(text);
|
||||
utterance.lang = 'de-DE';
|
||||
utterance.rate = 0.8;
|
||||
utterance.pitch = 1.2;
|
||||
synth.speak(utterance);
|
||||
}
|
||||
|
||||
// Event listeners
|
||||
canvas.addEventListener('mousedown', startDraw);
|
||||
canvas.addEventListener('mousemove', draw);
|
||||
canvas.addEventListener('mouseup', stopDraw);
|
||||
canvas.addEventListener('mouseout', stopDraw);
|
||||
canvas.addEventListener('touchstart', startDraw);
|
||||
canvas.addEventListener('touchmove', draw);
|
||||
canvas.addEventListener('touchend', stopDraw);
|
||||
|
||||
// Init
|
||||
initGrid();
|
||||
clearCanvas();
|
||||
updateDisplay();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user