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.
This commit is contained in:
219
ferien.html
Normal file
219
ferien.html
Normal file
@@ -0,0 +1,219 @@
|
||||
<!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>
|
||||
Reference in New Issue
Block a user