Liveweave: Generative AI Web Editor & HTML/CSS/JS Playground
Initializing
Liveweave
Web
expand_more
home
Home
Palette
Color Explorer
arrow_outward
Polyline
Graphics Editor
arrow_outward
frame_source
Python Playground
arrow_outward
build
Tools
expand_more
restart_alt
Load "Hello Weaver!"
post_add
Generate Lorem ipsum...
code
Format HTML
code_blocks
Format CSS
data_object
Format JavaScript
library_add
Library
expand_more
A
Algolia JS
Animate CSS
Apex Charts JS
B
Bulma CSS
Bootstrap
C
Chart JS
Chartist
Create JS
D
D3
Dojo
F
Foundation
Fullpage JS
G
Granim JS
Google Charts
H
Halfmoon
J
jQuery
M
Materialize
Moment JS
Masonry JS
Milligram CSS
P
Pure CSS
Primer CSS
Popper JS
Pattern CSS
Picnic CSS
R
React JS
Raphael JS
Raisin CSS
S
Semantic UI
Skeleton CSS
Spectre CSS
Tachyons CSS
T
Tailwind
Three JS
U
UI Kit
Vis JS
W
Water CSS
download
Download
expand_more
developer_mode
Download as HTML
folder_zip
Download as .ZIP
cloud_upload
Fork
account_circle
Login
settings
Settings
expand_more
Editor font
14
px
A
A
Night mode
Line number
Mini map
Word wrap
sync_alt
Reset Settings
smart_display
Run
left_panel_close
AI Assistant
dashboard
All
HTML
CSS
JS
visibility
Preview
bolt
Live Preview
terminal
JS Console
<!DOCTYPE html> <html> <head> <title>Weather simulator</title> </head> <body> <!-- Start your code here --> <div class="app"> <header class="topbar"> <div class="brand"> <div class="brand-icon">☁</div> <div> <h1>Weather Simulator</h1> <p>INTERACTIVE WEATHER PLAYGROUND</p> </div> </div> <span class="live-tag">SIMULATION</span> </header> <main class="layout"> <section class="scene-card"> <div class="scene" id="scene"> <div class="sky"></div> <div class="stars" id="stars"></div> <div class="sun" id="sun"></div> <div class="moon" id="moon"></div> <div class="cloud cloud-one"></div> <div class="cloud cloud-two"></div> <div class="cloud cloud-three"></div> <!-- Detailed vector landscape --> <svg class="landscape" viewBox="0 0 900 600" preserveAspectRatio="xMidYMax slice" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"> <defs> <linearGradient id="farRock" x2="0" y2="1"> <stop offset="0" stop-color="#b2c7d2"/> <stop offset="1" stop-color="#6b92a1"/> </linearGradient> <linearGradient id="midRock" x2="0" y2="1"> <stop offset="0" stop-color="#718fa0"/> <stop offset="1" stop-color="#385e70"/> </linearGradient> <linearGradient id="nearRock" x2="0" y2="1"> <stop offset="0" stop-color="#56798a"/> <stop offset="1" stop-color="#26495a"/> </linearGradient> <linearGradient id="ground" x2="0" y2="1"> <stop offset="0" stop-color="#376e64"/> <stop offset="1" stop-color="#173d3c"/> </linearGradient> <linearGradient id="water" x2="0" y2="1"> <stop offset="0" stop-color="#6faaa9"/> <stop offset="1" stop-color="#244f62"/> </linearGradient> <g id="pine"> <path d="M0 0 L0 -54" stroke="#203d38" stroke-width="4"/> <path d="M0 -65 L-12 -43 L-7 -43 L-20 -22 L-12 -22 L-27 -4 L27 -4 L12 -22 L20 -22 L7 -43 L12 -43 Z" fill="#24564b"/> <path d="M0 -65 L-12 -43 L-7 -43 L-20 -22 L-12 -22 L-27 -4 L0 -4 Z" fill="#367b66"/> <path d="M0 -58 L-7 -44 M0 -44 L-12 -26 M0 -29 L-17 -10" fill="none" stroke="#75a28b" stroke-width="1.2" opacity=".55"/> </g> <g id="pineDark"> <path d="M0 0 L0 -70" stroke="#132e30" stroke-width="5"/> <path d="M0 -88 L-15 -59 L-9 -59 L-25 -32 L-16 -32 L-34 -5 L34 -5 L16 -32 L25 -32 L9 -59 L15 -59 Z" fill="#173c3c"/> <path d="M0 -88 L-15 -59 L-9 -59 L-25 -32 L-16 -32 L-34 -5 L0 -5 Z" fill="#28554a"/> </g> </defs> <!-- Distant mountain range --> <path d="M0 380 L65 310 L115 330 L195 185 L245 240 L315 155 L370 220 L440 125 L510 235 L585 165 L660 260 L730 195 L810 290 L900 220 L900 600 L0 600 Z" fill="url(#farRock)"/> <!-- Snow and rocky ridges --> <path d="M151 239 L195 185 L245 240 L216 222 L203 230 L190 211 L178 230 Z" fill="#eef4f5"/> <path d="M276 203 L315 155 L370 220 L336 199 L321 211 L308 185 L297 202 Z" fill="#f0f6f7"/> <path d="M397 177 L440 125 L510 235 L471 203 L451 213 L438 167 L424 193 Z" fill="#f4f8f7"/> <path d="M545 210 L585 165 L635 232 L600 211 L587 221 L573 193 Z" fill="#e7f1f4"/> <!-- Mountain shadow faces --> <path d="M440 125 L510 235 L540 340 L450 370 L456 240 Z" fill="#456e83" opacity=".55"/> <path d="M315 155 L370 220 L410 360 L337 355 L326 236 Z" fill="#517c8e" opacity=".45"/> <path d="M195 185 L245 240 L285 355 L213 370 L208 258 Z" fill="#537b8a" opacity=".4"/> <!-- Middle mountains --> <path d="M0 430 L90 330 L145 370 L240 280 L320 390 L400 295 L475 380 L565 270 L655 385 L745 315 L830 390 L900 330 L900 600 L0 600 Z" fill="url(#midRock)"/> <path d="M240 280 L320 390 L275 359 L256 322 Z" fill="#294f65" opacity=".55"/> <path d="M565 270 L655 385 L600 350 L581 311 Z" fill="#294f65" opacity=".6"/> <path d="M745 315 L830 390 L775 359 Z" fill="#294f65" opacity=".5"/> <!-- Near foothills --> <path d="M0 470 Q100 380 205 430 Q300 355 405 425 Q520 365 635 430 Q760 375 900 445 L900 600 L0 600 Z" fill="url(#nearRock)"/> <!-- Distant forest --> <g opacity=".8"> <use href="#pine" transform="translate(25 458) scale(.6)"/> <use href="#pine" transform="translate(60 445) scale(.7)"/> <use href="#pine" transform="translate(95 438) scale(.8)"/> <use href="#pine" transform="translate(140 445) scale(.65)"/> <use href="#pine" transform="translate(180 438) scale(.75)"/> <use href="#pine" transform="translate(225 428) scale(.8)"/> <use href="#pine" transform="translate(270 439) scale(.65)"/> <use href="#pine" transform="translate(315 420) scale(.85)"/> <use href="#pine" transform="translate(360 435) scale(.65)"/> <use href="#pine" transform="translate(410 420) scale(.8)"/> <use href="#pine" transform="translate(455 437) scale(.7)"/> <use href="#pine" transform="translate(505 425) scale(.8)"/> <use href="#pine" transform="translate(550 438) scale(.65)"/> <use href="#pine" transform="translate(600 430) scale(.8)"/> <use href="#pine" transform="translate(650 440) scale(.7)"/> <use href="#pine" transform="translate(700 429) scale(.8)"/> <use href="#pine" transform="translate(750 440) scale(.7)"/> <use href="#pine" transform="translate(800 428) scale(.8)"/> <use href="#pine" transform="translate(850 445) scale(.7)"/> <use href="#pine" transform="translate(890 440) scale(.8)"/> </g> <!-- Lake --> <path d="M0 478 Q200 470 450 477 Q700 470 900 478 L900 600 L0 600 Z" fill="url(#water)"/> <!-- Lake reflections --> <g stroke="#d6eeea" fill="none" opacity=".25"> <path d="M40 505 H180 M260 520 H390 M530 495 H720 M760 540 H875"/> <path d="M100 548 H260 M340 560 H520 M600 570 H800"/> <path d="M25 585 H150 M450 590 H650"/> </g> <!-- Foreground shoreline --> <path d="M0 565 Q90 540 170 570 Q230 552 310 585 L310 600 L0 600 Z" fill="url(#ground)"/> <path d="M680 590 Q760 550 900 555 L900 600 L680 600 Z" fill="url(#ground)"/> <!-- Foreground pine trees --> <use href="#pineDark" transform="translate(28 575) scale(1.8)"/> <use href="#pineDark" transform="translate(88 570) scale(1.35)"/> <use href="#pineDark" transform="translate(145 580) scale(1.6)"/> <use href="#pineDark" transform="translate(205 588) scale(1.15)"/> <use href="#pineDark" transform="translate(735 590) scale(1.2)"/> <use href="#pineDark" transform="translate(805 578) scale(1.7)"/> <use href="#pineDark" transform="translate(875 585) scale(1.4)"/> </svg> <canvas id="weatherCanvas"></canvas> <div class="lightning" id="lightning"></div> <div class="scene-info"> <div class="scene-label">CURRENT CONDITIONS</div> <div class="temperature" id="temperature">24°</div> <h2 id="weatherTitle">Sunny Skies</h2> <p id="weatherDescription"> A perfect day to enjoy the outdoors. </p> </div> <div class="scene-bottom"> <span id="timeLabel">DAYTIME</span> <span id="windLabel">WIND 20%</span> </div> </div> <div class="scene-caption"> <span>LIVE VECTOR ENVIRONMENT</span> <span>SVG + CANVAS</span> </div> </section> <aside class="control-panel"> <div class="panel-heading"> <span class="eyebrow">ENVIRONMENT CONTROLS</span> <h2>Shape the sky.</h2> <p>Change the weather and watch the landscape respond.</p> </div> <div class="control-section"> <h3>WEATHER CONDITIONS</h3> <div class="weather-grid"> <button class="weather-btn active" data-weather="sunny"> <span class="weather-icon">☀</span>Sunny </button> <button class="weather-btn" data-weather="rain"> <span class="weather-icon">☂</span>Rain </button> <button class="weather-btn" data-weather="snow"> <span class="weather-icon">❄</span>Snow </button> <button class="weather-btn" data-weather="storm"> <span class="weather-icon">⚡</span>Storm </button> <button class="weather-btn" data-weather="fog"> <span class="weather-icon">☰</span>Fog </button> </div> </div> <div class="control-section"> <div class="control-heading"> <h3>WIND INTENSITY</h3> <span id="windValue">20%</span> </div> <input id="windSlider" type="range" min="0" max="100" value="20"> <div class="range-labels"> <span>CALM</span><span>WINDY</span> </div> </div> <div class="control-section"> <div class="control-heading"> <h3>TIME OF DAY</h3> <span id="timeValue">12:00</span> </div> <input id="timeSlider" type="range" min="0" max="24" value="12"> <div class="range-labels"> <span>MIDNIGHT</span><span>NOON</span> <span>MIDNIGHT</span> </div> </div> <button id="randomBtn" class="random-btn"> Randomize Weather </button> <div class="control-footer"> Pure SVG, CSS and JavaScript. No images or external libraries. </div> </aside> </main> <footer class="footer"> <span>ATMOSPHERE / VECTOR EDITION</span> <span>MADE FOR LIVEWEAVE</span> </footer> </div> <!-- End your code here --> </body> </html>
* { box-sizing: border-box; } body { margin: 0; background: #0b101b; color: #f0f4fa; font-family: Arial, sans-serif; } button, input { font: inherit; } button { cursor: pointer; } .app { max-width: 1350px; margin: auto; padding: 30px; } .topbar, .brand, .layout, .scene-caption, .scene-bottom, .control-heading, .range-labels, .footer { display: flex; justify-content: space-between; align-items: center; } .topbar { margin-bottom: 30px; gap: 20px; } .brand { justify-content: flex-start; gap: 14px; } .brand-icon { display: grid; place-items: center; width: 48px; height: 48px; background: #203b4d; color: #80e2d2; border-radius: 13px; font-size: 28px; } .brand h1 { margin: 0; font-size: 22px; letter-spacing: 2px; } .brand p { margin: 5px 0 0; font-size: 10px; letter-spacing: 2px; color: #8b9aaf; } .live-tag { padding: 9px 13px; border: 1px solid #344354; border-radius: 30px; font-size: 10px; letter-spacing: 1px; color: #a9b8c8; } .layout { align-items: stretch; gap: 24px; } .scene-card { flex: 1; min-width: 0; background: #151d2b; border: 1px solid #293446; border-radius: 18px; overflow: hidden; } .scene { position: relative; height: 570px; overflow: hidden; isolation: isolate; background: linear-gradient( 180deg, #5bb6e5 0%, #b4e0eb 65%, #e9d5ae 100% ); transition: background 1s; } .sky { position: absolute; inset: 0; background: radial-gradient( circle at 70% 20%, rgba(255,255,255,.4), transparent 45% ); } .sun { position: absolute; z-index: 1; width: 85px; height: 85px; left: 72%; top: 16%; border-radius: 50%; background: #fff0b0; box-shadow: 0 0 45px #ffe9a1aa, 0 0 120px #ffe9a177; transition: opacity 1s, top 1s; } .moon { position: absolute; z-index: 1; width: 65px; height: 65px; left: 72%; top: 16%; border-radius: 50%; background: #e6edf8; box-shadow: 0 0 45px #c7d6ff77; opacity: 0; transition: opacity 1s; } .stars { position: absolute; inset: 0; opacity: 0; transition: opacity 1s; } .star { position: absolute; width: 2px; height: 2px; background: white; border-radius: 50%; box-shadow: 0 0 5px white; } .cloud { position: absolute; z-index: 2; width: 170px; height: 45px; background: #ffffffbb; border-radius: 50px; filter: blur(9px); opacity: .7; animation: drift 25s linear infinite alternate; } .cloud::before, .cloud::after { content: ""; position: absolute; border-radius: 50%; background: inherit; } .cloud::before { width: 90px; height: 75px; left: 30px; bottom: 7px; } .cloud::after { width: 70px; height: 60px; right: 15px; bottom: 4px; } .cloud-one { top: 18%; left: 5%; } .cloud-two { top: 31%; left: 58%; } .cloud-three { top: 43%; left: 17%; } @keyframes drift { from { margin-left: -30px; } to { margin-left: 50px; } } /* SVG vector landscape */ .landscape { position: absolute; z-index: 3; width: 100%; height: 100%; inset: 0; pointer-events: none; transition: filter 1s; } /* Weather effects */ #weatherCanvas { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 5; pointer-events: none; } .lightning { position: absolute; inset: 0; z-index: 6; background: #e4efff; opacity: 0; pointer-events: none; } .scene-info { position: absolute; z-index: 8; left: 36px; top: 35px; color: white; text-shadow: 0 2px 15px #18304788; } .scene-label { font-size: 10px; letter-spacing: 2px; font-weight: 700; opacity: .8; } .temperature { font-size: 86px; font-weight: 600; letter-spacing: -6px; margin-top: 8px; } .scene-info h2 { font-size: 27px; margin: 0 0 8px; } .scene-info p { margin: 0; max-width: 240px; font-size: 13px; line-height: 1.6; opacity: .85; } .scene-bottom { position: absolute; z-index: 8; bottom: 24px; left: 30px; right: 30px; font-size: 10px; letter-spacing: 1.5px; color: white; } .scene-caption { padding: 17px 22px; color: #8393a8; font-size: 10px; letter-spacing: 1px; } /* Control panel */ .control-panel { width: 335px; flex-shrink: 0; padding: 26px; background: #151d2b; border: 1px solid #293446; border-radius: 18px; } .eyebrow, .control-section h3 { font-size: 10px; letter-spacing: 1.7px; color: #91a4b9; font-weight: 700; } .panel-heading h2 { font-size: 28px; margin: 12px 0; } .panel-heading p { font-size: 13px; color: #91a4b9; line-height: 1.7; } .control-section { margin-top: 28px; padding-top: 22px; border-top: 1px solid #293446; } .control-section h3 { margin: 0 0 16px; } .weather-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 9px; } .weather-btn { display: flex; flex-direction: column; align-items: center; gap: 7px; padding: 13px 4px; border: 1px solid #344255; background: #1e293a; border-radius: 10px; color: #b4c2d2; font-size: 11px; transition: .2s; } .weather-btn:hover { border-color: #6de1c8; } .weather-btn.active { border-color: #6de1c8; background: #244b49; color: #9ef5e3; } .weather-icon { font-size: 24px; } .control-heading h3 { margin: 0; } .control-heading > span { font-size: 12px; color: #77e7d0; } input[type="range"] { width: 100%; margin: 20px 0 12px; accent-color: #6de1c8; cursor: pointer; } .range-labels { color: #75869c; font-size: 9px; letter-spacing: 1px; } .random-btn { width: 100%; padding: 14px; margin-top: 30px; background: #6de1c8; color: #092b2a; border: 0; border-radius: 9px; font-weight: 700; } .random-btn:hover { background: #9cf4e2; } .control-footer { margin-top: 20px; color: #74849a; text-align: center; font-size: 11px; line-height: 1.6; } .footer { margin-top: 28px; font-size: 10px; letter-spacing: 1.4px; color: #74849a; } @media (max-width: 900px) { .layout { flex-direction: column; } .control-panel { width: 100%; } .scene { height: 470px; } .weather-grid { grid-template-columns: repeat(5, 1fr); } } @media (max-width: 540px) { .app { padding: 12px; } .brand h1 { font-size: 17px; } .brand p { font-size: 8px; } .live-tag { display: none; } .scene { height: 440px; } .scene-info { left: 20px; top: 25px; } .temperature { font-size: 68px; } .scene-info h2 { font-size: 23px; } .scene-bottom { left: 20px; right: 20px; } .weather-grid { grid-template-columns: repeat(3, 1fr); } .control-panel { padding: 20px; } }
(function () { const scene = document.getElementById("scene"); const canvas = document.getElementById("weatherCanvas"); const ctx = canvas.getContext("2d"); const title = document.getElementById("weatherTitle"); const description = document.getElementById("weatherDescription"); const temperature = document.getElementById("temperature"); const windSlider = document.getElementById("windSlider"); const timeSlider = document.getElementById("timeSlider"); const windValue = document.getElementById("windValue"); const timeValue = document.getElementById("timeValue"); const windLabel = document.getElementById("windLabel"); const timeLabel = document.getElementById("timeLabel"); const sun = document.getElementById("sun"); const moon = document.getElementById("moon"); const stars = document.getElementById("stars"); const lightning = document.getElementById("lightning"); const landscape = document.querySelector(".landscape"); let weather = "sunny"; let wind = 20; let hour = 12; let particles = []; let width = 0; let height = 0; let lastFrame = 0; let nextLightning = 0; let flashUntil = 0; const weatherData = { sunny: { title: "Sunny Skies", description: "A perfect day to enjoy the outdoors.", temp: 24 }, rain: { title: "Gentle Rain", description: "Raindrops dance across the landscape.", temp: 16 }, snow: { title: "Winter Wonderland", description: "Soft snowflakes drift through the air.", temp: -3 }, storm: { title: "Thunderstorm", description: "Dark clouds gather as lightning strikes.", temp: 19 }, fog: { title: "Misty Morning", description: "A quiet blanket of fog covers the hills.", temp: 11 } }; function random(min, max) { return min + Math.random() * (max - min); } function resizeCanvas() { width = scene.clientWidth; height = scene.clientHeight; const dpr = Math.min(window.devicePixelRatio || 1, 2); canvas.width = Math.round(width * dpr); canvas.height = Math.round(height * dpr); ctx.setTransform(dpr, 0, 0, dpr, 0, 0); createParticles(); } function createParticles() { particles = []; let count = 0; if (weather === "rain") count = 150; if (weather === "snow") count = 110; if (weather === "storm") count = 220; if (weather === "fog") count = 36; for (let i = 0; i < count; i++) { particles.push({ x: random(0, width), y: random(0, height), size: random(1, 4), speed: random(0.6, 1.6), phase: random(0, Math.PI * 2) }); } } function createStars() { stars.replaceChildren(); for (let i = 0; i < 65; i++) { const star = document.createElement("span"); star.className = "star"; star.style.left = random(0, 100) + "%"; star.style.top = random(0, 65) + "%"; star.style.opacity = random(0.3, 1); stars.appendChild(star); } } function updateWeather() { const data = weatherData[weather]; title.textContent = data.title; description.textContent = data.description; temperature.textContent = data.temp + "\u00B0"; document.querySelectorAll(".weather-btn").forEach( function (button) { button.classList.toggle( "active", button.dataset.weather === weather ); } ); document.querySelectorAll(".cloud").forEach( function (cloud) { cloud.style.opacity = weather === "sunny" ? "0.35" : "0.9"; cloud.style.background = weather === "storm" ? "#48576b" : weather === "rain" ? "#a2afbf" : "#ffffffbb"; } ); createParticles(); updateSky(); } function updateSky() { const night = hour < 6 || hour >= 19; const dusk = (hour >= 6 && hour < 9) || (hour >= 16 && hour < 19); let top = "#5bb6e5"; let bottom = "#e9d5ae"; if (night) { top = "#071328"; bottom = "#283657"; } else if (dusk) { top = "#776ca4"; bottom = "#f5a878"; } if (weather === "rain") { top = night ? "#111b2d" : "#60758a"; bottom = night ? "#344258" : "#a7b8c4"; } if (weather === "storm") { top = "#182536"; bottom = "#56677c"; } if (weather === "snow") { top = night ? "#14223c" : "#8eafc6"; bottom = night ? "#566b83" : "#e2ebf0"; } if (weather === "fog") { top = night ? "#354354" : "#a2b2b6"; bottom = night ? "#77848d" : "#d5d9d0"; } scene.style.background = "linear-gradient(180deg, " + top + " 0%, " + bottom + " 100%)"; sun.style.opacity = night || weather === "storm" || weather === "rain" || weather === "fog" ? "0" : "1"; moon.style.opacity = night && weather !== "storm" ? "1" : "0"; stars.style.opacity = night && weather !== "storm" ? "1" : "0"; const sunPosition = 75 - Math.sin((hour - 6) / 12 * Math.PI) * 60; sun.style.top = sunPosition + "%"; // Adjust vector landscape for nighttime. landscape.style.filter = night ? "brightness(0.38) saturate(0.65)" : weather === "fog" ? "brightness(1.1) saturate(0.6)" : weather === "storm" ? "brightness(0.55) saturate(0.7)" : "none"; timeValue.textContent = String(hour).padStart(2, "0") + ":00"; timeLabel.textContent = night ? "NIGHTTIME" : dusk ? "GOLDEN HOUR" : "DAYTIME"; } function drawRain(p, dt) { const speed = (weather === "storm" ? 14 : 9) * p.speed; const drift = wind * 0.12; p.x += drift * dt; p.y += speed * dt; ctx.strokeStyle = "rgba(205,230,255,0.65)"; ctx.lineWidth = 1.3; ctx.beginPath(); ctx.moveTo(p.x, p.y); ctx.lineTo( p.x - drift * 1.6, p.y - speed * 1.8 ); ctx.stroke(); if (p.y > height + 25 || p.x > width + 25) { p.y = -20; p.x = random(-width * 0.3, width); } } function drawSnow(p, dt, time) { p.x += ( wind * 0.025 + Math.sin(time * 0.001 + p.phase) * 0.45 ) * dt; p.y += p.speed * 1.4 * dt; ctx.fillStyle = "rgba(255,255,255,0.9)"; ctx.beginPath(); ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2); ctx.fill(); if (p.y > height + 10 || p.x > width + 10) { p.y = -10; p.x = random(-40, width); } } function drawFog(p, dt, time) { p.x += (0.15 + wind * 0.008) * dt; const x = p.x; const y = p.y + Math.sin(time * 0.0004 + p.phase) * 8; const radius = 75 + p.size * 30; const gradient = ctx.createRadialGradient( x, y, 0, x, y, radius ); gradient.addColorStop( 0, "rgba(240,245,248,0.13)" ); gradient.addColorStop( 1, "rgba(240,245,248,0)" ); ctx.fillStyle = gradient; ctx.beginPath(); ctx.arc(x, y, radius, 0, Math.PI * 2); ctx.fill(); if (p.x > width + radius) { p.x = -radius; } } function updateLightning(time) { if (weather !== "storm") { lightning.style.opacity = "0"; return; } if (time > nextLightning) { flashUntil = time + random(70, 160); nextLightning = time + random(2200, 6500); } lightning.style.opacity = time < flashUntil ? "0.65" : "0"; } function animate(time) { const dt = Math.min( (time - lastFrame) / 16.67 || 1, 2 ); lastFrame = time; ctx.clearRect(0, 0, width, height); for (const particle of particles) { if (weather === "rain" || weather === "storm") { drawRain(particle, dt); } else if (weather === "snow") { drawSnow(particle, dt, time); } else if (weather === "fog") { drawFog(particle, dt, time); } } updateLightning(time); requestAnimationFrame(animate); } document.querySelectorAll(".weather-btn").forEach( function (button) { button.addEventListener("click", function () { weather = button.dataset.weather; updateWeather(); }); } ); windSlider.addEventListener("input", function () { wind = Number(windSlider.value); windValue.textContent = wind + "%"; windLabel.textContent = "WIND " + wind + "%"; document.querySelectorAll(".cloud").forEach( function (cloud) { cloud.style.animationDuration = Math.max(5, 35 - wind * 0.28) + "s"; } ); }); timeSlider.addEventListener("input", function () { hour = Number(timeSlider.value); updateSky(); }); document.getElementById("randomBtn").addEventListener( "click", function () { const types = Object.keys(weatherData); weather = types[ Math.floor(Math.random() * types.length) ]; wind = Math.floor(random(0, 101)); hour = Math.floor(random(0, 25)); windSlider.value = wind; timeSlider.value = hour; windSlider.dispatchEvent(new Event("input")); timeSlider.dispatchEvent(new Event("input")); updateWeather(); } ); window.addEventListener("resize", resizeCanvas); createStars(); resizeCanvas(); updateWeather(); requestAnimationFrame(animate); })();
terminal
JavaScript Console
Preview
Clear
close
›
Run