Files
Oeffentlich/ferien.html
Teacher 8270ea7609 Dateien nach "/" hochladen
Version 1 der Hamburger Ferien-Datei. Es werden die nächsten Ferien in HTML angezeigt, die Termine stehen als Array in der Datei. Die Termine gelten bis 2030. Es wurde KI zur Erstellung genutzt.
2026-03-11 15:03:49 +01:00

219 lines
11 KiB
HTML

<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ferien-Countdown Hamburg</title>
<script>
// Der Datensatz im Header - Quelle: BSB Hamburg (Stand 2023):
// https://www.hamburg.de/politik-und-verwaltung/behoerden/bsfb/veroeffentlichungen/pressemeldungen/2023-01-19-bsb-ferientermine-2024-2030-veroeffentlicht-234406
const holidayData = [
{ n: "Frühjahrsferien", d: "2025-03-10" }, { n: "Pfingstferien", d: "2025-05-26" }, { n: "Sommerferien", d: "2025-07-24" }, { n: "Herbstferien", d: "2025-10-20" }, { n: "Weihnachtsferien", d: "2025-12-17" },
{ n: "Frühjahrsferien", d: "2026-03-02" }, { n: "Pfingstferien", d: "2026-05-11" }, { n: "Sommerferien", d: "2026-07-09" }, { n: "Herbstferien", d: "2026-10-19" }, { n: "Weihnachtsferien", d: "2026-12-21" },
{ n: "Frühjahrsferien", d: "2027-03-01" }, { n: "Pfingstferien", d: "2027-05-07" }, { n: "Sommerferien", d: "2027-07-01" }, { n: "Herbstferien", d: "2027-10-11" }, { n: "Weihnachtsferien", d: "2027-12-20" },
{ n: "Frühjahrsferien", d: "2028-03-06" }, { n: "Pfingstferien", d: "2028-05-22" }, { n: "Sommerferien", d: "2028-07-03" }, { n: "Herbstferien", d: "2028-10-02" }, { n: "Weihnachtsferien", d: "2028-12-18" },
{ n: "Frühjahrsferien", d: "2029-03-05" }, { n: "Pfingstferien", d: "2029-05-11" }, { n: "Sommerferien", d: "2029-07-02" }, { n: "Herbstferien", d: "2029-10-01" }, { n: "Weihnachtsferien", d: "2029-12-21" },
{ n: "Frühjahrsferien", d: "2030-03-04" }, { n: "Pfingstferien", d: "2030-05-20" }, { n: "Sommerferien", d: "2030-07-04" }
];
</script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body, html {
height: 100%;
font-family: 'Segoe UI', Arial, sans-serif;
color: white;
background-color: #000000;
overflow: hidden;
}
.holiday-container {
display: flex;
flex-direction: column;
height: 100vh;
width: 100%;
padding: 12px;
gap: 12px;
}
.row {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
position: relative;
overflow: hidden;
border-radius: 15px;
border: 1px solid rgba(255, 255, 255, 0.2);
}
canvas { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 1; }
.holiday-row canvas { opacity: 0.8; }
.row-content { position: relative; z-index: 2; padding: 10px; }
.header-row {
background: linear-gradient(to bottom, #a5dcf0, #e0f6ff);
border-color: rgba(255, 255, 255, 0.4);
}
.header-row h1 { color: #2c3e50; text-shadow: 1px 1px 2px rgba(255,255,255,0.8); }
.bg-fruehjahr { background-color: #3498db; }
.bg-pfingsten { background-color: #ffdf00; }
.bg-sommer { background-color: #e67e22; }
.bg-herbst { background-color: #c0392b; }
.bg-weihnachten { background-color: #2c3e50; }
h1 { font-size: clamp(1.5rem, 6vw, 2.5rem); text-transform: uppercase; letter-spacing: 4px; }
h2 { font-size: clamp(1rem, 5vw, 1.7rem); margin-bottom: 2px; text-shadow: 2px 2px 10px rgba(0,0,0,0.4); }
.date-info { font-size: 0.85rem; margin-bottom: 8px; opacity: 0.9; }
.bg-pfingsten h2, .bg-pfingsten .date-info { color: #2c3e50; text-shadow: none; }
.counter {
font-size: clamp(0.9rem, 4vw, 1.4rem); font-weight: bold;
font-family: 'Courier New', monospace; background: rgba(0, 0, 0, 0.85);
padding: 10px 0; border-radius: 6px; border: 1px solid rgba(255,255,255,0.4);
width: 320px; display: inline-block; text-align: center; color: white !important;
}
</style>
</head>
<body onload="init()">
<div class="holiday-container" id="main-container">
<div class="row header-row">
<canvas id="header-canvas"></canvas>
<div class="row-content">
<h1>Ferien Hamburg</h1>
</div>
</div>
</div>
<script>
function init() {
const container = document.getElementById('main-container');
const now = new Date();
const upcoming = holidayData.map(item => ({ name: item.n, start: new Date(item.d) }))
.filter(item => item.start > now).sort((a, b) => a.start - b.start).slice(0, 5);
drawHeader(document.getElementById('header-canvas'));
upcoming.forEach((holiday, i) => {
const type = getBgType(holiday.name);
const row = document.createElement('div');
row.className = `row holiday-row bg-${type}`;
const canvas = document.createElement('canvas');
const content = document.createElement('div');
content.className = 'row-content';
const dateStr = holiday.start.toLocaleDateString('de-DE', { day: '2-digit', month: 'long', year: 'numeric' });
content.innerHTML = `<h2>${holiday.name} ${holiday.start.getFullYear()}</h2><p class="date-info">Beginnt am: ${dateStr}</p><div class="counter" id="t-${i}">Lädt...</div>`;
row.append(canvas, content);
container.append(row);
runTimer(holiday.start, "t-" + i, i === 0);
runAnimation(type, canvas);
});
}
function runTimer(target, id, showFull) {
function update() {
const diff = target - new Date();
const el = document.getElementById(id);
if (!el) return;
if (diff <= 0) { el.innerText = "FERIEN!"; return; }
const d = Math.floor(diff / 86400000);
if (showFull) {
const h = Math.floor((diff % 86400000) / 3600000), m = Math.floor((diff % 3600000) / 60000), s = Math.floor((diff % 60000) / 1000);
el.innerText = `${d}T ${h}S ${m}M ${s}S`;
} else { el.innerText = `${d} Tage`; }
}
update();
if (showFull) setInterval(update, 1000);
}
function getBgType(n) {
const name = n.toLowerCase();
if (name.includes("frühjahr")) return "fruehjahr";
if (name.includes("pfingst") || name.includes("himmelfahrt")) return "pfingsten";
if (name.includes("sommer")) return "sommer";
if (name.includes("herbst")) return "herbst";
return "weihnachten";
}
function drawHeader(canvas) {
const ctx = canvas.getContext('2d');
let w, h, clouds = [], gulls = [];
const res = () => { w = canvas.width = canvas.offsetWidth; h = canvas.height = canvas.offsetHeight; clouds = []; gulls = [];
for(let i=0; i<5; i++) clouds.push({x: Math.random()*w, y: Math.random()*h*0.35, s: Math.random()*0.4+0.3});
for(let i=0; i<8; i++) gulls.push({x: Math.random()*w, y: Math.random()*(h*0.6), vx: Math.random()*1.2+0.6, wing: Math.random()*Math.PI, ws: Math.random()*0.15+0.1});
};
window.addEventListener('resize', res); res();
function draw() {
ctx.clearRect(0,0,w,h);
ctx.fillStyle = "rgba(255,255,255,0.8)";
clouds.forEach(c => {
c.x += c.s * 0.3; if(c.x > w + 100) c.x = -100;
ctx.beginPath(); ctx.arc(c.x, c.y, 30*c.s, 0, 7); ctx.arc(c.x+25*c.s, c.y-12*c.s, 35*c.s, 0, 7); ctx.fill();
});
ctx.fillStyle = "#3498db"; ctx.fillRect(0, h-10, w, 10);
gulls.forEach(g => {
g.x += g.vx; g.wing += g.ws; if(g.x > w + 40) g.x = -40;
ctx.save(); ctx.strokeStyle = "#444"; ctx.lineWidth = 2.5; ctx.beginPath();
let flap = Math.sin(g.wing) * 7;
ctx.moveTo(g.x - 12, g.y + flap); ctx.lineTo(g.x, g.y); ctx.lineTo(g.x + 12, g.y + flap);
ctx.stroke(); ctx.strokeStyle = "white"; ctx.lineWidth = 1.2; ctx.stroke();
ctx.fillStyle = "#FFD700"; ctx.beginPath(); ctx.arc(g.x+1, g.y-1, 1.8, 0, 7); ctx.fill(); ctx.restore();
});
requestAnimationFrame(draw);
}
draw();
}
function runAnimation(type, canvas) {
const ctx = canvas.getContext('2d');
let w, h, p = [];
const res = () => { w = canvas.width = canvas.offsetWidth; h = canvas.height = canvas.offsetHeight; };
window.addEventListener('resize', res); res();
const count = type === 'fruehjahr' ? 180 : 60;
for(let i=0; i<count; i++) {
let color = "white";
if(type === 'pfingsten') color = '#e84393';
else if(type === 'herbst') color = ['#ff7675', '#fdcb6e', '#d63031'][i%3];
p.push({ x: Math.random()*w, y: Math.random()*h, s: type === 'fruehjahr' ? Math.random()*25+15 : Math.random()*8+4, vx: type === 'herbst' ? (Math.random()*-3-2) : (Math.random()*2-1), vy: type === 'fruehjahr' ? Math.random()*15+20 : Math.random()*2+1, c: color });
}
function draw() {
ctx.clearRect(0,0,w,h);
p.forEach(part => {
ctx.fillStyle = ctx.strokeStyle = part.c;
part.x += part.vx; part.y += part.vy;
let buffer = part.s * 4;
if(part.y > h + buffer) { part.y = -buffer; part.x = Math.random() * w; }
if(part.x < -buffer) { part.x = w + buffer; part.y = Math.random() * h; }
if(part.x > w + buffer) { part.x = -buffer; }
if (type === 'fruehjahr') {
ctx.lineWidth = 2; ctx.beginPath(); ctx.moveTo(part.x, part.y); ctx.lineTo(part.x+part.vx, part.y+part.s); ctx.stroke();
} else if (type === 'pfingsten') {
ctx.beginPath(); ctx.ellipse(part.x, part.y, part.s, part.s/1.5, part.y/20, 0, 7); ctx.fill();
} else if (type === 'herbst') {
ctx.save(); ctx.translate(part.x, part.y); ctx.rotate(part.y/30); ctx.fillRect(0, 0, part.s*2, part.s); ctx.restore();
} else if (type === 'sommer') {
let flicker = Math.abs(Math.sin(Date.now()/800 + p.indexOf(part))) * 18 + 12;
if(part.y > h + 50) part.y = -50;
ctx.fillStyle = "rgba(255, 255, 255, 0.4)"; ctx.beginPath(); ctx.arc(part.x, part.y, flicker, 0, 7); ctx.fill();
} else {
ctx.beginPath(); ctx.arc(part.x, part.y, part.s/3, 0, 7); ctx.fill();
}
});
requestAnimationFrame(draw);
}
draw();
}
</script>
</body>
</html>