<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Simulasi Siklus Air - Media Belajar Kelas 5</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
@import url('https://fonts.googleapis.com/css2?family=Fredoka:wght@400;600&display=swap');
body {
font-family: 'Fredoka', sans-serif;
background-color: #f0fdfa;
overflow-x: hidden;
}
.sky {
background: linear-gradient(to bottom, #38bdf8, #bae6fd);
height: 300px;
position: relative;
overflow: hidden;
}
.ground {
background: linear-gradient(to bottom, #16a34a, #15803d);
height: 150px;
position: relative;
}
/* Animasi Laut */
.sea {
background: linear-gradient(to bottom, #0284c7, #075985);
width: 45%;
height: 100%;
position: absolute;
right: 0;
border-top-left-radius: 100% 20%;
overflow: hidden;
}
.sea-wave {
position: absolute;
width: 200%;
height: 100%;
background: rgba(255,255,255,0.1);
top: 0;
left: 0;
animation: waveMove 8s infinite linear;
border-top-left-radius: 100% 20%;
}
@keyframes waveMove {
0% { transform: translateX(0); }
100% { transform: translateX(-50%); }
}
/* Animasi Matahari */
.sun {
position: absolute;
top: 20px;
left: 50px;
font-size: 60px;
filter: drop-shadow(0 0 20px yellow);
animation: pulse 3s infinite;
z-index: 10;
}
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.15); }
}
/* Evaporasi (Uap Air) */
.vapor {
position: absolute;
bottom: 20px;
right: 120px;
font-size: 24px;
opacity: 0;
z-index: 5;
}
.animate-evaporation {
animation: rise 4s infinite linear;
}
@keyframes rise {
0% { transform: translateY(0); opacity: 0; }
50% { opacity: 0.8; }
100% { transform: translateY(-180px); opacity: 0; }
}
/* Awan Bergerak */
.cloud {
position: absolute;
font-size: 80px;
color: white;
transition: all 2s ease-in-out;
filter: drop-shadow(0 5px 15px rgba(0,0,0,0.1));
animation: floatCloud 20s infinite linear;
}
@keyframes floatCloud {
0% { transform: translateX(0); }
50% { transform: translateX(-100px); }
100% { transform: translateX(0); }
}
.cloud-dark {
filter: grayscale(1) brightness(0.4) drop-shadow(0 10px 20px rgba(0,0,0,0.3));
}
/* Hujan */
.rain-drop {
position: absolute;
background-color: #e0f2fe;
width: 2px;
height: 15px;
animation: fall 0.8s infinite linear;
}
@keyframes fall {
to { transform: translateY(320px); }
}
/* Burung Terbang */
.bird {
position: absolute;
font-size: 20px;
animation: flyBird 15s infinite linear;
}
@keyframes flyBird {
0% { left: -50px; top: 100px; }
100% { left: 110%; top: 50px; }
}
.fade-in {
animation: fadeIn 0.5s ease-out forwards;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
</style>
</head>
<body class="p-4 md:p-8">
<div class="max-w-6xl mx-auto">
<!-- Header -->
<header class="bg-white rounded-3xl shadow-lg p-6 mb-8 flex flex-col md:flex-row justify-between items-center border-b-8 border-blue-500 gap-4">
<div class="flex items-center gap-4">
<div class="bg-blue-100 p-3 rounded-2xl text-3xl">🌊</div>
<div>
<h1 class="text-2xl font-bold text-blue-800">Media Interaktif: Siklus Air</h1>
<p class="text-sm text-gray-500 font-medium">Bahan Ajar IPAS Kelas 5 SD - Kurikulum Merdeka</p>
</div>
</div>
<button onclick="playFullCycle()" class="bg-blue-600 text-white px-8 py-3 rounded-full font-bold hover:bg-blue-700 transition-all shadow-lg flex items-center gap-2 active:scale-95">
<span>▶️</span> Putar Animasi Lengkap
</button>
</header>
<div class="grid grid-cols-1 lg:grid-cols-12 gap-8">
<!-- Layar Animasi (Visual Utama) -->
<div class="lg:col-span-8 bg-white p-4 rounded-[3rem] shadow-2xl border-4 border-blue-50">
<div id="simulation-screen" class="rounded-[2rem] overflow-hidden relative border-4 border-blue-100 shadow-inner">
<!-- Langit -->
<div class="sky">
<div class="sun">☀️</div>
<!-- Burung -->
<div class="bird">🕊️</div>
<div class="bird" style="animation-delay: 5s; top: 150px;">🕊️</div>
<!-- Awan -->
<div id="cloud1" class="cloud" style="top: 40px; left: 300px;">☁️</div>
<div id="cloud2" class="cloud" style="top: 100px; left: 550px;">☁️</div>
<!-- Hujan (Hidden by default) -->
<div id="rain-container" class="hidden absolute inset-0"></div>
<!-- Uap Air -->
<div id="vapor-container" class="absolute inset-0"></div>
</div>
<!-- Tanah & Laut -->
<div class="ground">
<div class="sea">
<div class="sea-wave"></div>
<div class="absolute bottom-5 right-10 text-2xl opacity-50">🐟</div>
</div>
<!-- Objek Daratan -->
<div class="absolute left-10 bottom-12 text-5xl">🌳</div>
<div class="absolute left-32 bottom-8 text-6xl">⛰️</div>
<div class="absolute left-56 bottom-6 text-4xl">🏠</div>
<!-- Aliran Air Infiltrasi -->
<div id="ground-water" class="hidden absolute left-0 bottom-0 w-full h-2 bg-blue-400/30"></div>
</div>
<!-- Label Nama Proses -->
<div id="process-label" class="absolute top-10 right-10 bg-white/95 px-6 py-3 rounded-2xl font-bold text-blue-700 shadow-2xl opacity-0 transition-all border-2 border-blue-200">
TAHAP: EVAPORASI
</div>
</div>
<!-- Kontrol Manual -->
<div class="mt-8 flex flex-wrap justify-center gap-3">
<button onclick="showStep(0)" class="px-5 py-2 bg-blue-50 border border-blue-100 rounded-xl text-xs font-bold text-blue-700 hover:bg-blue-600 hover:text-white transition-all shadow-sm">1. Evaporasi</button>
<button onclick="showStep(1)" class="px-5 py-2 bg-blue-50 border border-blue-100 rounded-xl text-xs font-bold text-blue-700 hover:bg-blue-600 hover:text-white transition-all shadow-sm">2. Kondensasi</button>
<button onclick="showStep(2)" class="px-5 py-2 bg-blue-50 border border-blue-100 rounded-xl text-xs font-bold text-blue-700 hover:bg-blue-600 hover:text-white transition-all shadow-sm">3. Presipitasi</button>
<button onclick="showStep(3)" class="px-5 py-2 bg-blue-50 border border-blue-100 rounded-xl text-xs font-bold text-blue-700 hover:bg-blue-600 hover:text-white transition-all shadow-sm">4. Infiltrasi</button>
</div>
</div>
<!-- Panel Penjelasan -->
<div class="lg:col-span-4 flex flex-col gap-6">
<div id="desc-box" class="bg-white p-8 rounded-[2.5rem] shadow-xl border-t-8 border-yellow-400 min-h-[400px] flex flex-col relative overflow-hidden">
<div class="absolute -right-4 -top-4 text-8xl opacity-5">💧</div>
<h3 id="step-title" class="text-2xl font-bold text-gray-800 mb-6">Halo, Anak Hebat! 👋</h3>
<div id="step-content" class="fade-in">
<p id="step-text" class="text-gray-600 leading-relaxed text-lg">Ayo kita pelajari bagaimana hujan bisa tercipta melalui siklus air. Klik tombol <b>Putar Animasi</b> untuk memulai petualangan air!</p>
</div>
<div id="fun-fact" class="mt-auto bg-blue-50 p-5 rounded-3xl border border-blue-100 shadow-inner">
<p class="text-xs font-bold text-blue-800 uppercase mb-2 flex items-center gap-2"><span>💡</span> Tahukah Kamu?</p>
<p class="text-sm text-blue-700 italic">"Air yang kita minum hari ini mungkin saja pernah diminum oleh dinosaurus jutaan tahun lalu, karena air hanya terus berputar!"</p>
</div>
</div>
<!-- Indikator Progress -->
<div class="bg-blue-900 p-8 rounded-[2.5rem] text-white shadow-2xl">
<h4 class="text-sm font-bold mb-6 flex items-center gap-2 uppercase tracking-widest text-blue-300">Statistik Siklus:</h4>
<div class="space-y-4">
<div class="flex items-center justify-between">
<span class="text-xs font-medium opacity-80">Penguapan</span>
<div id="prog-1" class="w-6 h-6 rounded-full border-2 border-blue-400 transition-colors"></div>
</div>
<div class="flex items-center justify-between">
<span class="text-xs font-medium opacity-80">Pembentukan Awan</span>
<div id="prog-2" class="w-6 h-6 rounded-full border-2 border-blue-400 transition-colors"></div>
</div>
<div class="flex items-center justify-between">
<span class="text-xs font-medium opacity-80">Turun Hujan</span>
<div id="prog-3" class="w-6 h-6 rounded-full border-2 border-blue-400 transition-colors"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
const steps = [
{
title: "1. Evaporasi (Penguapan)",
text: "Panas matahari menyebabkan air di laut dan sungai menguap ke udara. <b>Air berubah wujud dari cair menjadi gas (uap air)</b> dan naik menuju langit.",
label: "EVAPORASI"
},
{
title: "2. Kondensasi (Pengembunan)",
text: "Di atas sana, udara sangat dingin. Uap air berubah kembali menjadi titik-titik air kecil yang berkumpul membentuk <b>Awan</b>. Semakin banyak air, awan akan menjadi hitam dan berat.",
label: "KONDENSASI"
},
{
title: "3. Presipitasi (Hujan)",
text: "Awan yang sudah sangat berat tidak bisa lagi menampung air. Akhirnya, air jatuh kembali ke bumi dalam bentuk <b>Hujan</b>, salju, atau es.",
label: "PRESIPITASI"
},
{
title: "4. Infiltrasi (Penyerapan)",
text: "Air hujan yang jatuh ke tanah akan diserap oleh akar pohon atau masuk ke dalam pori-pori tanah. Air ini akan kembali mengalir menuju laut untuk memulai siklus lagi.",
label: "INFILTRASI"
}
];
function createRain() {
const container = document.getElementById('rain-container');
container.innerHTML = '';
for (let i = 0; i < 60; i++) {
const drop = document.createElement('div');
drop.className = 'rain-drop';
drop.style.left = Math.random() * 100 + '%';
drop.style.top = '-' + Math.random() * 100 + 'px';
drop.style.animationDelay = Math.random() * 1 + 's';
drop.style.opacity = Math.random();
container.appendChild(drop);
}
}
function createVapor() {
const container = document.getElementById('vapor-container');
container.innerHTML = '';
for (let i = 0; i < 8; i++) {
const v = document.createElement('div');
v.className = 'vapor animate-evaporation';
v.innerText = '💨';
v.style.right = (80 + (i * 35)) + 'px';
v.style.animationDelay = (i * 0.4) + 's';
container.appendChild(v);
}
}
function resetSimulation() {
document.getElementById('rain-container').classList.add('hidden');
document.getElementById('vapor-container').innerHTML = '';
document.getElementById('cloud1').classList.remove('cloud-dark');
document.getElementById('cloud2').classList.remove('cloud-dark');
document.getElementById('cloud1').style.transform = 'scale(1)';
document.getElementById('cloud2').style.transform = 'scale(1)';
document.getElementById('process-label').style.opacity = '0';
document.getElementById('ground-water').classList.add('hidden');
// Reset Progress
for(let i=1; i<=3; i++) {
document.getElementById('prog-'+i).classList.remove('bg-blue-400', 'bg-green-400', 'shadow-[0_0_10px_white]');
}
}
async function playFullCycle() {
const label = document.getElementById('process-label');
// Tahap 1: Evaporasi
showStep(0);
createVapor();
label.innerText = "TAHAP 1: EVAPORASI";
label.style.opacity = '1';
document.getElementById('prog-1').classList.add('bg-green-400', 'shadow-[0_0_10px_white]');
await new Promise(r => setTimeout(r, 4500));
// Tahap 2: Kondensasi
showStep(1);
document.getElementById('vapor-container').innerHTML = '';
label.innerText = "TAHAP 2: KONDENSASI";
document.getElementById('cloud1').classList.add('cloud-dark');
document.getElementById('cloud2').classList.add('cloud-dark');
document.getElementById('cloud1').style.transform = 'scale(1.4)';
document.getElementById('cloud2').style.transform = 'scale(1.2)';
document.getElementById('prog-2').classList.add('bg-green-400', 'shadow-[0_0_10px_white]');
await new Promise(r => setTimeout(r, 4500));
// Tahap 3: Presipitasi
showStep(2);
label.innerText = "TAHAP 3: PRESIPITASI";
document.getElementById('rain-container').classList.remove('hidden');
createRain();
document.getElementById('prog-3').classList.add('bg-green-400', 'shadow-[0_0_10px_white]');
await new Promise(r => setTimeout(r, 5000));
// Tahap 4: Infiltrasi
showStep(3);
label.innerText = "TAHAP 4: INFILTRASI";
document.getElementById('rain-container').classList.add('hidden');
document.getElementById('ground-water').classList.remove('hidden');
await new Promise(r => setTimeout(r, 4000));
// Selesai
label.innerText = "SIKLUS TERUS BERPUTAR";
document.getElementById('step-title').innerText = "Hebat! Siklus Selesai.";
document.getElementById('step-text').innerText = "Begitulah cara air bergerak di bumi kita. Dari laut, ke langit, lalu kembali lagi ke tanah. Alam sangat menakjubkan, ya!";
setTimeout(resetSimulation, 3000);
}
function showStep(index) {
const data = steps[index];
if (!data) return;
const title = document.getElementById('step-title');
const text = document.getElementById('step-text');
const content = document.getElementById('step-content');
content.classList.remove('fade-in');
void content.offsetWidth; // trigger reflow
content.classList.add('fade-in');
title.innerHTML = data.title;
text.innerHTML = data.text;
// Manual trigger visual changes based on click
resetSimulation();
if(index === 0) { createVapor(); }
if(index === 1) {
document.getElementById('cloud1').classList.add('cloud-dark');
document.getElementById('cloud1').style.transform = 'scale(1.4)';
}
if(index === 2) {
document.getElementById('cloud1').classList.add('cloud-dark');
document.getElementById('rain-container').classList.remove('hidden');
createRain();
}
if(index === 3) {
document.getElementById('ground-water').classList.remove('hidden');
}
}
</script>
</body>
</html>