环境:CC
提示词来源:Deepseek V3 生成的天气卡片分享
在线预览
第一版: Animated Weather Cards
第二版: Premium Weather Experience
第一版,有动效,但是感觉丑丑的,上面的都可以点击
你是顶级前端工程师,现就职于apple.
Create a single HTML file containing CSS and JavaScript to generate an animated weather card. The card should visually represent the following weather conditions with distinct animations: Wind: (e.g., moving clouds, swaying trees, or wind lines) Rain: (e.g., falling raindrops, puddles forming) Sun: (e.g., shining rays, bright background) Snow: (e.g., falling snowflakes, snow accumulating) Show all the weather card side by side The card should have a dark background. Provide all the HTML, CSS, and JavaScript code within this single file. The JavaScript should include a way to switch between the different weather conditions (e.g., a function or a set of buttons) to demonstrate the animations for each.

源代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Animated Weather Cards</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
padding: 20px;
font-family: 'Arial', sans-serif;
}
.controls {
margin-bottom: 30px;
display: flex;
gap: 15px;
flex-wrap: wrap;
justify-content: center;
}
.btn {
padding: 10px 20px;
border: none;
border-radius: 25px;
cursor: pointer;
font-weight: bold;
transition: all 0.3s ease;
text-transform: uppercase;
letter-spacing: 1px;
}
.btn-wind { background: linear-gradient(45deg, #4facfe 0%, #00f2fe 100%); color: white; }
.btn-rain { background: linear-gradient(45deg, #434343 0%, #000000 100%); color: white; }
.btn-sun { background: linear-gradient(45deg, #f093fb 0%, #f5576c 100%); color: white; }
.btn-snow { background: linear-gradient(45deg, #e0eafc 0%, #cfdef3 100%); color: #333; }
.btn:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(0,0,0,0.3);
}
.weather-container {
display: flex;
gap: 30px;
flex-wrap: wrap;
justify-content: center;
max-width: 1200px;
}
.weather-card {
width: 280px;
height: 400px;
border-radius: 20px;
position: relative;
overflow: hidden;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 10px 30px rgba(0,0,0,0.3);
}
.weather-card:hover {
transform: translateY(-5px);
box-shadow: 0 15px 40px rgba(0,0,0,0.4);
}
.weather-info {
position: absolute;
bottom: 20px;
left: 20px;
right: 20px;
background: rgba(255,255,255,0.1);
backdrop-filter: blur(10px);
border-radius: 15px;
padding: 15px;
color: white;
z-index: 10;
}
.weather-type {
font-size: 24px;
font-weight: bold;
margin-bottom: 5px;
}
.weather-temp {
font-size: 36px;
font-weight: bold;
}
.weather-desc {
font-size: 14px;
opacity: 0.8;
margin-top: 5px;
}
/* Wind Animation */
.wind-card {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.cloud {
position: absolute;
background: rgba(255,255,255,0.8);
border-radius: 50px;
animation: windMove 8s infinite linear;
}
.cloud1 {
width: 80px;
height: 40px;
top: 20%;
left: -80px;
}
.cloud2 {
width: 60px;
height: 30px;
top: 40%;
left: -60px;
animation-delay: 2s;
}
.cloud3 {
width: 100px;
height: 50px;
top: 60%;
left: -100px;
animation-delay: 4s;
}
.wind-line {
position: absolute;
height: 2px;
background: rgba(255,255,255,0.6);
animation: windLine 3s infinite linear;
}
.wind-line1 { top: 30%; width: 60px; left: -60px; animation-delay: 0s; }
.wind-line2 { top: 50%; width: 80px; left: -80px; animation-delay: 1s; }
.wind-line3 { top: 70%; width: 40px; left: -40px; animation-delay: 2s; }
@keyframes windMove {
0% { transform: translateX(0); }
100% { transform: translateX(360px); }
}
@keyframes windLine {
0% { transform: translateX(0); opacity: 0; }
10% { opacity: 1; }
90% { opacity: 1; }
100% { transform: translateX(360px); opacity: 0; }
}
/* Rain Animation */
.rain-card {
background: linear-gradient(135deg, #2c3e50 0%, #34495e 100%);
}
.raindrop {
position: absolute;
width: 2px;
height: 20px;
background: linear-gradient(to bottom, transparent, #74b9ff);
animation: rainFall 1s infinite linear;
}
.puddle {
position: absolute;
bottom: 0;
width: 100%;
height: 30px;
background: rgba(116, 185, 255, 0.3);
border-radius: 50% 50% 0 0;
animation: puddleGrow 2s infinite alternate;
}
@keyframes rainFall {
0% { transform: translateY(-20px); opacity: 0; }
10% { opacity: 1; }
90% { opacity: 1; }
100% { transform: translateY(400px); opacity: 0; }
}
@keyframes puddleGrow {
0% { transform: scaleY(0.8); }
100% { transform: scaleY(1.2); }
}
/* Sun Animation */
.sun-card {
background: linear-gradient(135deg, #ffeaa7 0%, #fab1a0 100%);
}
.sun {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 100px;
height: 100px;
background: #ffeb3b;
border-radius: 50%;
box-shadow: 0 0 50px #ffeb3b;
animation: sunPulse 3s infinite alternate;
}
.sun-ray {
position: absolute;
top: 50%;
left: 50%;
width: 150px;
height: 4px;
background: linear-gradient(to right, transparent, #ffeb3b, transparent);
transform-origin: left center;
animation: sunRayRotate 8s infinite linear;
}
.sun-ray:nth-child(2) { transform: rotate(45deg); }
.sun-ray:nth-child(3) { transform: rotate(90deg); }
.sun-ray:nth-child(4) { transform: rotate(135deg); }
@keyframes sunPulse {
0% { transform: translate(-50%, -50%) scale(1); }
100% { transform: translate(-50%, -50%) scale(1.1); }
}
@keyframes sunRayRotate {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* Snow Animation */
.snow-card {
background: linear-gradient(135deg, #ddd6fe 0%, #a78bfa 100%);
}
.snowflake {
position: absolute;
color: white;
font-size: 20px;
animation: snowFall 3s infinite linear;
}
.snow-ground {
position: absolute;
bottom: 0;
width: 100%;
height: 50px;
background: rgba(255,255,255,0.8);
border-radius: 50% 50% 0 0;
animation: snowAccumulate 4s infinite alternate;
}
@keyframes snowFall {
0% { transform: translateY(-20px) rotate(0deg); opacity: 0; }
10% { opacity: 1; }
90% { opacity: 1; }
100% { transform: translateY(400px) rotate(360deg); opacity: 0; }
}
@keyframes snowAccumulate {
0% { transform: scaleY(0.8); }
100% { transform: scaleY(1.1); }
}
.hidden {
display: none !important;
}
</style>
</head>
<body>
<div class="controls">
<button class="btn btn-wind" onclick="showWeather('wind')">Wind</button>
<button class="btn btn-rain" onclick="showWeather('rain')">Rain</button>
<button class="btn btn-sun" onclick="showWeather('sun')">Sun</button>
<button class="btn btn-snow" onclick="showWeather('snow')">Snow</button>
<button class="btn" onclick="showAllWeather()" style="background: linear-gradient(45deg, #667eea 0%, #764ba2 100%); color: white;">Show All</button>
</div>
<div class="weather-container">
<!-- Wind Card -->
<div class="weather-card wind-card" id="wind-card">
<div class="cloud cloud1"></div>
<div class="cloud cloud2"></div>
<div class="cloud cloud3"></div>
<div class="wind-line wind-line1"></div>
<div class="wind-line wind-line2"></div>
<div class="wind-line wind-line3"></div>
<div class="weather-info">
<div class="weather-type">Windy</div>
<div class="weather-temp">18°C</div>
<div class="weather-desc">Strong winds expected</div>
</div>
</div>
<!-- Rain Card -->
<div class="weather-card rain-card" id="rain-card">
<div class="raindrop" style="left: 10%; animation-delay: 0s;"></div>
<div class="raindrop" style="left: 20%; animation-delay: 0.2s;"></div>
<div class="raindrop" style="left: 30%; animation-delay: 0.4s;"></div>
<div class="raindrop" style="left: 40%; animation-delay: 0.6s;"></div>
<div class="raindrop" style="left: 50%; animation-delay: 0.8s;"></div>
<div class="raindrop" style="left: 60%; animation-delay: 1.0s;"></div>
<div class="raindrop" style="left: 70%; animation-delay: 1.2s;"></div>
<div class="raindrop" style="left: 80%; animation-delay: 1.4s;"></div>
<div class="raindrop" style="left: 90%; animation-delay: 1.6s;"></div>
<div class="puddle"></div>
<div class="weather-info">
<div class="weather-type">Rainy</div>
<div class="weather-temp">15°C</div>
<div class="weather-desc">Heavy rainfall</div>
</div>
</div>
<!-- Sun Card -->
<div class="weather-card sun-card" id="sun-card">
<div class="sun">
<div class="sun-ray"></div>
<div class="sun-ray"></div>
<div class="sun-ray"></div>
<div class="sun-ray"></div>
</div>
<div class="weather-info">
<div class="weather-type">Sunny</div>
<div class="weather-temp">28°C</div>
<div class="weather-desc">Clear skies</div>
</div>
</div>
<!-- Snow Card -->
<div class="weather-card snow-card" id="snow-card">
<div class="snowflake" style="left: 10%; animation-delay: 0s;">❄</div>
<div class="snowflake" style="left: 25%; animation-delay: 0.5s;">❅</div>
<div class="snowflake" style="left: 40%; animation-delay: 1.0s;">❆</div>
<div class="snowflake" style="left: 55%; animation-delay: 1.5s;">❄</div>
<div class="snowflake" style="left: 70%; animation-delay: 2.0s;">❅</div>
<div class="snowflake" style="left: 85%; animation-delay: 2.5s;">❆</div>
<div class="snow-ground"></div>
<div class="weather-info">
<div class="weather-type">Snowy</div>
<div class="weather-temp">-2°C</div>
<div class="weather-desc">Light snowfall</div>
</div>
</div>
</div>
<script>
function showWeather(type) {
const cards = document.querySelectorAll('.weather-card');
cards.forEach(card => {
card.classList.add('hidden');
});
const targetCard = document.getElementById(type + '-card');
if (targetCard) {
targetCard.classList.remove('hidden');
}
}
function showAllWeather() {
const cards = document.querySelectorAll('.weather-card');
cards.forEach(card => {
card.classList.remove('hidden');
});
}
// Initialize with all weather cards visible
showAllWeather();
// Add click handlers to cards for mobile interaction
document.querySelectorAll('.weather-card').forEach(card => {
card.addEventListener('click', function() {
const cardType = this.id.replace('-card', '');
showWeather(cardType);
});
});
// Add dynamic snowflakes for more realistic effect
function createSnowflake() {
const snowCard = document.getElementById('snow-card');
if (snowCard && !snowCard.classList.contains('hidden')) {
const snowflake = document.createElement('div');
snowflake.className = 'snowflake';
snowflake.innerHTML = Math.random() > 0.5 ? '❄' : '❅';
snowflake.style.left = Math.random() * 100 + '%';
snowflake.style.animationDuration = (Math.random() * 3 + 2) + 's';
snowflake.style.animationDelay = Math.random() * 2 + 's';
snowCard.appendChild(snowflake);
// Remove snowflake after animation
setTimeout(() => {
if (snowflake.parentNode) {
snowflake.parentNode.removeChild(snowflake);
}
}, 5000);
}
}
// Create new snowflakes periodically
setInterval(createSnowflake, 800);
// Add dynamic raindrops
function createRaindrop() {
const rainCard = document.getElementById('rain-card');
if (rainCard && !rainCard.classList.contains('hidden')) {
const raindrop = document.createElement('div');
raindrop.className = 'raindrop';
raindrop.style.left = Math.random() * 100 + '%';
raindrop.style.animationDuration = (Math.random() * 0.5 + 0.5) + 's';
raindrop.style.animationDelay = Math.random() * 0.5 + 's';
rainCard.appendChild(raindrop);
// Remove raindrop after animation
setTimeout(() => {
if (raindrop.parentNode) {
raindrop.parentNode.removeChild(raindrop);
}
}, 1500);
}
}
// Create new raindrops periodically
setInterval(createRaindrop, 200);
</script>
</body>
</html>
源代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Animated Weather Cards</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
padding: 20px;
font-family: 'Arial', sans-serif;
}
.controls {
margin-bottom: 30px;
display: flex;
gap: 15px;
flex-wrap: wrap;
justify-content: center;
}
.btn {
padding: 10px 20px;
border: none;
border-radius: 25px;
cursor: pointer;
font-weight: bold;
transition: all 0.3s ease;
text-transform: uppercase;
letter-spacing: 1px;
}
.btn-wind { background: linear-gradient(45deg, #4facfe 0%, #00f2fe 100%); color: white; }
.btn-rain { background: linear-gradient(45deg, #434343 0%, #000000 100%); color: white; }
.btn-sun { background: linear-gradient(45deg, #f093fb 0%, #f5576c 100%); color: white; }
.btn-snow { background: linear-gradient(45deg, #e0eafc 0%, #cfdef3 100%); color: #333; }
.btn:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(0,0,0,0.3);
}
.weather-container {
display: flex;
gap: 30px;
flex-wrap: wrap;
justify-content: center;
max-width: 1200px;
}
.weather-card {
width: 280px;
height: 400px;
border-radius: 20px;
position: relative;
overflow: hidden;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 10px 30px rgba(0,0,0,0.3);
}
.weather-card:hover {
transform: translateY(-5px);
box-shadow: 0 15px 40px rgba(0,0,0,0.4);
}
.weather-info {
position: absolute;
bottom: 20px;
left: 20px;
right: 20px;
background: rgba(255,255,255,0.1);
backdrop-filter: blur(10px);
border-radius: 15px;
padding: 15px;
color: white;
z-index: 10;
}
.weather-type {
font-size: 24px;
font-weight: bold;
margin-bottom: 5px;
}
.weather-temp {
font-size: 36px;
font-weight: bold;
}
.weather-desc {
font-size: 14px;
opacity: 0.8;
margin-top: 5px;
}
/* Wind Animation */
.wind-card {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.cloud {
position: absolute;
background: rgba(255,255,255,0.8);
border-radius: 50px;
animation: windMove 8s infinite linear;
}
.cloud1 {
width: 80px;
height: 40px;
top: 20%;
left: -80px;
}
.cloud2 {
width: 60px;
height: 30px;
top: 40%;
left: -60px;
animation-delay: 2s;
}
.cloud3 {
width: 100px;
height: 50px;
top: 60%;
left: -100px;
animation-delay: 4s;
}
.wind-line {
position: absolute;
height: 2px;
background: rgba(255,255,255,0.6);
animation: windLine 3s infinite linear;
}
.wind-line1 { top: 30%; width: 60px; left: -60px; animation-delay: 0s; }
.wind-line2 { top: 50%; width: 80px; left: -80px; animation-delay: 1s; }
.wind-line3 { top: 70%; width: 40px; left: -40px; animation-delay: 2s; }
@keyframes windMove {
0% { transform: translateX(0); }
100% { transform: translateX(360px); }
}
@keyframes windLine {
0% { transform: translateX(0); opacity: 0; }
10% { opacity: 1; }
90% { opacity: 1; }
100% { transform: translateX(360px); opacity: 0; }
}
/* Rain Animation */
.rain-card {
background: linear-gradient(135deg, #2c3e50 0%, #34495e 100%);
}
.raindrop {
position: absolute;
width: 2px;
height: 20px;
background: linear-gradient(to bottom, transparent, #74b9ff);
animation: rainFall 1s infinite linear;
}
.puddle {
position: absolute;
bottom: 0;
width: 100%;
height: 30px;
background: rgba(116, 185, 255, 0.3);
border-radius: 50% 50% 0 0;
animation: puddleGrow 2s infinite alternate;
}
@keyframes rainFall {
0% { transform: translateY(-20px); opacity: 0; }
10% { opacity: 1; }
90% { opacity: 1; }
100% { transform: translateY(400px); opacity: 0; }
}
@keyframes puddleGrow {
0% { transform: scaleY(0.8); }
100% { transform: scaleY(1.2); }
}
/* Sun Animation */
.sun-card {
background: linear-gradient(135deg, #ffeaa7 0%, #fab1a0 100%);
}
.sun {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 100px;
height: 100px;
background: #ffeb3b;
border-radius: 50%;
box-shadow: 0 0 50px #ffeb3b;
animation: sunPulse 3s infinite alternate;
}
.sun-ray {
position: absolute;
top: 50%;
left: 50%;
width: 150px;
height: 4px;
background: linear-gradient(to right, transparent, #ffeb3b, transparent);
transform-origin: left center;
animation: sunRayRotate 8s infinite linear;
}
.sun-ray:nth-child(2) { transform: rotate(45deg); }
.sun-ray:nth-child(3) { transform: rotate(90deg); }
.sun-ray:nth-child(4) { transform: rotate(135deg); }
@keyframes sunPulse {
0% { transform: translate(-50%, -50%) scale(1); }
100% { transform: translate(-50%, -50%) scale(1.1); }
}
@keyframes sunRayRotate {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* Snow Animation */
.snow-card {
background: linear-gradient(135deg, #ddd6fe 0%, #a78bfa 100%);
}
.snowflake {
position: absolute;
color: white;
font-size: 20px;
animation: snowFall 3s infinite linear;
}
.snow-ground {
position: absolute;
bottom: 0;
width: 100%;
height: 50px;
background: rgba(255,255,255,0.8);
border-radius: 50% 50% 0 0;
animation: snowAccumulate 4s infinite alternate;
}
@keyframes snowFall {
0% { transform: translateY(-20px) rotate(0deg); opacity: 0; }
10% { opacity: 1; }
90% { opacity: 1; }
100% { transform: translateY(400px) rotate(360deg); opacity: 0; }
}
@keyframes snowAccumulate {
0% { transform: scaleY(0.8); }
100% { transform: scaleY(1.1); }
}
.hidden {
display: none !important;
}
</style>
</head>
<body>
<div class="controls">
<button class="btn btn-wind" onclick="showWeather('wind')">Wind</button>
<button class="btn btn-rain" onclick="showWeather('rain')">Rain</button>
<button class="btn btn-sun" onclick="showWeather('sun')">Sun</button>
<button class="btn btn-snow" onclick="showWeather('snow')">Snow</button>
<button class="btn" onclick="showAllWeather()" style="background: linear-gradient(45deg, #667eea 0%, #764ba2 100%); color: white;">Show All</button>
</div>
<div class="weather-container">
<!-- Wind Card -->
<div class="weather-card wind-card" id="wind-card">
<div class="cloud cloud1"></div>
<div class="cloud cloud2"></div>
<div class="cloud cloud3"></div>
<div class="wind-line wind-line1"></div>
<div class="wind-line wind-line2"></div>
<div class="wind-line wind-line3"></div>
<div class="weather-info">
<div class="weather-type">Windy</div>
<div class="weather-temp">18°C</div>
<div class="weather-desc">Strong winds expected</div>
</div>
</div>
<!-- Rain Card -->
<div class="weather-card rain-card" id="rain-card">
<div class="raindrop" style="left: 10%; animation-delay: 0s;"></div>
<div class="raindrop" style="left: 20%; animation-delay: 0.2s;"></div>
<div class="raindrop" style="left: 30%; animation-delay: 0.4s;"></div>
<div class="raindrop" style="left: 40%; animation-delay: 0.6s;"></div>
<div class="raindrop" style="left: 50%; animation-delay: 0.8s;"></div>
<div class="raindrop" style="left: 60%; animation-delay: 1.0s;"></div>
<div class="raindrop" style="left: 70%; animation-delay: 1.2s;"></div>
<div class="raindrop" style="left: 80%; animation-delay: 1.4s;"></div>
<div class="raindrop" style="left: 90%; animation-delay: 1.6s;"></div>
<div class="puddle"></div>
<div class="weather-info">
<div class="weather-type">Rainy</div>
<div class="weather-temp">15°C</div>
<div class="weather-desc">Heavy rainfall</div>
</div>
</div>
<!-- Sun Card -->
<div class="weather-card sun-card" id="sun-card">
<div class="sun">
<div class="sun-ray"></div>
<div class="sun-ray"></div>
<div class="sun-ray"></div>
<div class="sun-ray"></div>
</div>
<div class="weather-info">
<div class="weather-type">Sunny</div>
<div class="weather-temp">28°C</div>
<div class="weather-desc">Clear skies</div>
</div>
</div>
<!-- Snow Card -->
<div class="weather-card snow-card" id="snow-card">
<div class="snowflake" style="left: 10%; animation-delay: 0s;">❄</div>
<div class="snowflake" style="left: 25%; animation-delay: 0.5s;">❅</div>
<div class="snowflake" style="left: 40%; animation-delay: 1.0s;">❆</div>
<div class="snowflake" style="left: 55%; animation-delay: 1.5s;">❄</div>
<div class="snowflake" style="left: 70%; animation-delay: 2.0s;">❅</div>
<div class="snowflake" style="left: 85%; animation-delay: 2.5s;">❆</div>
<div class="snow-ground"></div>
<div class="weather-info">
<div class="weather-type">Snowy</div>
<div class="weather-temp">-2°C</div>
<div class="weather-desc">Light snowfall</div>
</div>
</div>
</div>
<script>
function showWeather(type) {
const cards = document.querySelectorAll('.weather-card');
cards.forEach(card => {
card.classList.add('hidden');
});
const targetCard = document.getElementById(type + '-card');
if (targetCard) {
targetCard.classList.remove('hidden');
}
}
function showAllWeather() {
const cards = document.querySelectorAll('.weather-card');
cards.forEach(card => {
card.classList.remove('hidden');
});
}
// Initialize with all weather cards visible
showAllWeather();
// Add click handlers to cards for mobile interaction
document.querySelectorAll('.weather-card').forEach(card => {
card.addEventListener('click', function() {
const cardType = this.id.replace('-card', '');
showWeather(cardType);
});
});
// Add dynamic snowflakes for more realistic effect
function createSnowflake() {
const snowCard = document.getElementById('snow-card');
if (snowCard && !snowCard.classList.contains('hidden')) {
const snowflake = document.createElement('div');
snowflake.className = 'snowflake';
snowflake.innerHTML = Math.random() > 0.5 ? '❄' : '❅';
snowflake.style.left = Math.random() * 100 + '%';
snowflake.style.animationDuration = (Math.random() * 3 + 2) + 's';
snowflake.style.animationDelay = Math.random() * 2 + 's';
snowCard.appendChild(snowflake);
// Remove snowflake after animation
setTimeout(() => {
if (snowflake.parentNode) {
snowflake.parentNode.removeChild(snowflake);
}
}, 5000);
}
}
// Create new snowflakes periodically
setInterval(createSnowflake, 800);
// Add dynamic raindrops
function createRaindrop() {
const rainCard = document.getElementById('rain-card');
if (rainCard && !rainCard.classList.contains('hidden')) {
const raindrop = document.createElement('div');
raindrop.className = 'raindrop';
raindrop.style.left = Math.random() * 100 + '%';
raindrop.style.animationDuration = (Math.random() * 0.5 + 0.5) + 's';
raindrop.style.animationDelay = Math.random() * 0.5 + 's';
rainCard.appendChild(raindrop);
// Remove raindrop after animation
setTimeout(() => {
if (raindrop.parentNode) {
raindrop.parentNode.removeChild(raindrop);
}
}, 1500);
}
}
// Create new raindrops periodically
setInterval(createRaindrop, 200);
</script>
</body>
</html>
第二版,咋感觉越来越丑了,
把前端显示变得更精致,更丝滑的动态效果,感觉是用户需要付费20元每月的绝美天气app的前端显示

源代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Premium Weather Experience</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--primary-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
--glass-bg: rgba(255, 255, 255, 0.1);
--glass-border: rgba(255, 255, 255, 0.2);
--text-primary: #ffffff;
--text-secondary: rgba(255, 255, 255, 0.8);
--accent-glow: rgba(255, 255, 255, 0.3);
}
body {
background: linear-gradient(135deg, #0f0c29 0%, #302b63 50%, #24243e 100%);
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
padding: 20px;
font-family: 'Inter', sans-serif;
overflow-x: hidden;
position: relative;
}
/* Animated background particles */
.bg-particle {
position: fixed;
width: 4px;
height: 4px;
background: rgba(255, 255, 255, 0.1);
border-radius: 50%;
pointer-events: none;
animation: floatParticle 20s infinite linear;
}
@keyframes floatParticle {
0% { transform: translateY(100vh) rotate(0deg); opacity: 0; }
10% { opacity: 1; }
90% { opacity: 1; }
100% { transform: translateY(-100vh) rotate(360deg); opacity: 0; }
}
.header {
text-align: center;
margin-bottom: 40px;
z-index: 10;
}
.header h1 {
font-size: 3rem;
font-weight: 700;
background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin-bottom: 10px;
text-shadow: 0 0 30px rgba(102, 126, 234, 0.5);
}
.header p {
color: var(--text-secondary);
font-size: 1.2rem;
font-weight: 300;
letter-spacing: 1px;
}
.controls {
display: flex;
gap: 15px;
flex-wrap: wrap;
justify-content: center;
margin-bottom: 40px;
z-index: 10;
}
.btn {
padding: 12px 24px;
border: 2px solid var(--glass-border);
border-radius: 30px;
background: var(--glass-bg);
backdrop-filter: blur(20px);
cursor: pointer;
font-weight: 500;
color: var(--text-primary);
transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
position: relative;
overflow: hidden;
text-transform: uppercase;
letter-spacing: 1px;
font-size: 0.9rem;
}
.btn::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
transition: left 0.6s;
}
.btn:hover::before {
left: 100%;
}
.btn:hover {
transform: translateY(-3px);
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
border-color: var(--accent-glow);
}
.btn.active {
background: var(--primary-gradient);
border-color: transparent;
box-shadow: 0 0 30px rgba(102, 126, 234, 0.6);
}
.weather-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
gap: 30px;
max-width: 1400px;
width: 100%;
z-index: 10;
}
.weather-card {
height: 480px;
border-radius: 25px;
position: relative;
overflow: hidden;
cursor: pointer;
transition: all 0.6s cubic-bezier(0.175, 0.885, 0.32, 1.275);
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
backdrop-filter: blur(20px);
border: 1px solid var(--glass-border);
}
.weather-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: var(--glass-bg);
backdrop-filter: blur(20px);
z-index: 1;
}
.weather-card:hover {
transform: translateY(-10px) scale(1.02);
box-shadow: 0 30px 80px rgba(0, 0, 0, 0.4);
}
.weather-animation {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 2;
}
.weather-info {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: linear-gradient(to top, rgba(0, 0, 0, 0.8), transparent);
backdrop-filter: blur(20px);
border-radius: 25px 25px 0 0;
padding: 30px;
color: var(--text-primary);
z-index: 10;
transform: translateY(0);
transition: transform 0.4s ease;
}
.weather-card:hover .weather-info {
transform: translateY(-10px);
}
.weather-type {
font-size: 2rem;
font-weight: 600;
margin-bottom: 10px;
text-shadow: 0 2px 10px rgba(0, 0, 0, 0.5);
}
.weather-temp {
font-size: 3.5rem;
font-weight: 700;
margin-bottom: 5px;
background: linear-gradient(135deg, #ffffff 0%, #e0e0e0 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.weather-stats {
display: flex;
gap: 20px;
margin-top: 15px;
flex-wrap: wrap;
}
.stat-item {
display: flex;
align-items: center;
gap: 8px;
font-size: 0.9rem;
color: var(--text-secondary);
}
.stat-icon {
width: 16px;
height: 16px;
background: var(--accent-glow);
border-radius: 50%;
}
/* Wind Card - Premium Design */
.wind-card {
background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%);
}
.cloud {
position: absolute;
background: rgba(255, 255, 255, 0.9);
border-radius: 50px;
filter: blur(2px);
animation: windMove 12s infinite ease-in-out;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
}
.cloud::before,
.cloud::after {
content: '';
position: absolute;
background: rgba(255, 255, 255, 0.9);
border-radius: 50px;
}
.cloud1 {
width: 120px;
height: 60px;
top: 15%;
left: -120px;
animation-delay: 0s;
}
.cloud1::before {
width: 80px;
height: 80px;
top: -40px;
left: 20px;
}
.cloud1::after {
width: 60px;
height: 60px;
top: -30px;
right: 20px;
}
.cloud2 {
width: 100px;
height: 50px;
top: 35%;
left: -100px;
animation-delay: 3s;
}
.cloud2::before {
width: 70px;
height: 70px;
top: -35px;
left: 15px;
}
.cloud3 {
width: 140px;
height: 70px;
top: 55%;
left: -140px;
animation-delay: 6s;
}
.cloud3::before {
width: 90px;
height: 90px;
top: -45px;
left: 25px;
}
.wind-particle {
position: absolute;
width: 3px;
height: 3px;
background: rgba(255, 255, 255, 0.8);
border-radius: 50%;
animation: windParticle 4s infinite linear;
}
@keyframes windMove {
0% { transform: translateX(0) scale(1); opacity: 0; }
10% { opacity: 1; }
90% { opacity: 1; }
100% { transform: translateX(440px) scale(1.1); opacity: 0; }
}
@keyframes windParticle {
0% { transform: translateX(-50px) translateY(0); opacity: 0; }
10% { opacity: 1; }
90% { opacity: 1; }
100% { transform: translateX(400px) translateY(-20px); opacity: 0; }
}
/* Rain Card - Premium Design */
.rain-card {
background: linear-gradient(135deg, #2c3e50 0%, #34495e 50%, #4a6741 100%);
}
.raindrop {
position: absolute;
width: 2px;
height: 25px;
background: linear-gradient(to bottom, transparent, rgba(116, 185, 255, 0.8), rgba(116, 185, 255, 0.3));
border-radius: 0 0 50% 50%;
animation: rainFall 1.5s infinite linear;
filter: blur(0.5px);
}
.raindrop.splash {
width: 8px;
height: 8px;
border-radius: 50%;
background: rgba(116, 185, 255, 0.6);
animation: splash 0.6s ease-out forwards;
}
.puddle {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 40px;
background: linear-gradient(to top, rgba(116, 185, 255, 0.4), transparent);
border-radius: 50% 50% 0 0;
animation: puddleGrow 3s infinite ease-in-out;
filter: blur(2px);
}
.rain-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(to bottom, rgba(44, 62, 80, 0.3), rgba(52, 73, 94, 0.5));
animation: rainIntensity 4s infinite ease-in-out;
}
@keyframes rainFall {
0% { transform: translateY(-30px) rotate(10deg); opacity: 0; }
10% { opacity: 0.8; }
90% { opacity: 0.8; }
100% { transform: translateY(480px) rotate(10deg); opacity: 0; }
}
@keyframes splash {
0% { transform: scale(0); opacity: 1; }
100% { transform: scale(4); opacity: 0; }
}
@keyframes puddleGrow {
0%, 100% { transform: scaleY(0.8); }
50% { transform: scaleY(1.2); }
}
@keyframes rainIntensity {
0%, 100% { opacity: 0.3; }
50% { opacity: 0.6; }
}
/* Sun Card - Premium Design */
.sun-card {
background: linear-gradient(135deg, #ffeaa7 0%, #fab1a0 50%, #fd79a8 100%);
}
.sun {
position: absolute;
top: 40%;
left: 50%;
transform: translate(-50%, -50%);
width: 120px;
height: 120px;
background: radial-gradient(circle, #ffeb3b 0%, #ffc107 70%, #ff9800 100%);
border-radius: 50%;
box-shadow: 0 0 80px #ffeb3b, 0 0 120px #ffc107, 0 0 160px #ff9800;
animation: sunPulse 4s infinite ease-in-out;
}
.sun-ray {
position: absolute;
top: 50%;
left: 50%;
width: 200px;
height: 6px;
background: linear-gradient(to right, transparent, rgba(255, 235, 59, 0.8), rgba(255, 193, 7, 0.6), transparent);
transform-origin: left center;
animation: sunRayRotate 20s infinite linear;
filter: blur(1px);
}
.sun-ray:nth-child(2) { transform: rotate(45deg); animation-delay: 0s; }
.sun-ray:nth-child(3) { transform: rotate(90deg); animation-delay: 2.5s; }
.sun-ray:nth-child(4) { transform: rotate(135deg); animation-delay: 5s; }
.sun-ray:nth-child(5) { transform: rotate(180deg); animation-delay: 7.5s; }
.sun-ray:nth-child(6) { transform: rotate(225deg); animation-delay: 10s; }
.sun-ray:nth-child(7) { transform: rotate(270deg); animation-delay: 12.5s; }
.sun-ray:nth-child(8) { transform: rotate(315deg); animation-delay: 15s; }
.lens-flare {
position: absolute;
top: 30%;
left: 30%;
width: 20px;
height: 20px;
background: rgba(255, 255, 255, 0.8);
border-radius: 50%;
animation: lensFlare 3s infinite ease-in-out;
filter: blur(2px);
}
.sun-halo {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 200px;
height: 200px;
border: 2px solid rgba(255, 235, 59, 0.3);
border-radius: 50%;
animation: haloRotate 15s infinite linear;
}
@keyframes sunPulse {
0%, 100% { transform: translate(-50%, -50%) scale(1); }
50% { transform: translate(-50%, -50%) scale(1.05); }
}
@keyframes sunRayRotate {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
@keyframes lensFlare {
0%, 100% { opacity: 0.3; transform: scale(1); }
50% { opacity: 0.8; transform: scale(1.5); }
}
@keyframes haloRotate {
0% { transform: translate(-50%, -50%) rotate(0deg); }
100% { transform: translate(-50%, -50%) rotate(360deg); }
}
/* Snow Card - Premium Design */
.snow-card {
background: linear-gradient(135deg, #ddd6fe 0%, #a78bfa 50%, #8b5cf6 100%);
}
.snowflake {
position: absolute;
color: rgba(255, 255, 255, 0.9);
font-size: 18px;
animation: snowFall 4s infinite linear;
text-shadow: 0 0 10px rgba(255, 255, 255, 0.8);
filter: blur(0.5px);
}
.snowflake.crystal {
width: 12px;
height: 12px;
background: linear-gradient(45deg, rgba(255, 255, 255, 0.9), rgba(221, 214, 254, 0.8));
border-radius: 50%;
animation: snowCrystal 5s infinite linear;
}
.snow-ground {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 60px;
background: linear-gradient(to top, rgba(255, 255, 255, 0.9), rgba(221, 214, 254, 0.6), transparent);
border-radius: 50% 50% 0 0;
animation: snowAccumulate 5s infinite ease-in-out;
filter: blur(3px);
}
.snow-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: radial-gradient(circle at 30% 30%, rgba(255, 255, 255, 0.1), transparent);
animation: snowShimmer 3s infinite ease-in-out;
}
@keyframes snowFall {
0% { transform: translateY(-30px) rotate(0deg); opacity: 0; }
10% { opacity: 0.9; }
90% { opacity: 0.9; }
100% { transform: translateY(480px) rotate(360deg); opacity: 0; }
}
@keyframes snowCrystal {
0% { transform: translateY(-30px) rotate(0deg) scale(1); opacity: 0; }
10% { opacity: 0.8; }
90% { opacity: 0.8; }
100% { transform: translateY(480px) rotate(720deg) scale(0.8); opacity: 0; }
}
@keyframes snowAccumulate {
0%, 100% { transform: scaleY(0.9); }
50% { transform: scaleY(1.1); }
}
@keyframes snowShimmer {
0%, 100% { opacity: 0.3; }
50% { opacity: 0.6; }
}
.hidden {
display: none !important;
}
/* Responsive Design */
@media (max-width: 768px) {
.header h1 {
font-size: 2rem;
}
.weather-container {
grid-template-columns: 1fr;
gap: 20px;
}
.weather-card {
height: 400px;
}
.controls {
gap: 10px;
}
.btn {
padding: 10px 20px;
font-size: 0.8rem;
}
}
</style>
</head>
<body>
<div class="header">
<h1>Premium Weather</h1>
<p>Experience weather like never before</p>
</div>
<div class="controls">
<button class="btn active" onclick="showWeather('all')">All Weather</button>
<button class="btn" onclick="showWeather('wind')">Wind</button>
<button class="btn" onclick="showWeather('rain')">Rain</button>
<button class="btn" onclick="showWeather('sun')">Sun</button>
<button class="btn" onclick="showWeather('snow')">Snow</button>
</div>
<div class="weather-container">
<!-- Wind Card -->
<div class="weather-card wind-card" data-weather="wind">
<div class="weather-animation">
<div class="cloud cloud1"></div>
<div class="cloud cloud2"></div>
<div class="cloud cloud3"></div>
<div class="wind-particle" style="top: 25%; left: -50px; animation-delay: 0s;"></div>
<div class="wind-particle" style="top: 45%; left: -50px; animation-delay: 1s;"></div>
<div class="wind-particle" style="top: 65%; left: -50px; animation-delay: 2s;"></div>
<div class="wind-particle" style="top: 35%; left: -50px; animation-delay: 3s;"></div>
<div class="wind-particle" style="top: 55%; left: -50px; animation-delay: 4s;"></div>
</div>
<div class="weather-info">
<div class="weather-type">Windy</div>
<div class="weather-temp">18°</div>
<div class="weather-stats">
<div class="stat-item">
<div class="stat-icon"></div>
<span>25 km/h</span>
</div>
<div class="stat-item">
<div class="stat-icon"></div>
<span>65%</span>
</div>
<div class="stat-item">
<div class="stat-icon"></div>
<span>Feels 15°</span>
</div>
</div>
</div>
</div>
<!-- Rain Card -->
<div class="weather-card rain-card" data-weather="rain">
<div class="weather-animation">
<div class="rain-overlay"></div>
<div class="raindrop" style="left: 5%; animation-delay: 0s;"></div>
<div class="raindrop" style="left: 15%; animation-delay: 0.2s;"></div>
<div class="raindrop" style="left: 25%; animation-delay: 0.4s;"></div>
<div class="raindrop" style="left: 35%; animation-delay: 0.6s;"></div>
<div class="raindrop" style="left: 45%; animation-delay: 0.8s;"></div>
<div class="raindrop" style="left: 55%; animation-delay: 1.0s;"></div>
<div class="raindrop" style="left: 65%; animation-delay: 1.2s;"></div>
<div class="raindrop" style="left: 75%; animation-delay: 1.4s;"></div>
<div class="raindrop" style="left: 85%; animation-delay: 1.6s;"></div>
<div class="raindrop" style="left: 95%; animation-delay: 1.8s;"></div>
<div class="puddle"></div>
</div>
<div class="weather-info">
<div class="weather-type">Rainy</div>
<div class="weather-temp">15°</div>
<div class="weather-stats">
<div class="stat-item">
<div class="stat-icon"></div>
<span>12 mm</span>
</div>
<div class="stat-item">
<div class="stat-icon"></div>
<span>85%</span>
</div>
<div class="stat-item">
<div class="stat-icon"></div>
<span>Feels 13°</span>
</div>
</div>
</div>
</div>
<!-- Sun Card -->
<div class="weather-card sun-card" data-weather="sun">
<div class="weather-animation">
<div class="sun-halo"></div>
<div class="sun">
<div class="sun-ray"></div>
<div class="sun-ray"></div>
<div class="sun-ray"></div>
<div class="sun-ray"></div>
<div class="sun-ray"></div>
<div class="sun-ray"></div>
<div class="sun-ray"></div>
<div class="sun-ray"></div>
</div>
<div class="lens-flare"></div>
</div>
<div class="weather-info">
<div class="weather-type">Sunny</div>
<div class="weather-temp">28°</div>
<div class="weather-stats">
<div class="stat-item">
<div class="stat-icon"></div>
<span>UV 8</span>
</div>
<div class="stat-item">
<div class="stat-icon"></div>
<span>45%</span>
</div>
<div class="stat-item">
<div class="stat-icon"></div>
<span>Feels 32°</span>
</div>
</div>
</div>
</div>
<!-- Snow Card -->
<div class="weather-card snow-card" data-weather="snow">
<div class="weather-animation">
<div class="snow-overlay"></div>
<div class="snowflake" style="left: 10%; animation-delay: 0s;">❄</div>
<div class="snowflake" style="left: 30%; animation-delay: 1s;">❅</div>
<div class="snowflake" style="left: 50%; animation-delay: 2s;">❆</div>
<div class="snowflake" style="left: 70%; animation-delay: 3s;">❄</div>
<div class="snowflake" style="left: 90%; animation-delay: 4s;">❅</div>
<div class="snowflake crystal" style="left: 20%; animation-delay: 0.5s;"></div>
<div class="snowflake crystal" style="left: 40%; animation-delay: 1.5s;"></div>
<div class="snowflake crystal" style="left: 60%; animation-delay: 2.5s;"></div>
<div class="snowflake crystal" style="left: 80%; animation-delay: 3.5s;"></div>
<div class="snow-ground"></div>
</div>
<div class="weather-info">
<div class="weather-type">Snowy</div>
<div class="weather-temp">-2°</div>
<div class="weather-stats">
<div class="stat-item">
<div class="stat-icon"></div>
<span>5 cm</span>
</div>
<div class="stat-item">
<div class="stat-icon"></div>
<span>90%</span>
</div>
<div class="stat-item">
<div class="stat-icon"></div>
<span>Feels -6°</span>
</div>
</div>
</div>
</div>
</div>
<script>
// Background particles
function createBackgroundParticles() {
for (let i = 0; i < 20; i++) {
const particle = document.createElement('div');
particle.className = 'bg-particle';
particle.style.left = Math.random() * 100 + '%';
particle.style.animationDelay = Math.random() * 20 + 's';
particle.style.animationDuration = (Math.random() * 10 + 15) + 's';
document.body.appendChild(particle);
}
}
// Weather display function
function showWeather(type) {
const cards = document.querySelectorAll('.weather-card');
const buttons = document.querySelectorAll('.btn');
// Update button states
buttons.forEach(btn => btn.classList.remove('active'));
event.target.classList.add('active');
// Show/hide cards
cards.forEach(card => {
if (type === 'all') {
card.classList.remove('hidden');
} else {
const cardType = card.getAttribute('data-weather');
if (cardType === type) {
card.classList.remove('hidden');
} else {
card.classList.add('hidden');
}
}
});
}
// Enhanced particle systems
function createWindParticles() {
const windCard = document.querySelector('[data-weather="wind"]:not(.hidden)');
if (windCard) {
const animation = windCard.querySelector('.weather-animation');
const particle = document.createElement('div');
particle.className = 'wind-particle';
particle.style.top = Math.random() * 80 + '%';
particle.style.left = '-50px';
particle.style.animationDelay = Math.random() * 2 + 's';
animation.appendChild(particle);
setTimeout(() => {
if (particle.parentNode) {
particle.parentNode.removeChild(particle);
}
}, 4000);
}
}
function createRaindrops() {
const rainCard = document.querySelector('[data-weather="rain"]:not(.hidden)');
if (rainCard) {
const animation = rainCard.querySelector('.weather-animation');
const raindrop = document.createElement('div');
raindrop.className = 'raindrop';
raindrop.style.left = Math.random() * 100 + '%';
raindrop.style.animationDelay = Math.random() * 0.5 + 's';
animation.appendChild(raindrop);
// Create splash effect
setTimeout(() => {
const splash = document.createElement('div');
splash.className = 'raindrop splash';
splash.style.left = raindrop.style.left;
splash.style.bottom = '40px';
animation.appendChild(splash);
setTimeout(() => {
if (splash.parentNode) {
splash.parentNode.removeChild(splash);
}
}, 600);
}, 1400);
setTimeout(() => {
if (raindrop.parentNode) {
raindrop.parentNode.removeChild(raindrop);
}
}, 1500);
}
}
function createSnowflakes() {
const snowCard = document.querySelector('[data-weather="snow"]:not(.hidden)');
if (snowCard) {
const animation = snowCard.querySelector('.weather-animation');
const snowflake = document.createElement('div');
snowflake.className = Math.random() > 0.5 ? 'snowflake' : 'snowflake crystal';
snowflake.innerHTML = Math.random() > 0.5 ? '❄' : '❅';
snowflake.style.left = Math.random() * 100 + '%';
snowflake.style.animationDuration = (Math.random() * 3 + 3) + 's';
snowflake.style.animationDelay = Math.random() * 2 + 's';
animation.appendChild(snowflake);
setTimeout(() => {
if (snowflake.parentNode) {
snowflake.parentNode.removeChild(snowflake);
}
}, 6000);
}
}
// Card click handlers
document.querySelectorAll('.weather-card').forEach(card => {
card.addEventListener('click', function() {
const weatherType = this.getAttribute('data-weather');
const buttons = document.querySelectorAll('.btn');
buttons.forEach(btn => btn.classList.remove('active'));
document.querySelector(`[onclick="showWeather('${weatherType}')"]`).classList.add('active');
showWeather(weatherType);
});
});
// Initialize
createBackgroundParticles();
// Start particle systems
setInterval(createWindParticles, 800);
setInterval(createRaindrops, 150);
setInterval(createSnowflakes, 600);
// Add smooth scrolling
document.documentElement.style.scrollBehavior = 'smooth';
</script>
</body>
</html>