146 lines
8.1 KiB
Plaintext
146 lines
8.1 KiB
Plaintext
---
|
|
// src/components/SubpageRain.astro
|
|
---
|
|
<script is:inline>
|
|
window.rainData = function() {
|
|
return {
|
|
rainIntensity: 50,
|
|
wind: 0,
|
|
lofiFilter: 800,
|
|
drops: [],
|
|
audioCtx: null,
|
|
noiseNode: null,
|
|
filterNode: null,
|
|
gainNode: null,
|
|
|
|
generateDrops(val) {
|
|
this.drops = [];
|
|
for(let i=0; i<val; i++) this.drops.push({ left: Math.random()*100, speed: 0.5+Math.random()*0.5, delay: Math.random()*2 });
|
|
},
|
|
|
|
initAudio() {
|
|
if (this.audioCtx) return;
|
|
try {
|
|
this.audioCtx = new (window.AudioContext || window.webkitAudioContext)();
|
|
|
|
// --- REGEN-SOUND ---
|
|
let bufferSize = 2 * this.audioCtx.sampleRate;
|
|
let noiseBuffer = this.audioCtx.createBuffer(1, bufferSize, this.audioCtx.sampleRate);
|
|
let output = noiseBuffer.getChannelData(0);
|
|
for (let i = 0; i < bufferSize; i++) {
|
|
output[i] = Math.random() * 2 - 1;
|
|
}
|
|
|
|
this.noiseNode = this.audioCtx.createBufferSource();
|
|
this.noiseNode.buffer = noiseBuffer;
|
|
this.noiseNode.loop = true;
|
|
|
|
this.filterNode = this.audioCtx.createBiquadFilter();
|
|
this.filterNode.type = 'lowpass';
|
|
this.filterNode.frequency.setValueAtTime(this.lofiFilter, this.audioCtx.currentTime);
|
|
|
|
this.gainNode = this.audioCtx.createGain();
|
|
this.gainNode.gain.setValueAtTime(this.rainIntensity / 200 * 0.05, this.audioCtx.currentTime);
|
|
|
|
this.noiseNode.connect(this.filterNode);
|
|
this.filterNode.connect(this.gainNode);
|
|
this.gainNode.connect(this.audioCtx.destination);
|
|
|
|
this.noiseNode.start();
|
|
|
|
} catch(e) {
|
|
console.log('Audio failed', e);
|
|
}
|
|
},
|
|
|
|
updateAudio() {
|
|
if (this.gainNode) {
|
|
this.gainNode.gain.linearRampToValueAtTime(this.rainIntensity / 200 * 0.05, this.audioCtx.currentTime + 0.2);
|
|
}
|
|
if (this.filterNode) {
|
|
this.filterNode.frequency.linearRampToValueAtTime(this.lofiFilter, this.audioCtx.currentTime + 0.2);
|
|
}
|
|
}
|
|
};
|
|
}
|
|
</script>
|
|
|
|
<!-- Subpage: Rain Detail -->
|
|
<div x-show="currentPage === 'page-rain'" x-cloak x-transition:enter="transition ease-out duration-500" x-transition:enter-start="opacity-0 translate-y-4" x-transition:enter-end="opacity-100 translate-y-0" class="min-h-screen pt-28 pb-24 px-6 lg:px-8 bg-stone-950 relative overflow-hidden"
|
|
x-data="window.rainData()"
|
|
x-init="generateDrops(rainIntensity); $watch('rainIntensity', value => { generateDrops(value); updateAudio() }); $watch('lofiFilter', value => updateAudio()); $watch('currentPage', val => { if(val === 'page-rain') { initAudio(); } })">
|
|
|
|
<!-- Rain Container (Full Screen on this page) -->
|
|
<div class="absolute inset-0 pointer-events-none z-0">
|
|
<template x-for="drop in drops">
|
|
<div class="absolute bg-emerald-400/30 w-0.5 h-8"
|
|
:style="`left: ${drop.left}%; top: -20px; animation: fall ${drop.speed}s linear infinite; animation-delay: ${drop.delay}s; transform: rotate(${wind}deg)`">
|
|
</div>
|
|
</template>
|
|
</div>
|
|
|
|
<div class="max-w-4xl mx-auto space-y-12 relative z-10">
|
|
<button @click="currentPage = 'main'" class="text-stone-400 hover:text-white transition-colors font-semibold text-xs uppercase tracking-wider flex items-center gap-2 bg-stone-900 px-5 py-2.5 rounded-lg border border-stone-800 hover:border-stone-700">
|
|
<i class="fa-solid fa-arrow-left"></i> Zurück zur Übersicht
|
|
</button>
|
|
|
|
<div class="border-b border-stone-800 pb-6">
|
|
<span class="text-xs text-emerald-500 font-mono uppercase tracking-widest block mb-2">Atmosphäre & Ökologie</span>
|
|
<h1 class="text-4xl sm:text-5xl font-luxury font-bold text-white">Regen für Gemütlichkeit</h1>
|
|
</div>
|
|
|
|
<!-- Controls -->
|
|
<div class="glass p-8 rounded-2xl border border-stone-800 space-y-6">
|
|
<!-- Intensity -->
|
|
<div>
|
|
<label class="block text-xs font-mono text-stone-500 uppercase mb-2 tracking-widest">Regen-Intensität: <span x-text="rainIntensity" class="text-emerald-400"></span> Tropfen</label>
|
|
<input type="range" min="0" max="200" x-model="rainIntensity" class="w-full h-2 bg-stone-800 rounded-lg appearance-none cursor-pointer accent-emerald-500">
|
|
</div>
|
|
|
|
<!-- Wind -->
|
|
<div>
|
|
<label class="block text-xs font-mono text-stone-500 uppercase mb-2 tracking-widest">Windstärke (Neigung): <span x-text="wind" class="text-emerald-400"></span>°</label>
|
|
<input type="range" min="-45" max="45" x-model="wind" class="w-full h-2 bg-stone-800 rounded-lg appearance-none cursor-pointer accent-emerald-500">
|
|
</div>
|
|
|
|
<!-- Lofi Filter -->
|
|
<div>
|
|
<label class="block text-xs font-mono text-stone-500 uppercase mb-2 tracking-widest">Lofi-Filter (Muffigkeit): <span x-text="lofiFilter" class="text-emerald-400"></span> Hz</label>
|
|
<input type="range" min="200" max="2000" x-model="lofiFilter" class="w-full h-2 bg-stone-800 rounded-lg appearance-none cursor-pointer accent-emerald-500">
|
|
</div>
|
|
|
|
<div class="flex justify-between text-xs text-stone-600 font-mono pt-4 border-t border-stone-800">
|
|
<span>Sound läuft automatisch</span>
|
|
<span class="text-emerald-400">Realtime Web Audio Rain</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- YouTube Player with Vocals/Diverse Beats -->
|
|
<div class="glass p-6 rounded-2xl border border-stone-800 space-y-4">
|
|
<div>
|
|
<span class="block text-xs font-mono text-stone-500 uppercase mb-1 tracking-widest">Musik (Lofi mit Vocals)</span>
|
|
<span class="text-xs text-stone-400">Echte Tracks für mehr Vielfalt & Gesang</span>
|
|
</div>
|
|
<div class="rounded-lg overflow-hidden border border-stone-800 aspect-video">
|
|
<!-- Größerer Player für bessere Bedienung -->
|
|
<iframe width="100%" height="100%" src="https://www.youtube.com/embed/jfKfPfyJRdk" title="Lofi Hip Hop" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
|
</div>
|
|
<p class="text-xs text-stone-500 leading-relaxed">Da echte Vocals und komplexe Beats nicht im Browser generiert werden können, nutzen wir diesen Stream. Spiele ihn ab und nutze die Regler oben für den Regensound!</p>
|
|
</div>
|
|
|
|
<!-- Content -->
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-8 text-stone-400 text-sm leading-relaxed">
|
|
<div class="space-y-4">
|
|
<h3 class="text-white font-bold text-lg">Warum wir den Regen lieben</h3>
|
|
<p>Für viele ist Regen ein Grund, im Haus zu bleiben. Für uns Gärtner ist er der Herzschlag der Natur. Ohne Regen gibt es kein Wachstum, keine Kühlung und keine Erholung für den Boden.</p>
|
|
<p>Mit unserem "Regen-Modus" möchten wir dir die beruhigende Wirkung eines Sommerregens näherbringen. Setz dich hin, dreh die Intensität hoch und genieße die Atmosphäre.</p>
|
|
</div>
|
|
<div class="space-y-4">
|
|
<h3 class="text-white font-bold text-lg">Vom Genuss zur Technik</h3>
|
|
<p>Aber Regen ist nicht nur Atmosphäre. In Zeiten des Klimawandels müssen wir lernen, jeden Tropfen zu nutzen. Hier schließt sich der Kreis zu unserem **Schwammstadt-Prinzip**.</p>
|
|
<p>Wir bauen Gärten, die das Wasser nicht einfach ableiten, sondern wie ein Schwamm aufsaugen und speichern. So schützen wir vor Überflutung und versorgen die Pflanzen in Trockenzeiten.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|