站里大佬的prompt:
你是一位就职于苹果公司的顶级前端工程师。请创建一个包含CSS和JavaScript的HTML文件,用于生成动画天气卡片。卡片需要以不同动画效果直观展示以下天气状况:
风力(如:飘动的云朵、摇曳的树木或风线)
降雨(如:下落的雨滴、形成的水洼)
晴天(如:闪耀的光线、明亮的背景)
下雪(如:飘落的雪花、积雪效果)
所有天气卡片需要并排显示,背景采用深色设计。所有HTML、CSS和JavaScript代码都需包含在这个单一文件中。JavaScript部分需包含切换不同天气状态的功能(例如通过函数或按钮组),以演示每种天气的动画效果。
将前端显示效果优化得更精致流畅,打造出价值20元/月的精品天气应用既视感。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>精品天气卡片 - Premium Weather Cards</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
min-height: 100vh;
background: linear-gradient(135deg, #0f0f1a 0%, #1a1a2e 50%, #16213e 100%);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
padding: 20px;
overflow-x: auto;
}
.title {
color: #fff;
font-size: 2.5rem;
font-weight: 300;
margin-bottom: 10px;
text-align: center;
letter-spacing: 3px;
text-shadow: 0 0 30px rgba(255, 255, 255, 0.3);
}
.subtitle {
color: rgba(255, 255, 255, 0.5);
font-size: 0.9rem;
margin-bottom: 40px;
letter-spacing: 2px;
}
.cards-container {
display: flex;
gap: 30px;
flex-wrap: wrap;
justify-content: center;
max-width: 1400px;
}
.weather-card {
width: 280px;
height: 400px;
border-radius: 30px;
position: relative;
overflow: hidden;
cursor: pointer;
transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
}
.weather-card:hover {
transform: translateY(-10px) scale(1.02);
box-shadow: 0 30px 80px rgba(0, 0, 0, 0.6);
}
.weather-card.active {
box-shadow: 0 0 40px rgba(255, 255, 255, 0.3), 0 20px 60px rgba(0, 0, 0, 0.5);
}
/* 晴天卡片 */
.sunny-card {
background: linear-gradient(180deg, #4facfe 0%, #00f2fe 100%);
}
.sun {
width: 100px;
height: 100px;
background: radial-gradient(circle, #ffd700 0%, #ff8c00 70%);
border-radius: 50%;
position: absolute;
top: 60px;
left: 50%;
transform: translateX(-50%);
box-shadow: 0 0 60px #ffd700, 0 0 100px #ff8c00;
animation: sunPulse 3s ease-in-out infinite;
}
@keyframes sunPulse {
0%, 100% { transform: translateX(-50%) scale(1); box-shadow: 0 0 60px #ffd700, 0 0 100px #ff8c00; }
50% { transform: translateX(-50%) scale(1.1); box-shadow: 0 0 80px #ffd700, 0 0 120px #ff8c00; }
}
.sun-ray {
position: absolute;
width: 4px;
height: 30px;
background: linear-gradient(to bottom, rgba(255, 215, 0, 0.8), transparent);
top: 50%;
left: 50%;
transform-origin: center bottom;
animation: sunRayRotate 10s linear infinite;
}
.sun-ray:nth-child(1) { transform: translate(-50%, -100%) rotate(0deg); }
.sun-ray:nth-child(2) { transform: translate(-50%, -100%) rotate(45deg); }
.sun-ray:nth-child(3) { transform: translate(-50%, -100%) rotate(90deg); }
.sun-ray:nth-child(4) { transform: translate(-50%, -100%) rotate(135deg); }
.sun-ray:nth-child(5) { transform: translate(-50%, -100%) rotate(180deg); }
.sun-ray:nth-child(6) { transform: translate(-50%, -100%) rotate(225deg); }
.sun-ray:nth-child(7) { transform: translate(-50%, -100%) rotate(270deg); }
.sun-ray:nth-child(8) { transform: translate(-50%, -100%) rotate(315deg); }
@keyframes sunRayRotate {
from { transform: translate(-50%, -100%) rotate(0deg); }
to { transform: translate(-50%, -100%) rotate(360deg); }
}
.cloud {
position: absolute;
background: rgba(255, 255, 255, 0.9);
border-radius: 100px;
opacity: 0.8;
}
.cloud::before,
.cloud::after {
content: '';
position: absolute;
background: rgba(255, 255, 255, 0.9);
border-radius: 100px;
}
.cloud1 {
width: 80px;
height: 30px;
top: 180px;
left: -80px;
animation: cloudFloat1 15s linear infinite;
}
.cloud1::before {
width: 40px;
height: 40px;
top: -20px;
left: 10px;
}
.cloud1::after {
width: 50px;
height: 35px;
top: -15px;
right: 10px;
}
@keyframes cloudFloat1 {
0% { left: -80px; }
100% { left: 100%; }
}
.cloud2 {
width: 60px;
height: 25px;
top: 220px;
left: -60px;
animation: cloudFloat2 20s linear infinite;
animation-delay: 5s;
}
.cloud2::before {
width: 35px;
height: 35px;
top: -18px;
left: 8px;
}
.cloud2::after {
width: 40px;
height: 30px;
top: -12px;
right: 8px;
}
@keyframes cloudFloat2 {
0% { left: -60px; }
100% { left: 100%; }
}
/* 雨天卡片 */
.rainy-card {
background: linear-gradient(180deg, #2c3e50 0%, #4a5568 50%, #2d3748 100%);
}
.dark-cloud {
position: absolute;
background: linear-gradient(180deg, #4a5568 0%, #2d3748 100%);
border-radius: 100px;
top: 40px;
left: 50%;
transform: translateX(-50%);
width: 150px;
height: 50px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
}
.dark-cloud::before,
.dark-cloud::after {
content: '';
position: absolute;
background: linear-gradient(180deg, #4a5568 0%, #2d3748 100%);
border-radius: 100px;
}
.dark-cloud::before {
width: 70px;
height: 70px;
top: -35px;
left: 20px;
}
.dark-cloud::after {
width: 80px;
height: 60px;
top: -25px;
right: 20px;
}
.rain-container {
position: absolute;
top: 100px;
left: 0;
right: 0;
bottom: 0;
overflow: hidden;
}
.raindrop {
position: absolute;
width: 2px;
height: 15px;
background: linear-gradient(to bottom, transparent, rgba(174, 194, 224, 0.8));
border-radius: 2px;
animation: rainFall linear infinite;
}
@keyframes rainFall {
0% { transform: translateY(-20px); opacity: 0; }
10% { opacity: 1; }
90% { opacity: 1; }
100% { transform: translateY(300px); opacity: 0; }
}
.puddle {
position: absolute;
bottom: 30px;
left: 50%;
transform: translateX(-50%);
width: 120px;
height: 20px;
background: rgba(174, 194, 224, 0.3);
border-radius: 50%;
animation: puddleRipple 2s ease-in-out infinite;
}
@keyframes puddleRipple {
0%, 100% { transform: translateX(-50%) scale(1); opacity: 0.3; }
50% { transform: translateX(-50%) scale(1.1); opacity: 0.5; }
}
.lightning {
position: absolute;
top: 80px;
left: 50%;
transform: translateX(-50%);
width: 4px;
height: 100px;
background: linear-gradient(to bottom, #fff, #ffd700);
clip-path: polygon(40% 0, 100% 0, 60% 40%, 80% 40%, 20% 100%, 40% 100%, 0 60%, 20% 60%);
opacity: 0;
animation: lightningFlash 4s ease-in-out infinite;
}
@keyframes lightningFlash {
0%, 90%, 100% { opacity: 0; }
92%, 96% { opacity: 1; }
94% { opacity: 0.3; }
}
/* 雪天卡片 */
.snowy-card {
background: linear-gradient(180deg, #1a202c 0%, #2d3748 50%, #4a5568 100%);
}
.snow-container {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow: hidden;
}
.snowflake {
position: absolute;
color: #fff;
font-size: 1em;
opacity: 0.8;
animation: snowFall linear infinite;
text-shadow: 0 0 5px rgba(255, 255, 255, 0.8);
}
@keyframes snowFall {
0% { transform: translateY(-20px) rotate(0deg); opacity: 0; }
10% { opacity: 0.8; }
90% { opacity: 0.8; }
100% { transform: translateY(420px) rotate(360deg); opacity: 0; }
}
.snow-ground {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 60px;
background: linear-gradient(to top, rgba(255, 255, 255, 0.3), transparent);
border-radius: 50% 50% 0 0 / 20px 20px 0 0;
}
.snow-hill {
position: absolute;
bottom: 0;
background: linear-gradient(180deg, rgba(255, 255, 255, 0.4) 0%, rgba(255, 255, 255, 0.2) 100%);
border-radius: 50% 50% 0 0;
}
.snow-hill1 {
width: 200px;
height: 80px;
left: -50px;
}
.snow-hill2 {
width: 180px;
height: 60px;
right: -30px;
}
/* 风天卡片 */
.windy-card {
background: linear-gradient(180deg, #2d3748 0%, #4a5568 50%, #718096 100%);
}
.wind-lines {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow: hidden;
}
.wind-line {
position: absolute;
height: 2px;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.6), transparent);
border-radius: 2px;
animation: windBlow linear infinite;
}
@keyframes windBlow {
0% { transform: translateX(-100%); opacity: 0; }
10% { opacity: 1; }
90% { opacity: 1; }
100% { transform: translateX(300px); opacity: 0; }
}
.tree {
position: absolute;
bottom: 40px;
left: 50%;
transform: translateX(-50%);
}
.tree-trunk {
width: 20px;
height: 80px;
background: linear-gradient(90deg, #4a3728, #6b4e3d);
margin: 0 auto;
border-radius: 0 0 5px 5px;
}
.tree-leaves {
width: 120px;
height: 100px;
background: linear-gradient(180deg, #48bb78 0%, #2f855a 100%);
border-radius: 50% 50% 45% 45%;
position: relative;
top: -20px;
animation: treeSway 2s ease-in-out infinite;
transform-origin: center bottom;
}
@keyframes treeSway {
0%, 100% { transform: rotate(-3deg); }
50% { transform: rotate(3deg); }
}
.tree-leaves::before,
.tree-leaves::after {
content: '';
position: absolute;
background: linear-gradient(180deg, #48bb78 0%, #2f855a 100%);
border-radius: 50%;
}
.tree-leaves::before {
width: 80px;
height: 80px;
top: -30px;
left: -20px;
}
.tree-leaves::after {
width: 80px;
height: 80px;
top: -30px;
right: -20px;
}
.floating-cloud {
position: absolute;
background: rgba(255, 255, 255, 0.6);
border-radius: 100px;
animation: cloudFloatFast 8s linear infinite;
}
.floating-cloud::before,
.floating-cloud::after {
content: '';
position: absolute;
background: rgba(255, 255, 255, 0.6);
border-radius: 100px;
}
.floating-cloud1 {
width: 60px;
height: 25px;
top: 60px;
left: -60px;
}
.floating-cloud1::before {
width: 35px;
height: 35px;
top: -18px;
left: 8px;
}
.floating-cloud1::after {
width: 40px;
height: 30px;
top: -12px;
right: 8px;
}
@keyframes cloudFloatFast {
0% { left: -80px; }
100% { left: 100%; }
}
/* 卡片信息 */
.card-info {
position: absolute;
bottom: 0;
left: 0;
right: 0;
padding: 25px;
background: linear-gradient(to top, rgba(0, 0, 0, 0.7), transparent);
color: #fff;
}
.weather-type {
font-size: 1.5rem;
font-weight: 600;
margin-bottom: 5px;
text-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
}
.temperature {
font-size: 3rem;
font-weight: 300;
margin-bottom: 5px;
text-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
}
.description {
font-size: 0.9rem;
opacity: 0.8;
text-shadow: 0 1px 5px rgba(0, 0, 0, 0.3);
}
/* 控制按钮 */
.controls {
margin-top: 40px;
display: flex;
gap: 15px;
flex-wrap: wrap;
justify-content: center;
}
.control-btn {
padding: 12px 30px;
border: none;
border-radius: 25px;
background: rgba(255, 255, 255, 0.1);
color: #fff;
font-size: 0.95rem;
cursor: pointer;
transition: all 0.3s ease;
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.2);
letter-spacing: 1px;
}
.control-btn:hover {
background: rgba(255, 255, 255, 0.2);
transform: translateY(-2px);
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
}
.control-btn.active {
background: rgba(255, 255, 255, 0.3);
box-shadow: 0 0 20px rgba(255, 255, 255, 0.3);
}
/* 粒子效果 */
.particle {
position: absolute;
pointer-events: none;
opacity: 0;
}
/* 响应式 */
@media (max-width: 1200px) {
.cards-container {
gap: 20px;
}
.weather-card {
width: 240px;
height: 350px;
}
}
@media (max-width: 768px) {
.title {
font-size: 1.8rem;
}
.weather-card {
width: 100%;
max-width: 300px;
height: 380px;
}
}
</style>
</head>
<body>
<h1 class="title">Weather Cards</h1>
<p class="subtitle">PREMIUM ANIMATED WEATHER EXPERIENCE</p>
<div class="cards-container">
<!-- 晴天卡片 -->
<div class="weather-card sunny-card" data-weather="sunny" onclick="selectWeather('sunny')">
<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="cloud cloud1"></div>
<div class="cloud cloud2"></div>
<div class="card-info">
<div class="weather-type">晴天</div>
<div class="temperature">28°</div>
<div class="description">阳光明媚 · 微风</div>
</div>
</div>
<!-- 雨天卡片 -->
<div class="weather-card rainy-card" data-weather="rainy" onclick="selectWeather('rainy')">
<div class="dark-cloud"></div>
<div class="lightning"></div>
<div class="rain-container" id="rainContainer"></div>
<div class="puddle"></div>
<div class="card-info">
<div class="weather-type">降雨</div>
<div class="temperature">18°</div>
<div class="description">中雨 · 湿度 85%</div>
</div>
</div>
<!-- 雪天卡片 -->
<div class="weather-card snowy-card" data-weather="snowy" onclick="selectWeather('snowy')">
<div class="snow-container" id="snowContainer"></div>
<div class="snow-hill snow-hill1"></div>
<div class="snow-hill snow-hill2"></div>
<div class="snow-ground"></div>
<div class="card-info">
<div class="weather-type">下雪</div>
<div class="temperature">-3°</div>
<div class="description">大雪 · 积雪 5cm</div>
</div>
</div>
<!-- 风天卡片 -->
<div class="weather-card windy-card" data-weather="windy" onclick="selectWeather('windy')">
<div class="wind-lines" id="windContainer"></div>
<div class="floating-cloud floating-cloud1"></div>
<div class="tree">
<div class="tree-leaves"></div>
<div class="tree-trunk"></div>
</div>
<div class="card-info">
<div class="weather-type">大风</div>
<div class="temperature">15°</div>
<div class="description">西北风 · 6级</div>
</div>
</div>
</div>
<div class="controls">
<button class="control-btn active" onclick="selectWeather('sunny')">☀️ 晴天</button>
<button class="control-btn" onclick="selectWeather('rainy')">🌧️ 降雨</button>
<button class="control-btn" onclick="selectWeather('snowy')">❄️ 下雪</button>
<button class="control-btn" onclick="selectWeather('windy')">💨 大风</button>
<button class="control-btn" onclick="toggleAnimation()">⏸️ 暂停/播放</button>
</div>
<script>
// 全局动画状态
let animationPaused = false;
let currentWeather = 'sunny';
// 初始化雨滴
function createRaindrops() {
const container = document.getElementById('rainContainer');
container.innerHTML = '';
for (let i = 0; i < 40; i++) {
const drop = document.createElement('div');
drop.className = 'raindrop';
drop.style.left = Math.random() * 100 + '%';
drop.style.animationDuration = (Math.random() * 0.5 + 0.5) + 's';
drop.style.animationDelay = Math.random() * 2 + 's';
drop.style.opacity = Math.random() * 0.5 + 0.5;
container.appendChild(drop);
}
}
// 初始化雪花
function createSnowflakes() {
const container = document.getElementById('snowContainer');
container.innerHTML = '';
const snowflakeSymbols = ['❄', '❅', '❆'];
for (let i = 0; i < 50; i++) {
const flake = document.createElement('div');
flake.className = 'snowflake';
flake.innerHTML = snowflakeSymbols[Math.floor(Math.random() * snowflakeSymbols.length)];
flake.style.left = Math.random() * 100 + '%';
flake.style.fontSize = (Math.random() * 10 + 10) + 'px';
flake.style.animationDuration = (Math.random() * 3 + 2) + 's';
flake.style.animationDelay = Math.random() * 5 + 's';
flake.style.opacity = Math.random() * 0.6 + 0.4;
container.appendChild(flake);
}
}
// 初始化风线
function createWindLines() {
const container = document.getElementById('windContainer');
container.innerHTML = '';
for (let i = 0; i < 15; i++) {
const line = document.createElement('div');
line.className = 'wind-line';
line.style.top = (Math.random() * 250 + 50) + 'px';
line.style.width = (Math.random() * 100 + 50) + 'px';
line.style.animationDuration = (Math.random() * 1 + 0.5) + 's';
line.style.animationDelay = Math.random() * 2 + 's';
container.appendChild(line);
}
}
// 选择天气
function selectWeather(weather) {
currentWeather = weather;
// 更新卡片状态
document.querySelectorAll('.weather-card').forEach(card => {
card.classList.remove('active');
if (card.dataset.weather === weather) {
card.classList.add('active');
}
});
// 更新按钮状态
document.querySelectorAll('.control-btn').forEach((btn, index) => {
btn.classList.remove('active');
if (index < 4 && btn.textContent.includes(getWeatherEmoji(weather))) {
btn.classList.add('active');
}
});
// 触发粒子效果
createParticles(weather);
}
// 获取天气emoji
function getWeatherEmoji(weather) {
const emojis = {
'sunny': '☀️',
'rainy': '🌧️',
'snowy': '❄️',
'windy': '💨'
};
return emojis[weather] || '☀️';
}
// 创建粒子效果
function createParticles(weather) {
const colors = {
'sunny': '#ffd700',
'rainy': '#aec2e0',
'snowy': '#ffffff',
'windy': '#ffffff'
};
const card = document.querySelector(`[data-weather="${weather}"]`);
const rect = card.getBoundingClientRect();
for (let i = 0; i < 20; i++) {
setTimeout(() => {
const particle = document.createElement('div');
particle.className = 'particle';
particle.style.width = '6px';
particle.style.height = '6px';
particle.style.background = colors[weather];
particle.style.borderRadius = '50%';
particle.style.left = (rect.width / 2) + 'px';
particle.style.top = (rect.height / 2) + 'px';
particle.style.boxShadow = `0 0 10px ${colors[weather]}`;
const angle = (Math.PI * 2 * i) / 20;
const velocity = 100 + Math.random() * 100;
const tx = Math.cos(angle) * velocity;
const ty = Math.sin(angle) * velocity;
particle.style.transition = 'all 0.8s ease-out';
card.appendChild(particle);
requestAnimationFrame(() => {
particle.style.opacity = '1';
particle.style.transform = `translate(${tx}px, ${ty}px) scale(0)`;
});
setTimeout(() => particle.remove(), 800);
}, i * 30);
}
}
// 切换动画
function toggleAnimation() {
animationPaused = !animationPaused;
document.querySelectorAll('.weather-card *').forEach(el => {
el.style.animationPlayState = animationPaused ? 'paused' : 'running';
});
}
// 鼠标跟随效果
document.querySelectorAll('.weather-card').forEach(card => {
card.addEventListener('mousemove', (e) => {
const rect = card.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
const centerX = rect.width / 2;
const centerY = rect.height / 2;
const rotateX = (y - centerY) / 20;
const rotateY = (centerX - x) / 20;
card.style.transform = `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) translateY(-10px) scale(1.02)`;
});
card.addEventListener('mouseleave', () => {
card.style.transform = '';
});
});
// 初始化
document.addEventListener('DOMContentLoaded', () => {
createRaindrops();
createSnowflakes();
createWindLines();
selectWeather('sunny');
});
// 窗口大小改变时重新初始化
window.addEventListener('resize', () => {
createRaindrops();
createSnowflakes();
createWindLines();
});
</script>
</body>
</html>

