MiniMax-M2.5(API)天气卡片

以 iOS 18 的设计风格做一个带有动画效果的天气卡片,要求是使用 HTML、CSS 和基础 JavaScript,使用横板天气页面(拥有 4 个天气卡片 (晴天,大风,暴雨,暴雪))。应足够美观,实现一定的交互效果。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>iOS 18 天气卡片</title>
    <style>
        @import url('https://fonts.googleapis.com/css2?family=SF+Pro+Display:wght@300;400;500;600;700&display=swap');
        
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Segoe UI', Roboto, sans-serif;
            min-height: 100vh;
            background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
            display: flex;
            justify-content: center;
            align-items: center;
            overflow: hidden;
            padding: 20px;
            opacity: 0;
            transition: opacity 0.5s ease;
        }
        
        body.loaded {
            opacity: 1;
        }
        
        /* 背景装饰 */
        .bg-decoration {
            position: fixed;
            width: 600px;
            height: 600px;
            border-radius: 50%;
            filter: blur(120px);
            opacity: 0.4;
            animation: float 20s ease-in-out infinite;
            z-index: 0;
        }
        
        .bg-decoration:nth-child(1) {
            background: linear-gradient(135deg, #ff6b6b, #feca57);
            top: -200px;
            left: -100px;
        }
        
        .bg-decoration:nth-child(2) {
            background: linear-gradient(135deg, #667eea, #764ba2);
            bottom: -200px;
            right: -100px;
            animation-delay: -10s;
        }
        
        @keyframes float {
            0%, 100% { transform: translate(0, 0) scale(1); }
            33% { transform: translate(30px, -30px) scale(1.1); }
            66% { transform: translate(-20px, 20px) scale(0.9); }
        }
        
        .container {
            position: relative;
            z-index: 1;
            width: 100%;
            max-width: 1200px;
        }
        
        .header {
            text-align: center;
            margin-bottom: 40px;
            animation: fadeInDown 0.8s ease-out;
        }
        
        .header h1 {
            font-size: 2.5rem;
            font-weight: 300;
            color: rgba(255, 255, 255, 0.9);
            letter-spacing: 2px;
            margin-bottom: 8px;
        }
        
        .header p {
            font-size: 1rem;
            color: rgba(255, 255, 255, 0.6);
            font-weight: 400;
        }
        
        /* 卡片容器 */
        .cards-wrapper {
            display: flex;
            gap: 24px;
            justify-content: center;
            flex-wrap: wrap;
            perspective: 1000px;
        }
        
        /* 天气卡片基础样式 */
        .weather-card {
            width: 260px;
            height: 380px;
            border-radius: 32px;
            position: relative;
            cursor: pointer;
            transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
            overflow: hidden;
            animation: fadeInUp 0.8s ease-out backwards;
        }
        
        .weather-card:nth-child(1) { animation-delay: 0.1s; }
        .weather-card:nth-child(2) { animation-delay: 0.2s; }
        .weather-card:nth-child(3) { animation-delay: 0.3s; }
        .weather-card:nth-child(4) { animation-delay: 0.4s; }
        
        /* 卡片玻璃效果 */
        .weather-card::before {
            content: '';
            position: absolute;
            inset: 0;
            border-radius: 32px;
            padding: 1px;
            background: linear-gradient(135deg, rgba(255,255,255,0.4), rgba(255,255,255,0.1));
            -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
            mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
            -webkit-mask-composite: xor;
            mask-composite: exclude;
            pointer-events: none;
            z-index: 2;
        }
        
        .weather-card .card-bg {
            position: absolute;
            inset: 0;
            border-radius: 32px;
            opacity: 0.85;
            transition: all 0.5s ease;
        }
        
        /* 晴天 */
        .weather-card.sunny .card-bg {
            background: linear-gradient(180deg, #ff9a56 0%, #ff6b35 50%, #f7931e 100%);
        }
        
        .weather-card.sunny .weather-icon {
            font-size: 80px;
            animation: sunPulse 3s ease-in-out infinite;
        }
        
        @keyframes sunPulse {
            0%, 100% { transform: scale(1) rotate(0deg); text-shadow: 0 0 40px rgba(255, 200, 100, 0.8); }
            50% { transform: scale(1.1) rotate(5deg); text-shadow: 0 0 60px rgba(255, 200, 100, 1); }
        }
        
        /* 大风 */
        .weather-card.windy .card-bg {
            background: linear-gradient(180deg, #4facfe 0%, #00f2fe 50%, #43e97b 100%);
        }
        
        .weather-card.windy .weather-icon {
            font-size: 80px;
            animation: windBlow 2s ease-in-out infinite;
        }
        
        @keyframes windBlow {
            0%, 100% { transform: translateX(0) skewX(0deg); }
            25% { transform: translateX(-5px) skewX(-5deg); }
            75% { transform: translateX(5px) skewX(5deg); }
        }
        
        /* 暴雨 */
        .weather-card.storm .card-bg {
            background: linear-gradient(180deg, #434343 0%, #2c3e50 50%, #1a252f 100%);
        }
        
        .weather-card.storm .weather-icon {
            font-size: 80px;
            animation: rainShake 1.5s ease-in-out infinite;
        }
        
        @keyframes rainShake {
            0%, 100% { transform: translateY(0); }
            50% { transform: translateY(-3px); }
        }
        
        /* 暴雪 */
        .weather-card.snow .card-bg {
            background: linear-gradient(180deg, #e0e5ec 0%, #a8c0ce 50%, #6b8fa3 100%);
        }
        
        .weather-card.snow .weather-icon {
            font-size: 80px;
            animation: snowFloat 3s ease-in-out infinite;
        }
        
        .weather-card.snow .temperature,
        .weather-card.snow .weather-desc,
        .weather-card.snow .location,
        .weather-card.snow .detail-label,
        .weather-card.snow .detail-value {
            color: #2c3e50 !important;
        }
        
        .weather-card.snow .card-bottom {
            border-top-color: rgba(44, 62, 80, 0.2) !important;
        }
        
        @keyframes snowFloat {
            0%, 100% { transform: translateY(0) rotate(0deg); opacity: 1; }
            50% { transform: translateY(-5px) rotate(10deg); opacity: 0.8; }
        }
        
        /* 卡片内容 */
        .card-content {
            position: relative;
            z-index: 1;
            height: 100%;
            display: flex;
            flex-direction: column;
            justify-content: space-between;
            padding: 28px;
            color: white;
        }
        
        .card-top {
            display: flex;
            justify-content: space-between;
            align-items: flex-start;
        }
        
        .location {
            font-size: 0.9rem;
            font-weight: 500;
            opacity: 0.9;
            letter-spacing: 0.5px;
        }
        
        .weather-icon {
            display: block;
            margin-top: 20px;
            filter: drop-shadow(0 10px 20px rgba(0,0,0,0.2));
        }
        
        .card-center {
            text-align: center;
        }
        
        .temperature {
            font-size: 4.5rem;
            font-weight: 200;
            line-height: 1;
            letter-spacing: -2px;
            text-shadow: 0 4px 20px rgba(0,0,0,0.2);
        }
        
        .temperature span {
            font-size: 2rem;
            font-weight: 400;
            vertical-align: super;
        }
        
        .weather-desc {
            font-size: 1.1rem;
            font-weight: 400;
            margin-top: 8px;
            opacity: 0.9;
        }
        
        .card-bottom {
            display: flex;
            justify-content: space-between;
            padding-top: 20px;
            border-top: 1px solid rgba(255,255,255,0.2);
        }
        
        .detail-item {
            text-align: center;
        }
        
        .detail-label {
            font-size: 0.7rem;
            opacity: 0.7;
            text-transform: uppercase;
            letter-spacing: 1px;
            margin-bottom: 4px;
        }
        
        .detail-value {
            font-size: 1rem;
            font-weight: 500;
        }
        
        /* 装饰元素 */
        .card-decoration {
            position: absolute;
            border-radius: 50%;
            opacity: 0.3;
        }
        
        .weather-card.sunny .card-decoration:nth-child(1) {
            width: 150px;
            height: 150px;
            background: radial-gradient(circle, rgba(255,255,255,0.3) 0%, transparent 70%);
            top: -50px;
            right: -30px;
            animation: rotate 15s linear infinite;
        }
        
        .weather-card.sunny .card-decoration:nth-child(2) {
            width: 80px;
            height: 80px;
            background: radial-gradient(circle, rgba(255,255,255,0.4) 0%, transparent 70%);
            bottom: 60px;
            left: -20px;
            animation: rotate 10s linear infinite reverse;
        }
        
        .weather-card.windy .card-decoration {
            width: 100px;
            height: 100px;
            border: 2px solid rgba(255,255,255,0.2);
            border-radius: 50%;
            animation: windCircle 4s linear infinite;
        }
        
        .weather-card.storm .card-decoration {
            width: 120px;
            height: 120px;
            background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 70%);
            animation: stormPulse 2s ease-in-out infinite;
        }
        
        .weather-card.snow .card-decoration {
            width: 8px;
            height: 8px;
            background: white;
            border-radius: 50%;
            animation: snowParticle 2s ease-in-out infinite;
        }
        
        .weather-card.snow .card-decoration:nth-child(1) { top: 30%; left: 20%; animation-delay: 0s; }
        .weather-card.snow .card-decoration:nth-child(2) { top: 50%; right: 15%; animation-delay: 0.5s; }
        
        @keyframes rotate {
            from { transform: rotate(0deg); }
            to { transform: rotate(360deg); }
        }
        
        @keyframes windCircle {
            0% { transform: rotate(0deg) scale(1); opacity: 0.3; }
            50% { transform: rotate(180deg) scale(1.2); opacity: 0.1; }
            100% { transform: rotate(360deg) scale(1); opacity: 0.3; }
        }
        
        @keyframes stormPulse {
            0%, 100% { transform: scale(1); opacity: 0.3; }
            50% { transform: scale(1.3); opacity: 0.1; }
        }
        
        @keyframes snowParticle {
            0%, 100% { transform: translateY(0); opacity: 1; }
            50% { transform: translateY(-20px); opacity: 0.3; }
        }
        
        /* 悬停效果 */
        .weather-card:hover {
            transform: translateY(-15px) scale(1.02);
            box-shadow: 0 30px 60px rgba(0,0,0,0.3);
        }
        
        .weather-card:hover .card-bg {
            opacity: 1;
            transform: scale(1.05);
        }
        
        /* 动画关键帧 */
        @keyframes fadeInDown {
            from {
                opacity: 0;
                transform: translateY(-30px);
            }
            to {
                opacity: 1;
                transform: translateY(0);
            }
        }
        
        @keyframes fadeInUp {
            from {
                opacity: 0;
                transform: translateY(50px);
            }
            to {
                opacity: 1;
                transform: translateY(0);
            }
        }
        
        /* 响应式设计 */
        @media (max-width: 1200px) {
            .cards-wrapper {
                flex-wrap: wrap;
            }
        }
        
        @media (max-width: 768px) {
            .header h1 {
                font-size: 1.8rem;
            }
            
            .weather-card {
                width: 100%;
                max-width: 300px;
                height: 320px;
            }
            
            .temperature {
                font-size: 3.5rem;
            }
        }
        
        /* 闪光效果 */
        .glint {
            position: absolute;
            width: 100%;
            height: 100%;
            top: 0;
            left: 0;
            background: linear-gradient(
                135deg,
                transparent 40%,
                rgba(255,255,255,0.1) 45%,
                rgba(255,255,255,0.2) 50%,
                rgba(255,255,255,0.1) 55%,
                transparent 60%
            );
            transform: translateX(-100%);
            transition: transform 0.6s ease;
            pointer-events: none;
            border-radius: 32px;
            z-index: 3;
        }
        
        .weather-card:hover .glint {
            transform: translateX(100%);
            transition: transform 0.8s ease;
        }
    </style>
</head>
<body>
    <!-- 背景装饰 -->
    <div class="bg-decoration"></div>
    <div class="bg-decoration"></div>
    
    <div class="container">
        <div class="header">
            <h1>Weather</h1>
            <p>Beautiful weather, beautiful day</p>
        </div>
        
        <div class="cards-wrapper">
            <!-- 晴天 -->
            <div class="weather-card sunny">
                <div class="card-bg"></div>
                <div class="card-decoration"></div>
                <div class="card-decoration"></div>
                <div class="glint"></div>
                
                <div class="card-content">
                    <div class="card-top">
                        <div class="location">☀️ 晴朗</div>
                        <div class="menu-icon">⋮</div>
                    </div>
                    
                    <div class="weather-icon">☀️</div>
                    
                    <div class="card-center">
                        <div class="temperature" data-temp="28">0<span>°</span></div>
                        <div class="weather-desc">阳光明媚</div>
                    </div>
                    
                    <div class="card-bottom">
                        <div class="detail-item">
                            <div class="detail-label">湿度</div>
                            <div class="detail-value">45%</div>
                        </div>
                        <div class="detail-item">
                            <div class="detail-label">风速</div>
                            <div class="detail-value">12 km/h</div>
                        </div>
                        <div class="detail-item">
                            <div class="detail-label">紫外线</div>
                            <div class="detail-value">中等</div>
                        </div>
                    </div>
                </div>
            </div>
            
            <!-- 大风 -->
            <div class="weather-card windy">
                <div class="card-bg"></div>
                <div class="card-decoration"></div>
                <div class="card-decoration"></div>
                <div class="glint"></div>
                
                <div class="card-content">
                    <div class="card-top">
                        <div class="location">💨 大风</div>
                    </div>
                    
                    <div class="weather-icon">🌀</div>
                    
                    <div class="card-center">
                        <div class="temperature" data-temp="19">0<span>°</span></div>
                        <div class="weather-desc">大风蓝色预警</div>
                    </div>
                    
                    <div class="card-bottom">
                        <div class="detail-item">
                            <div class="detail-label">风速</div>
                            <div class="detail-value">45 km/h</div>
                        </div>
                        <div class="detail-item">
                            <div class="detail-label">阵风</div>
                            <div class="detail-value">65 km/h</div>
                        </div>
                        <div class="detail-item">
                            <div class="detail-label">风向</div>
                            <div class="detail-value">西北</div>
                        </div>
                    </div>
                </div>
            </div>
            
            <!-- 暴雨 -->
            <div class="weather-card storm">
                <div class="card-bg"></div>
                <div class="card-decoration"></div>
                <div class="glint"></div>
                
                <div class="card-content">
                    <div class="card-top">
                        <div class="location">⛈️ 暴雨</div>
                    </div>
                    
                    <div class="weather-icon">⛈️</div>
                    
                    <div class="card-center">
                        <div class="temperature" data-temp="22">0<span>°</span></div>
                        <div class="weather-desc">暴雨红色预警</div>
                    </div>
                    
                    <div class="card-bottom">
                        <div class="detail-item">
                            <div class="detail-label">降水量</div>
                            <div class="detail-value">85 mm</div>
                        </div>
                        <div class="detail-item">
                            <div class="detail-label">湿度</div>
                            <div class="detail-value">92%</div>
                        </div>
                        <div class="detail-item">
                            <div class="detail-label">气压</div>
                            <div class="detail-value">1002 hPa</div>
                        </div>
                    </div>
                </div>
            </div>
            
            <!-- 暴雪 -->
            <div class="weather-card snow">
                <div class="card-bg"></div>
                <div class="card-decoration"></div>
                <div class="card-decoration"></div>
                <div class="glint"></div>
                
                <div class="card-content">
                    <div class="card-top">
                        <div class="location">❄️ 暴雪</div>
                    </div>
                    
                    <div class="weather-icon">🌨️</div>
                    
                    <div class="card-center">
                        <div class="temperature" data-temp="-8">0<span>°</span></div>
                        <div class="weather-desc">暴雪橙色预警</div>
                    </div>
                    
                    <div class="card-bottom">
                        <div class="detail-item">
                            <div class="detail-label">积雪</div>
                            <div class="detail-value">25 cm</div>
                        </div>
                        <div class="detail-item">
                            <div class="detail-label">能见度</div>
                            <div class="detail-value">200 m</div>
                        </div>
                        <div class="detail-item">
                            <div class="detail-label">体感</div>
                            <div class="detail-value">-15°</div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    
    <script>
        // 温度数字动画 - 修复版
        function animateTemperature(element) {
            const targetTemp = parseInt(element.getAttribute('data-temp'), 10);
            const isNegative = targetTemp < 0;
            const absTarget = Math.abs(targetTemp);
            
            // 起始值
            let current = 0;
            const duration = 1500; // 动画持续时间
            const startTime = performance.now();
            
            function update(currentTime) {
                const elapsed = currentTime - startTime;
                const progress = Math.min(elapsed / duration, 1);
                
                // 使用缓动函数让动画更自然
                const easeProgress = 1 - Math.pow(1 - progress, 3);
                
                const currentValue = Math.round(absTarget * easeProgress);
                const displayValue = isNegative ? -currentValue : currentValue;
                
                element.innerHTML = `${displayValue}<span>°</span>`;
                
                if (progress < 1) {
                    requestAnimationFrame(update);
                } else {
                    // 确保最终显示正确的值
                    element.innerHTML = `${targetTemp}<span>°</span>`;
                }
            }
            
            requestAnimationFrame(update);
        }
        
        // 初始化所有温度动画
        document.querySelectorAll('.temperature').forEach((temp, index) => {
            setTimeout(() => {
                animateTemperature(temp);
            }, 300 + index * 150);
        });
        
        // 卡片交互动画
        document.querySelectorAll('.weather-card').forEach(card => {
            // 鼠标进入动画
            card.addEventListener('mouseenter', () => {
                card.style.transition = 'all 0.5s cubic-bezier(0.4, 0, 0.2, 1)';
            });
            
            // 鼠标离开动画
            card.addEventListener('mouseleave', () => {
                card.style.transition = 'all 0.5s cubic-bezier(0.4, 0, 0.2, 1)';
            });
            
            // 点击效果
            card.addEventListener('click', function(e) {
                // 创建涟漪效果
                const ripple = document.createElement('div');
                ripple.style.cssText = `
                    position: absolute;
                    width: 10px;
                    height: 10px;
                    background: rgba(255,255,255,0.6);
                    border-radius: 50%;
                    transform: translate(-50%, -50%);
                    pointer-events: none;
                    z-index: 10;
                    animation: ripple 0.6s ease-out forwards;
                `;
                
                const rect = card.getBoundingClientRect();
                const x = e.clientX - rect.left;
                const y = e.clientY - rect.top;
                
                ripple.style.left = x + 'px';
                ripple.style.top = y + 'px';
                
                card.appendChild(ripple);
                
                setTimeout(() => ripple.remove(), 600);
            });
        });
        
        // 添加涟漪动画
        const style = document.createElement('style');
        style.textContent = `
            @keyframes ripple {
                0% {
                    transform: translate(-50%, -50%) scale(0);
                    opacity: 1;
                }
                100% {
                    transform: translate(-50%, -50%) scale(30);
                    opacity: 0;
                }
            }
        `;
        document.head.appendChild(style);
        
        // 页面加载完成
        window.addEventListener('load', () => {
            document.body.classList.add('loaded');
        });
    </script>
</body>
</html>
23 个赞

很不错啊,感觉比opus都自然

2 个赞

线条风格很好看

1 个赞

这个好看

不戳不戳

不错不错

这么看国产模型还不错啊
MinMax做的蛮好看的 :grinning_face_with_smiling_eyes:

1 个赞

这个前端我觉得做的比glm更好,但是后端效果如何呢

1 个赞

m2.5审美也维持着在线

还不错的样子。

不错,好看

下面是对比:
GLM-5

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>天气 - iOS 18</title>
  <script src="https://cdn.tailwindcss.com"></script>
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=SF+Pro+Display:wght@300;400;500;600;700&display=swap" rel="stylesheet">
  <style>
    :root {
      --sunny-bg: linear-gradient(145deg, #FF9500 0%, #FF6B00 40%, #FF3B30 100%);
      --windy-bg: linear-gradient(145deg, #5AC8FA 0%, #007AFF 50%, #5856D6 100%);
      --rainy-bg: linear-gradient(145deg, #1C3D5A 0%, #0A2540 50%, #061625 100%);
      --snowy-bg: linear-gradient(145deg, #E5E5EA 0%, #AEAEB2 40%, #8E8E93 100%);
    }

    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    body {
      font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Helvetica Neue', sans-serif;
      min-height: 100vh;
      background: linear-gradient(135deg, #0f0c29 0%, #302b63 50%, #24243e 100%);
      overflow-x: hidden;
      -webkit-font-smoothing: antialiased;
    }

    /* 主容器 */
    .weather-container {
      display: grid;
      grid-template-columns: repeat(4, 1fr);
      gap: 24px;
      padding: 60px 40px;
      max-width: 1600px;
      margin: 0 auto;
    }

    @media (max-width: 1200px) {
      .weather-container {
        grid-template-columns: repeat(2, 1fr);
        padding: 40px 24px;
      }
    }

    @media (max-width: 640px) {
      .weather-container {
        grid-template-columns: 1fr;
        padding: 24px 16px;
      }
    }

    /* 天气卡片基础样式 */
    .weather-card {
      position: relative;
      border-radius: 32px;
      padding: 28px;
      height: 380px;
      overflow: hidden;
      cursor: pointer;
      transform: translateY(0) scale(1);
      transition: transform 0.5s cubic-bezier(0.34, 1.56, 0.64, 1),
                  box-shadow 0.4s ease;
      will-change: transform;
    }

    .weather-card::before {
      content: '';
      position: absolute;
      inset: 0;
      background: inherit;
      z-index: 0;
    }

    .weather-card::after {
      content: '';
      position: absolute;
      inset: 0;
      background: linear-gradient(180deg, 
        rgba(255,255,255,0.15) 0%, 
        rgba(255,255,255,0.05) 30%,
        transparent 60%);
      z-index: 1;
      pointer-events: none;
    }

    .weather-card:hover {
      transform: translateY(-12px) scale(1.02);
      box-shadow: 0 40px 80px -20px rgba(0,0,0,0.5);
    }

    .weather-card:active {
      transform: translateY(-6px) scale(0.98);
      transition-duration: 0.15s;
    }

    /* 卡片内容层 */
    .card-content {
      position: relative;
      z-index: 10;
      height: 100%;
      display: flex;
      flex-direction: column;
      justify-content: space-between;
    }

    /* 晴天卡片 */
    .sunny-card {
      background: var(--sunny-bg);
      box-shadow: 0 20px 60px -15px rgba(255, 107, 0, 0.6);
    }

    .sunny-card:hover {
      box-shadow: 0 40px 100px -20px rgba(255, 59, 48, 0.7);
    }

    /* 大风卡片 */
    .windy-card {
      background: var(--windy-bg);
      box-shadow: 0 20px 60px -15px rgba(0, 122, 255, 0.5);
    }

    .windy-card:hover {
      box-shadow: 0 40px 100px -20px rgba(88, 86, 214, 0.6);
    }

    /* 暴雨卡片 */
    .rainy-card {
      background: var(--rainy-bg);
      box-shadow: 0 20px 60px -15px rgba(10, 37, 64, 0.8);
    }

    .rainy-card:hover {
      box-shadow: 0 40px 100px -20px rgba(6, 22, 37, 0.9);
    }

    /* 暴雪卡片 */
    .snowy-card {
      background: var(--snowy-bg);
      box-shadow: 0 20px 60px -15px rgba(142, 142, 147, 0.5);
    }

    .snowy-card:hover {
      box-shadow: 0 40px 100px -20px rgba(174, 174, 178, 0.6);
    }

    /* 文字样式 */
    .location {
      font-size: 22px;
      font-weight: 600;
      color: rgba(255,255,255,0.95);
      text-shadow: 0 2px 8px rgba(0,0,0,0.15);
      letter-spacing: -0.3px;
    }

    .weather-desc {
      font-size: 15px;
      font-weight: 400;
      color: rgba(255,255,255,0.75);
      margin-top: 4px;
    }

    .temperature {
      font-size: 72px;
      font-weight: 300;
      color: rgba(255,255,255,0.98);
      line-height: 1;
      letter-spacing: -4px;
      text-shadow: 0 4px 20px rgba(0,0,0,0.15);
    }

    .snowy-card .location,
    .snowy-card .temperature {
      color: rgba(0,0,0,0.85);
      text-shadow: none;
    }

    .snowy-card .weather-desc {
      color: rgba(0,0,0,0.6);
    }

    /* 底部数据行 */
    .stats-row {
      display: flex;
      gap: 20px;
    }

    .stat-item {
      display: flex;
      flex-direction: column;
      gap: 2px;
    }

    .stat-label {
      font-size: 11px;
      font-weight: 500;
      color: rgba(255,255,255,0.55);
      text-transform: uppercase;
      letter-spacing: 0.5px;
    }

    .snowy-card .stat-label {
      color: rgba(0,0,0,0.45);
    }

    .stat-value {
      font-size: 16px;
      font-weight: 500;
      color: rgba(255,255,255,0.9);
    }

    .snowy-card .stat-value {
      color: rgba(0,0,0,0.75);
    }

    /* 天气动画容器 */
    .weather-animation {
      position: absolute;
      inset: 0;
      z-index: 5;
      pointer-events: none;
      overflow: hidden;
    }

    /* 晴天动画 - 太阳 */
    .sun {
      position: absolute;
      top: 20%;
      right: 15%;
      width: 100px;
      height: 100px;
      background: radial-gradient(circle, 
        #FFEB3B 0%, 
        #FFC107 40%, 
        rgba(255, 193, 7, 0) 70%);
      border-radius: 50%;
      animation: sunPulse 4s ease-in-out infinite;
    }

    .sun::before {
      content: '';
      position: absolute;
      inset: -30px;
      background: radial-gradient(circle, 
        rgba(255, 235, 59, 0.3) 0%, 
        rgba(255, 193, 7, 0.1) 50%, 
        transparent 70%);
      border-radius: 50%;
      animation: sunGlow 3s ease-in-out infinite alternate;
    }

    @keyframes sunPulse {
      0%, 100% { transform: scale(1); }
      50% { transform: scale(1.08); }
    }

    @keyframes sunGlow {
      0% { transform: scale(1); opacity: 0.8; }
      100% { transform: scale(1.2); opacity: 1; }
    }

    /* 大风动画 - 风线 */
    .wind-line {
      position: absolute;
      height: 3px;
      background: linear-gradient(90deg, 
        transparent 0%, 
        rgba(255,255,255,0.8) 30%, 
        rgba(255,255,255,0.9) 50%, 
        rgba(255,255,255,0.8) 70%, 
        transparent 100%);
      border-radius: 4px;
      animation: windBlow 2.5s ease-in-out infinite;
    }

    .wind-line:nth-child(1) { top: 25%; left: -100%; width: 80px; animation-delay: 0s; }
    .wind-line:nth-child(2) { top: 35%; left: -100%; width: 120px; animation-delay: 0.4s; }
    .wind-line:nth-child(3) { top: 50%; left: -100%; width: 60px; animation-delay: 0.8s; }
    .wind-line:nth-child(4) { top: 60%; left: -100%; width: 100px; animation-delay: 1.2s; }
    .wind-line:nth-child(5) { top: 70%; left: -100%; width: 70px; animation-delay: 1.6s; }

    @keyframes windBlow {
      0% { transform: translateX(0); opacity: 0; }
      20% { opacity: 1; }
      80% { opacity: 1; }
      100% { transform: translateX(calc(100vw)); opacity: 0; }
    }

    /* 暴雨动画 - 雨滴 */
    .raindrop {
      position: absolute;
      width: 2px;
      background: linear-gradient(180deg, 
        transparent 0%, 
        rgba(255,255,255,0.6) 50%, 
        rgba(255,255,255,0.9) 100%);
      border-radius: 0 0 4px 4px;
      animation: rainFall linear infinite;
    }

    @keyframes rainFall {
      0% { transform: translateY(-100%) rotate(15deg); opacity: 0; }
      10% { opacity: 1; }
      90% { opacity: 1; }
      100% { transform: translateY(500px) rotate(15deg); opacity: 0; }
    }

    /* 暴雪动画 - 雪花 */
    .snowflake {
      position: absolute;
      color: rgba(255,255,255,0.9);
      font-size: 12px;
      animation: snowFall linear infinite;
      text-shadow: 0 0 5px rgba(255,255,255,0.5);
    }

    .snowy-card .snowflake {
      color: rgba(100, 100, 110, 0.6);
      text-shadow: none;
    }

    @keyframes snowFall {
      0% { 
        transform: translateY(-20px) translateX(0) rotate(0deg); 
        opacity: 0; 
      }
      10% { opacity: 1; }
      90% { opacity: 0.8; }
      100% { 
        transform: translateY(420px) translateX(30px) rotate(360deg); 
        opacity: 0; 
      }
    }

    /* 云朵效果 */
    .cloud {
      position: absolute;
      background: rgba(255,255,255,0.2);
      border-radius: 50%;
      filter: blur(1px);
    }

    .cloud::before,
    .cloud::after {
      content: '';
      position: absolute;
      background: inherit;
      border-radius: 50%;
    }

    .cloud-1 {
      width: 60px;
      height: 30px;
      top: 40%;
      right: -20px;
      animation: cloudFloat 8s ease-in-out infinite;
    }

    .cloud-1::before {
      width: 35px;
      height: 35px;
      top: -15px;
      left: 8px;
    }

    .cloud-1::after {
      width: 25px;
      height: 25px;
      top: -8px;
      right: 8px;
    }

    @keyframes cloudFloat {
      0%, 100% { transform: translateX(0); }
      50% { transform: translateX(-15px); }
    }

    /* 头部样式 */
    .header {
      text-align: center;
      padding: 40px 20px 20px;
    }

    .header h1 {
      font-size: 42px;
      font-weight: 700;
      color: rgba(255,255,255,0.95);
      letter-spacing: -1px;
      margin-bottom: 8px;
    }

    .header p {
      font-size: 17px;
      color: rgba(255,255,255,0.5);
      font-weight: 400;
    }

    /* 玻璃态导航 */
    .glass-nav {
      position: fixed;
      bottom: 30px;
      left: 50%;
      transform: translateX(-50%);
      background: rgba(255,255,255,0.1);
      backdrop-filter: blur(20px);
      -webkit-backdrop-filter: blur(20px);
      border: 1px solid rgba(255,255,255,0.15);
      border-radius: 24px;
      padding: 12px 24px;
      display: flex;
      gap: 24px;
      z-index: 100;
    }

    .nav-dot {
      width: 10px;
      height: 10px;
      border-radius: 50%;
      background: rgba(255,255,255,0.3);
      cursor: pointer;
      transition: all 0.3s ease;
    }

    .nav-dot:hover {
      background: rgba(255,255,255,0.6);
      transform: scale(1.2);
    }

    .nav-dot.active {
      background: rgba(255,255,255,0.95);
      box-shadow: 0 0 10px rgba(255,255,255,0.5);
    }

    /* Reduced motion */
    @media (prefers-reduced-motion: reduce) {
      .weather-card,
      .sun,
      .sun::before,
      .wind-line,
      .raindrop,
      .snowflake,
      .cloud {
        animation: none !important;
        transition: none !important;
      }
    }

    /* 聚焦状态 */
    .weather-card:focus-visible {
      outline: 3px solid rgba(255,255,255,0.8);
      outline-offset: 4px;
    }

    /* 入场动画 */
    .weather-card {
      opacity: 0;
      transform: translateY(40px);
    }

    .weather-card.animate-in {
      animation: cardEntrance 0.7s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
    }

    @keyframes cardEntrance {
      0% {
        opacity: 0;
        transform: translateY(40px) scale(0.95);
      }
      100% {
        opacity: 1;
        transform: translateY(0) scale(1);
      }
    }

    /* 卡片展开详情 */
    .card-detail {
      position: absolute;
      bottom: 0;
      left: 0;
      right: 0;
      background: linear-gradient(180deg, transparent 0%, rgba(0,0,0,0.4) 100%);
      padding: 60px 28px 20px;
      transform: translateY(100%);
      transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
      z-index: 15;
    }

    .weather-card:hover .card-detail {
      transform: translateY(0);
    }

    .detail-row {
      display: flex;
      justify-content: space-between;
      color: rgba(255,255,255,0.9);
      font-size: 14px;
    }

    .snowy-card .card-detail {
      background: linear-gradient(180deg, transparent 0%, rgba(0,0,0,0.15) 100%);
    }

    .snowy-card .detail-row {
      color: rgba(0,0,0,0.7);
    }

    /* 闪电效果 */
    .lightning {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background: rgba(255,255,255,0);
      pointer-events: none;
      z-index: 20;
    }

    .lightning.flash {
      animation: lightningFlash 0.15s ease-out;
    }

    @keyframes lightningFlash {
      0% { background: rgba(255,255,255,0); }
      50% { background: rgba(255,255,255,0.3); }
      100% { background: rgba(255,255,255,0); }
    }
  </style>
</head>
<body>
  <header class="header">
    <h1>天气</h1>
    <p>2024年12月21日 周六</p>
  </header>

  <main class="weather-container">
    <!-- 晴天卡片 -->
    <article class="weather-card sunny-card" tabindex="0" role="button" aria-label="北京 晴天 28度">
      <div class="weather-animation">
        <div class="sun"></div>
      </div>
      <div class="card-content">
        <div class="card-header">
          <div class="location">北京</div>
          <div class="weather-desc">晴朗</div>
        </div>
        <div class="temperature">28°</div>
        <div class="stats-row">
          <div class="stat-item">
            <span class="stat-label">最高</span>
            <span class="stat-value">32°</span>
          </div>
          <div class="stat-item">
            <span class="stat-label">最低</span>
            <span class="stat-value">22°</span>
          </div>
          <div class="stat-item">
            <span class="stat-label">体感</span>
            <span class="stat-value">30°</span>
          </div>
        </div>
      </div>
      <div class="card-detail">
        <div class="detail-row">
          <span>紫外线指数</span>
          <span>极高</span>
        </div>
        <div class="detail-row" style="margin-top: 8px;">
          <span>日落</span>
          <span>18:42</span>
        </div>
      </div>
    </article>

    <!-- 大风卡片 -->
    <article class="weather-card windy-card" tabindex="0" role="button" aria-label="上海 大风 15度">
      <div class="weather-animation">
        <div class="wind-line"></div>
        <div class="wind-line"></div>
        <div class="wind-line"></div>
        <div class="wind-line"></div>
        <div class="wind-line"></div>
        <div class="cloud cloud-1"></div>
      </div>
      <div class="card-content">
        <div class="card-header">
          <div class="location">上海</div>
          <div class="weather-desc">大风</div>
        </div>
        <div class="temperature">15°</div>
        <div class="stats-row">
          <div class="stat-item">
            <span class="stat-label">风速</span>
            <span class="stat-value">45km/h</span>
          </div>
          <div class="stat-item">
            <span class="stat-label">风向</span>
            <span class="stat-value">西北</span>
          </div>
          <div class="stat-item">
            <span class="stat-label">阵风</span>
            <span class="stat-value">60km/h</span>
          </div>
        </div>
      </div>
      <div class="card-detail">
        <div class="detail-row">
          <span>能见度</span>
          <span>良好</span>
        </div>
        <div class="detail-row" style="margin-top: 8px;">
          <span>气压</span>
          <span>1013 hPa</span>
        </div>
      </div>
    </article>

    <!-- 暴雨卡片 -->
    <article class="weather-card rainy-card" tabindex="0" role="button" aria-label="广州 暴雨 19度">
      <div class="weather-animation" id="rain-container">
        <div class="lightning"></div>
      </div>
      <div class="card-content">
        <div class="card-header">
          <div class="location">广州</div>
          <div class="weather-desc">暴雨</div>
        </div>
        <div class="temperature">19°</div>
        <div class="stats-row">
          <div class="stat-item">
            <span class="stat-label">降水</span>
            <span class="stat-value">85mm</span>
          </div>
          <div class="stat-item">
            <span class="stat-label">湿度</span>
            <span class="stat-value">95%</span>
          </div>
          <div class="stat-item">
            <span class="stat-label">能见度</span>
            <span class="stat-value">2km</span>
          </div>
        </div>
      </div>
      <div class="card-detail">
        <div class="detail-row">
          <span>降水概率</span>
          <span>100%</span>
        </div>
        <div class="detail-row" style="margin-top: 8px;">
          <span>持续至</span>
          <span>明日 14:00</span>
        </div>
      </div>
    </article>

    <!-- 暴雪卡片 -->
    <article class="weather-card snowy-card" tabindex="0" role="button" aria-label="哈尔滨 暴雪 零下12度">
      <div class="weather-animation" id="snow-container"></div>
      <div class="card-content">
        <div class="card-header">
          <div class="location">哈尔滨</div>
          <div class="weather-desc">暴雪</div>
        </div>
        <div class="temperature">-12°</div>
        <div class="stats-row">
          <div class="stat-item">
            <span class="stat-label">降雪</span>
            <span class="stat-value">25cm</span>
          </div>
          <div class="stat-item">
            <span class="stat-label">湿度</span>
            <span class="stat-value">88%</span>
          </div>
          <div class="stat-item">
            <span class="stat-label">能见度</span>
            <span class="stat-value">500m</span>
          </div>
        </div>
      </div>
      <div class="card-detail">
        <div class="detail-row">
          <span>体感温度</span>
          <span>-18°</span>
        </div>
        <div class="detail-row" style="margin-top: 8px;">
          <span>积雪深度</span>
          <span>45cm</span>
        </div>
      </div>
    </article>
  </main>

  <nav class="glass-nav" aria-label="天气卡片导航">
    <div class="nav-dot active" data-index="0"></div>
    <div class="nav-dot" data-index="1"></div>
    <div class="nav-dot" data-index="2"></div>
    <div class="nav-dot" data-index="3"></div>
  </nav>

  <script>
    // 初始化雨滴
    function createRaindrops() {
      const container = document.getElementById('rain-container');
      if (!container) return;
      
      for (let i = 0; i < 50; i++) {
        const drop = document.createElement('div');
        drop.className = 'raindrop';
        drop.style.left = Math.random() * 100 + '%';
        drop.style.height = (Math.random() * 20 + 15) + 'px';
        drop.style.animationDuration = (Math.random() * 0.5 + 0.4) + 's';
        drop.style.animationDelay = (Math.random() * 2) + 's';
        container.appendChild(drop);
      }
    }

    // 初始化雪花
    function createSnowflakes() {
      const container = document.getElementById('snow-container');
      if (!container) return;
      
      const snowSymbols = ['❄', '❅', '❆', '•'];
      
      for (let i = 0; i < 40; i++) {
        const flake = document.createElement('div');
        flake.className = 'snowflake';
        flake.textContent = snowSymbols[Math.floor(Math.random() * snowSymbols.length)];
        flake.style.left = Math.random() * 100 + '%';
        flake.style.fontSize = (Math.random() * 10 + 8) + 'px';
        flake.style.animationDuration = (Math.random() * 4 + 5) + 's';
        flake.style.animationDelay = (Math.random() * 5) + 's';
        container.appendChild(flake);
      }
    }

    // 闪电效果
    function triggerLightning() {
      const lightning = document.querySelector('.lightning');
      if (!lightning) return;
      
      const randomInterval = Math.random() * 5000 + 3000;
      
      setTimeout(() => {
        lightning.classList.add('flash');
        setTimeout(() => {
          lightning.classList.remove('flash');
        }, 150);
        triggerLightning();
      }, randomInterval);
    }

    // 入场动画
    function animateCards() {
      const cards = document.querySelectorAll('.weather-card');
      cards.forEach((card, index) => {
        setTimeout(() => {
          card.classList.add('animate-in');
        }, index * 150);
      });
    }

    // 导航点击
    function initNavigation() {
      const dots = document.querySelectorAll('.nav-dot');
      const cards = document.querySelectorAll('.weather-card');
      
      dots.forEach((dot, index) => {
        dot.addEventListener('click', () => {
          dots.forEach(d => d.classList.remove('active'));
          dot.classList.add('active');
          
          if (cards[index]) {
            cards[index].scrollIntoView({ 
              behavior: 'smooth', 
              block: 'center' 
            });
          }
        });
      });
    }

    // 卡片交互 - 点击效果
    function initCardInteractions() {
      const cards = document.querySelectorAll('.weather-card');
      
      cards.forEach(card => {
        card.addEventListener('click', () => {
          card.style.transform = 'translateY(-12px) scale(0.97)';
          setTimeout(() => {
            card.style.transform = '';
          }, 150);
        });

        // 键盘支持
        card.addEventListener('keydown', (e) => {
          if (e.key === 'Enter' || e.key === ' ') {
            e.preventDefault();
            card.click();
          }
        });
      });
    }

    // 视差效果
    function initParallax() {
      const cards = document.querySelectorAll('.weather-card');
      
      cards.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) / 25;
          const rotateY = (centerX - x) / 25;
          
          card.style.transform = `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) translateY(-12px) scale(1.02)`;
        });

        card.addEventListener('mouseleave', () => {
          card.style.transform = '';
        });
      });
    }

    // 检查 reduced motion
    function checkReducedMotion() {
      const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
      return prefersReducedMotion;
    }

    // 初始化
    document.addEventListener('DOMContentLoaded', () => {
      if (!checkReducedMotion()) {
        createRaindrops();
        createSnowflakes();
        triggerLightning();
        initParallax();
      }
      
      animateCards();
      initNavigation();
      initCardInteractions();
    });
  </script>
</body>
</html>
1 个赞

claude-opus-4-6-thinking:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>iOS 18 天气卡片</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;
  }

  body {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    background: #0a0a1a;
    overflow: hidden;
    padding: 20px;
  }

  /* 背景动态光效 */
  .bg-orb {
    position: fixed;
    border-radius: 50%;
    filter: blur(100px);
    opacity: 0.3;
    animation: orbFloat 20s ease-in-out infinite;
    pointer-events: none;
    z-index: 0;
  }

  .bg-orb:nth-child(1) {
    width: 600px; height: 600px;
    background: radial-gradient(circle, #ff6b3520, #ff2d5520);
    top: -200px; left: -100px;
    animation-delay: 0s;
  }

  .bg-orb:nth-child(2) {
    width: 500px; height: 500px;
    background: radial-gradient(circle, #4facfe20, #00f2fe20);
    bottom: -200px; right: -100px;
    animation-delay: -7s;
  }

  .bg-orb:nth-child(3) {
    width: 400px; height: 400px;
    background: radial-gradient(circle, #a18cd120, #fbc2eb20);
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    animation-delay: -14s;
  }

  @keyframes orbFloat {
    0%, 100% { transform: translate(0, 0) scale(1); }
    25% { transform: translate(50px, -30px) scale(1.1); }
    50% { transform: translate(-20px, 40px) scale(0.95); }
    75% { transform: translate(30px, 20px) scale(1.05); }
  }

  /* 页面标题 */
  .page-header {
    text-align: center;
    margin-bottom: 50px;
    z-index: 1;
    position: relative;
  }

  .page-header h1 {
    font-size: 42px;
    font-weight: 700;
    background: linear-gradient(135deg, #ffffff, #a0a0b0);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
    letter-spacing: -1px;
    margin-bottom: 8px;
  }

  .page-header p {
    color: rgba(255, 255, 255, 0.45);
    font-size: 16px;
    font-weight: 400;
    letter-spacing: 0.5px;
  }

  /* 卡片容器 */
  .cards-container {
    display: flex;
    gap: 24px;
    z-index: 1;
    position: relative;
    flex-wrap: wrap;
    justify-content: center;
  }

  /* 天气卡片基础样式 */
  .weather-card {
    width: 260px;
    height: 380px;
    border-radius: 28px;
    position: relative;
    overflow: hidden;
    cursor: pointer;
    transition: all 0.6s cubic-bezier(0.23, 1, 0.32, 1);
    transform-style: preserve-3d;
    perspective: 1000px;
  }

  .weather-card:hover {
    transform: translateY(-16px) scale(1.03);
    box-shadow: 0 30px 80px rgba(0, 0, 0, 0.5);
  }

  .weather-card:active {
    transform: translateY(-8px) scale(0.98);
    transition: all 0.15s ease;
  }

  /* 卡片背景层 */
  .card-bg {
    position: absolute;
    inset: 0;
    z-index: 0;
  }

  /* 玻璃拟态层 */
  .card-glass {
    position: absolute;
    inset: 0;
    background: rgba(255, 255, 255, 0.05);
    backdrop-filter: blur(40px);
    -webkit-backdrop-filter: blur(40px);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 28px;
    z-index: 1;
  }

  /* 高光效果 */
  .card-shine {
    position: absolute;
    inset: 0;
    border-radius: 28px;
    z-index: 5;
    background: linear-gradient(
      135deg,
      rgba(255, 255, 255, 0.1) 0%,
      transparent 50%,
      transparent 100%
    );
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.4s ease;
  }

  .weather-card:hover .card-shine {
    opacity: 1;
  }

  /* 动画层 */
  .animation-layer {
    position: absolute;
    inset: 0;
    z-index: 2;
    overflow: hidden;
    border-radius: 28px;
    pointer-events: none;
  }

  /* 内容层 */
  .card-content {
    position: relative;
    z-index: 3;
    padding: 28px 24px;
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    color: #fff;
  }

  .card-top {
    display: flex;
    flex-direction: column;
    gap: 4px;
  }

  .card-location {
    font-size: 18px;
    font-weight: 600;
    letter-spacing: -0.3px;
    opacity: 0.95;
  }

  .card-condition {
    font-size: 13px;
    font-weight: 400;
    opacity: 0.6;
    letter-spacing: 0.3px;
  }

  .card-icon-area {
    display: flex;
    justify-content: center;
    align-items: center;
    flex: 1;
  }

  .weather-emoji {
    font-size: 72px;
    filter: drop-shadow(0 8px 20px rgba(0,0,0,0.3));
    transition: transform 0.6s cubic-bezier(0.23, 1, 0.32, 1);
    animation: emojiFloat 4s ease-in-out infinite;
  }

  .weather-card:hover .weather-emoji {
    transform: scale(1.15);
  }

  @keyframes emojiFloat {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(-8px); }
  }

  .card-bottom {
    display: flex;
    flex-direction: column;
    gap: 14px;
  }

  .card-temp {
    font-size: 56px;
    font-weight: 200;
    letter-spacing: -3px;
    line-height: 1;
  }

  .card-temp span {
    font-size: 28px;
    font-weight: 300;
    opacity: 0.7;
    vertical-align: super;
    margin-left: 2px;
  }

  .card-details {
    display: flex;
    gap: 16px;
  }

  .detail-item {
    display: flex;
    flex-direction: column;
    gap: 2px;
  }

  .detail-label {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 1px;
    opacity: 0.45;
    font-weight: 500;
  }

  .detail-value {
    font-size: 14px;
    font-weight: 500;
    opacity: 0.85;
  }

  /* ===== 晴天卡片 ===== */
  .card-sunny .card-bg {
    background: linear-gradient(160deg, #ff9a56, #ff6b35, #e84520);
  }

  .card-sunny .card-glass {
    background: linear-gradient(160deg, rgba(255, 200, 100, 0.15), rgba(255, 100, 50, 0.05));
  }

  /* 太阳光线 */
  .sun-core {
    position: absolute;
    width: 100px;
    height: 100px;
    background: radial-gradient(circle, rgba(255, 230, 150, 0.6), rgba(255, 180, 50, 0.1), transparent);
    border-radius: 50%;
    top: 20%;
    right: 10%;
    animation: sunPulse 3s ease-in-out infinite;
  }

  @keyframes sunPulse {
    0%, 100% { transform: scale(1); opacity: 0.6; }
    50% { transform: scale(1.3); opacity: 0.9; }
  }

  .sun-ray {
    position: absolute;
    width: 2px;
    height: 180px;
    background: linear-gradient(to bottom, rgba(255, 230, 150, 0.4), transparent);
    top: -20px;
    right: 55px;
    transform-origin: bottom center;
    animation: rayRotate 12s linear infinite;
  }

  .sun-ray:nth-child(2) { animation-delay: -2s; opacity: 0.5; }
  .sun-ray:nth-child(3) { animation-delay: -4s; opacity: 0.3; }
  .sun-ray:nth-child(4) { animation-delay: -6s; opacity: 0.6; }
  .sun-ray:nth-child(5) { animation-delay: -8s; opacity: 0.4; }
  .sun-ray:nth-child(6) { animation-delay: -10s; opacity: 0.35; }

  @keyframes rayRotate {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
  }

  .heat-wave {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    height: 120px;
    background: linear-gradient(to top, rgba(255, 150, 50, 0.25), transparent);
    animation: heatShimmer 2s ease-in-out infinite;
  }

  @keyframes heatShimmer {
    0%, 100% { opacity: 0.3; transform: scaleY(1); }
    50% { opacity: 0.6; transform: scaleY(1.1); }
  }

  /* 漂浮光点 */
  .sun-particle {
    position: absolute;
    width: 4px;
    height: 4px;
    background: rgba(255, 230, 150, 0.8);
    border-radius: 50%;
    animation: sunParticleFloat 6s ease-in-out infinite;
  }

  @keyframes sunParticleFloat {
    0% { transform: translateY(100%) translateX(0) scale(0); opacity: 0; }
    20% { opacity: 1; transform: scale(1); }
    100% { transform: translateY(-400px) translateX(30px) scale(0); opacity: 0; }
  }

  /* ===== 大风卡片 ===== */
  .card-windy .card-bg {
    background: linear-gradient(160deg, #6dd5ed, #4facfe, #2196f3);
  }

  .card-windy .card-glass {
    background: linear-gradient(160deg, rgba(150, 220, 255, 0.15), rgba(79, 172, 254, 0.05));
  }

  .wind-line {
    position: absolute;
    height: 2px;
    border-radius: 2px;
    background: linear-gradient(to right, transparent, rgba(255, 255, 255, 0.5), transparent);
    animation: windBlow 2s ease-in-out infinite;
  }

  @keyframes windBlow {
    0% { transform: translateX(-100%); opacity: 0; }
    30% { opacity: 1; }
    100% { transform: translateX(300px); opacity: 0; }
  }

  .wind-leaf {
    position: absolute;
    font-size: 16px;
    animation: leafBlow 4s ease-in-out infinite;
    opacity: 0;
  }

  @keyframes leafBlow {
    0% {
      transform: translateX(-50px) translateY(0) rotate(0deg) scale(0.5);
      opacity: 0;
    }
    20% { opacity: 0.8; transform: translateX(20px) translateY(-20px) rotate(45deg) scale(1); }
    60% { opacity: 0.6; }
    100% {
      transform: translateX(320px) translateY(30px) rotate(720deg) scale(0.3);
      opacity: 0;
    }
  }

  .wind-swirl {
    position: absolute;
    border: 2px solid rgba(255, 255, 255, 0.15);
    border-radius: 50%;
    border-top-color: transparent;
    border-left-color: transparent;
    animation: swirlSpin 3s linear infinite;
  }

  @keyframes swirlSpin {
    0% { transform: rotate(0deg) scale(0.5); opacity: 0; }
    50% { opacity: 0.5; transform: rotate(180deg) scale(1); }
    100% { transform: rotate(360deg) scale(1.5); opacity: 0; }
  }

  /* ===== 暴雨卡片 ===== */
  .card-rain .card-bg {
    background: linear-gradient(160deg, #4a5568, #2d3748, #1a202c);
  }

  .card-rain .card-glass {
    background: linear-gradient(160deg, rgba(100, 120, 150, 0.15), rgba(50, 60, 80, 0.1));
  }

  .rain-drop {
    position: absolute;
    width: 2px;
    background: linear-gradient(to bottom, transparent, rgba(150, 200, 255, 0.7));
    border-radius: 0 0 2px 2px;
    animation: rainFall linear infinite;
  }

  @keyframes rainFall {
    0% { transform: translateY(-20px) translateX(0); opacity: 0; }
    10% { opacity: 1; }
    90% { opacity: 0.8; }
    100% { transform: translateY(400px) translateX(-15px); opacity: 0; }
  }

  .rain-splash {
    position: absolute;
    bottom: 40px;
    width: 6px;
    height: 3px;
    background: rgba(150, 200, 255, 0.4);
    border-radius: 50%;
    animation: splash 1.5s ease-out infinite;
  }

  @keyframes splash {
    0% { transform: scale(0); opacity: 1; }
    50% { transform: scale(3, 1); opacity: 0.5; }
    100% { transform: scale(5, 0.5); opacity: 0; }
  }

  .lightning {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(200, 220, 255, 0.15);
    border-radius: 28px;
    opacity: 0;
    animation: lightningFlash 6s ease-in-out infinite;
  }

  @keyframes lightningFlash {
    0%, 100% { opacity: 0; }
    42% { opacity: 0; }
    43% { opacity: 0.8; }
    44% { opacity: 0; }
    45% { opacity: 0.6; }
    46% { opacity: 0; }
  }

  .dark-cloud {
    position: absolute;
    background: rgba(30, 40, 60, 0.6);
    border-radius: 50%;
    filter: blur(10px);
    animation: cloudDrift 8s ease-in-out infinite;
  }

  @keyframes cloudDrift {
    0%, 100% { transform: translateX(0); }
    50% { transform: translateX(15px); }
  }

  /* ===== 暴雪卡片 ===== */
  .card-snow .card-bg {
    background: linear-gradient(160deg, #e8ecf1, #b8c6db, #8ea4c0);
  }

  .card-snow .card-glass {
    background: linear-gradient(160deg, rgba(255, 255, 255, 0.2), rgba(200, 210, 230, 0.08));
  }

  .card-snow .card-content {
    color: #2d3748;
  }

  .card-snow .detail-label {
    color: #4a5568;
  }

  .card-snow .detail-value {
    color: #2d3748;
  }

  .snowflake {
    position: absolute;
    color: rgba(255, 255, 255, 0.9);
    font-size: 14px;
    animation: snowFall linear infinite;
    text-shadow: 0 0 6px rgba(255, 255, 255, 0.5);
  }

  @keyframes snowFall {
    0% {
      transform: translateY(-20px) translateX(0) rotate(0deg);
      opacity: 0;
    }
    10% { opacity: 1; }
    90% { opacity: 0.8; }
    100% {
      transform: translateY(400px) translateX(-30px) rotate(360deg);
      opacity: 0;
    }
  }

  .frost-layer {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    height: 80px;
    background: linear-gradient(to top, rgba(255, 255, 255, 0.3), transparent);
    border-radius: 0 0 28px 28px;
    animation: frostGrow 4s ease-in-out infinite;
  }

  @keyframes frostGrow {
    0%, 100% { height: 80px; opacity: 0.4; }
    50% { height: 110px; opacity: 0.6; }
  }

  .ice-crystal {
    position: absolute;
    width: 40px;
    height: 40px;
    border: 1px solid rgba(255, 255, 255, 0.15);
    transform: rotate(45deg);
    animation: crystalFloat 5s ease-in-out infinite;
  }

  @keyframes crystalFloat {
    0%, 100% { transform: rotate(45deg) scale(1); opacity: 0.15; }
    50% { transform: rotate(45deg) scale(1.2); opacity: 0.3; }
  }

  /* 展开详情面板 */
  .card-expanded-info {
    position: absolute;
    inset: 0;
    z-index: 10;
    border-radius: 28px;
    background: rgba(0, 0, 0, 0.7);
    backdrop-filter: blur(30px);
    -webkit-backdrop-filter: blur(30px);
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 16px;
    padding: 30px;
    opacity: 0;
    pointer-events: none;
    transition: all 0.4s cubic-bezier(0.23, 1, 0.32, 1);
    transform: scale(0.95);
  }

  .card-expanded-info.visible {
    opacity: 1;
    pointer-events: auto;
    transform: scale(1);
  }

  .expanded-title {
    font-size: 20px;
    font-weight: 600;
    color: #fff;
    text-align: center;
  }

  .expanded-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
    width: 100%;
  }

  .expanded-item {
    background: rgba(255, 255, 255, 0.08);
    border-radius: 14px;
    padding: 12px;
    text-align: center;
    border: 1px solid rgba(255, 255, 255, 0.06);
  }

  .expanded-item-label {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.8px;
    color: rgba(255, 255, 255, 0.45);
    margin-bottom: 4px;
    font-weight: 500;
  }

  .expanded-item-value {
    font-size: 16px;
    font-weight: 600;
    color: #fff;
  }

  .close-hint {
    font-size: 11px;
    color: rgba(255, 255, 255, 0.35);
    margin-top: 8px;
    letter-spacing: 0.3px;
  }

  /* 底部提示 */
  .footer-hint {
    margin-top: 40px;
    color: rgba(255, 255, 255, 0.25);
    font-size: 13px;
    z-index: 1;
    position: relative;
    letter-spacing: 0.3px;
    animation: fadeInUp 1s ease 0.8s both;
  }

  @keyframes fadeInUp {
    from { opacity: 0; transform: translateY(20px); }
    to { opacity: 1; transform: translateY(0); }
  }

  /* 入场动画 */
  .weather-card {
    animation: cardEnter 0.8s cubic-bezier(0.23, 1, 0.32, 1) both;
  }

  .weather-card:nth-child(1) { animation-delay: 0.1s; }
  .weather-card:nth-child(2) { animation-delay: 0.2s; }
  .weather-card:nth-child(3) { animation-delay: 0.3s; }
  .weather-card:nth-child(4) { animation-delay: 0.4s; }

  @keyframes cardEnter {
    from {
      opacity: 0;
      transform: translateY(60px) scale(0.9);
    }
    to {
      opacity: 1;
      transform: translateY(0) scale(1);
    }
  }

  .page-header h1 {
    animation: titleEnter 1s cubic-bezier(0.23, 1, 0.32, 1) 0s both;
  }

  .page-header p {
    animation: titleEnter 1s cubic-bezier(0.23, 1, 0.32, 1) 0.15s both;
  }

  @keyframes titleEnter {
    from { opacity: 0; transform: translateY(30px); }
    to { opacity: 1; transform: translateY(0); }
  }

  /* 鼠标跟随光效 */
  .card-glow {
    position: absolute;
    width: 200px;
    height: 200px;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(255,255,255,0.15), transparent 70%);
    pointer-events: none;
    z-index: 4;
    opacity: 0;
    transition: opacity 0.3s ease;
    transform: translate(-50%, -50%);
  }

  .weather-card:hover .card-glow {
    opacity: 1;
  }

  /* 响应式 */
  @media (max-width: 1200px) {
    .cards-container {
      gap: 18px;
    }
    .weather-card {
      width: 230px;
      height: 340px;
    }
  }

  @media (max-width: 1000px) {
    .cards-container {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 18px;
    }
  }

  @media (max-width: 520px) {
    .cards-container {
      grid-template-columns: 1fr;
    }
    .weather-card {
      width: 280px;
    }
  }
</style>
</head>
<body>

<!-- 背景光效 -->
<div class="bg-orb"></div>
<div class="bg-orb"></div>
<div class="bg-orb"></div>

<!-- 页面标题 -->
<div class="page-header">
  <h1>天气</h1>
  <p>今日各地天气概览</p>
</div>

<!-- 卡片容器 -->
<div class="cards-container">

  <!-- ☀️ 晴天卡片 -->
  <div class="weather-card card-sunny" onclick="toggleExpand(this)" onmousemove="handleGlow(event, this)" onmouseleave="resetGlow(this)">
    <div class="card-bg"></div>
    <div class="card-glass"></div>
    <div class="animation-layer" id="sunny-anim">
      <div class="sun-core"></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="heat-wave"></div>
    </div>
    <div class="card-glow"></div>
    <div class="card-shine"></div>
    <div class="card-content">
      <div class="card-top">
        <div class="card-location">三亚</div>
        <div class="card-condition">晴朗 · 万里无云</div>
      </div>
      <div class="card-icon-area">
        <div class="weather-emoji">☀️</div>
      </div>
      <div class="card-bottom">
        <div class="card-temp">36<span>°</span></div>
        <div class="card-details">
          <div class="detail-item">
            <span class="detail-label">体感</span>
            <span class="detail-value">39°</span>
          </div>
          <div class="detail-item">
            <span class="detail-label">紫外线</span>
            <span class="detail-value">极强</span>
          </div>
          <div class="detail-item">
            <span class="detail-label">湿度</span>
            <span class="detail-value">45%</span>
          </div>
        </div>
      </div>
    </div>
    <div class="card-expanded-info" data-info='{"uv":"11 极强","sunrise":"06:12","sunset":"19:35","aqi":"32 优","visibility":"25km","pressure":"1013hPa"}'>
      <div class="expanded-title">☀️ 三亚 · 详细信息</div>
      <div class="expanded-grid">
        <div class="expanded-item">
          <div class="expanded-item-label">紫外线指数</div>
          <div class="expanded-item-value">11 极强</div>
        </div>
        <div class="expanded-item">
          <div class="expanded-item-label">日出</div>
          <div class="expanded-item-value">06:12</div>
        </div>
        <div class="expanded-item">
          <div class="expanded-item-label">日落</div>
          <div class="expanded-item-value">19:35</div>
        </div>
        <div class="expanded-item">
          <div class="expanded-item-label">空气质量</div>
          <div class="expanded-item-value">32 优</div>
        </div>
        <div class="expanded-item">
          <div class="expanded-item-label">能见度</div>
          <div class="expanded-item-value">25 km</div>
        </div>
        <div class="expanded-item">
          <div class="expanded-item-label">气压</div>
          <div class="expanded-item-value">1013 hPa</div>
        </div>
      </div>
      <div class="close-hint">点击任意处关闭</div>
    </div>
  </div>

  <!-- 💨 大风卡片 -->
  <div class="weather-card card-windy" onclick="toggleExpand(this)" onmousemove="handleGlow(event, this)" onmouseleave="resetGlow(this)">
    <div class="card-bg"></div>
    <div class="card-glass"></div>
    <div class="animation-layer" id="windy-anim"></div>
    <div class="card-glow"></div>
    <div class="card-shine"></div>
    <div class="card-content">
      <div class="card-top">
        <div class="card-location">呼和浩特</div>
        <div class="card-condition">大风 · 阵风7级</div>
      </div>
      <div class="card-icon-area">
        <div class="weather-emoji">💨</div>
      </div>
      <div class="card-bottom">
        <div class="card-temp">12<span>°</span></div>
        <div class="card-details">
          <div class="detail-item">
            <span class="detail-label">风速</span>
            <span class="detail-value">52km/h</span>
          </div>
          <div class="detail-item">
            <span class="detail-label">风向</span>
            <span class="detail-value">西北</span>
          </div>
          <div class="detail-item">
            <span class="detail-label">湿度</span>
            <span class="detail-value">28%</span>
          </div>
        </div>
      </div>
    </div>
    <div class="card-expanded-info">
      <div class="expanded-title">💨 呼和浩特 · 详细信息</div>
      <div class="expanded-grid">
        <div class="expanded-item">
          <div class="expanded-item-label">风速</div>
          <div class="expanded-item-value">52 km/h</div>
        </div>
        <div class="expanded-item">
          <div class="expanded-item-label">阵风</div>
          <div class="expanded-item-value">7 级</div>
        </div>
        <div class="expanded-item">
          <div class="expanded-item-label">风向</div>
          <div class="expanded-item-value">西北风</div>
        </div>
        <div class="expanded-item">
          <div class="expanded-item-label">空气质量</div>
          <div class="expanded-item-value">158 中</div>
        </div>
        <div class="expanded-item">
          <div class="expanded-item-label">能见度</div>
          <div class="expanded-item-value">8 km</div>
        </div>
        <div class="expanded-item">
          <div class="expanded-item-label">气压</div>
          <div class="expanded-item-value">1025 hPa</div>
        </div>
      </div>
      <div class="close-hint">点击任意处关闭</div>
    </div>
  </div>

  <!-- 🌧️ 暴雨卡片 -->
  <div class="weather-card card-rain" onclick="toggleExpand(this)" onmousemove="handleGlow(event, this)" onmouseleave="resetGlow(this)">
    <div class="card-bg"></div>
    <div class="card-glass"></div>
    <div class="animation-layer" id="rain-anim">
      <div class="lightning"></div>
      <div class="dark-cloud" style="width:140px;height:50px;top:15px;left:-20px;"></div>
      <div class="dark-cloud" style="width:120px;height:40px;top:25px;right:-10px;animation-delay:-3s;"></div>
    </div>
    <div class="card-glow"></div>
    <div class="card-shine"></div>
    <div class="card-content">
      <div class="card-top">
        <div class="card-location">深圳</div>
        <div class="card-condition">暴雨 · 雷电预警</div>
      </div>
      <div class="card-icon-area">
        <div class="weather-emoji">⛈️</div>
      </div>
      <div class="card-bottom">
        <div class="card-temp">24<span>°</span></div>
        <div class="card-details">
          <div class="detail-item">
            <span class="detail-label">降水量</span>
            <span class="detail-value">82mm</span>
          </div>
          <div class="detail-item">
            <span class="detail-label">湿度</span>
            <span class="detail-value">96%</span>
          </div>
          <div class="detail-item">
            <span class="detail-label">能见度</span>
            <span class="detail-value">2km</span>
          </div>
        </div>
      </div>
    </div>
    <div class="card-expanded-info">
      <div class="expanded-title">⛈️ 深圳 · 详细信息</div>
      <div class="expanded-grid">
        <div class="expanded-item">
          <div class="expanded-item-label">降水量</div>
          <div class="expanded-item-value">82 mm</div>
        </div>
        <div class="expanded-item">
          <div class="expanded-item-label">降水概率</div>
          <div class="expanded-item-value">100%</div>
        </div>
        <div class="expanded-item">
          <div class="expanded-item-label">雷电预警</div>
          <div class="expanded-item-value">橙色</div>
        </div>
        <div class="expanded-item">
          <div class="expanded-item-label">空气质量</div>
          <div class="expanded-item-value">52 良</div>
        </div>
        <div class="expanded-item">
          <div class="expanded-item-label">能见度</div>
          <div class="expanded-item-value">2 km</div>
        </div>
        <div class="expanded-item">
          <div class="expanded-item-label">气压</div>
          <div class="expanded-item-value">998 hPa</div>
        </div>
      </div>
      <div class="close-hint">点击任意处关闭</div>
    </div>
  </div>

  <!-- ❄️ 暴雪卡片 -->
  <div class="weather-card card-snow" onclick="toggleExpand(this)" onmousemove="handleGlow(event, this)" onmouseleave="resetGlow(this)">
    <div class="card-bg"></div>
    <div class="card-glass"></div>
    <div class="animation-layer" id="snow-anim">
      <div class="frost-layer"></div>
    </div>
    <div class="card-glow"></div>
    <div class="card-shine"></div>
    <div class="card-content">
      <div class="card-top">
        <div class="card-location">哈尔滨</div>
        <div class="card-condition">暴雪 · 道路结冰</div>
      </div>
      <div class="card-icon-area">
        <div class="weather-emoji">🌨️</div>
      </div>
      <div class="card-bottom">
        <div class="card-temp">-18<span>°</span></div>
        <div class="card-details">
          <div class="detail-item">
            <span class="detail-label">降雪量</span>
            <span class="detail-value">15mm</span>
          </div>
          <div class="detail-item">
            <span class="detail-label">体感</span>
            <span class="detail-value">-27°</span>
          </div>
          <div class="detail-item">
            <span class="detail-label">湿度</span>
            <span class="detail-value">85%</span>
          </div>
        </div>
      </div>
    </div>
    <div class="card-expanded-info">
      <div class="expanded-title">🌨️ 哈尔滨 · 详细信息</div>
      <div class="expanded-grid">
        <div class="expanded-item">
          <div class="expanded-item-label">降雪量</div>
          <div class="expanded-item-value">15 mm</div>
        </div>
        <div class="expanded-item">
          <div class="expanded-item-label">积雪深度</div>
          <div class="expanded-item-value">32 cm</div>
        </div>
        <div class="expanded-item">
          <div class="expanded-item-label">道路状况</div>
          <div class="expanded-item-value">结冰</div>
        </div>
        <div class="expanded-item">
          <div class="expanded-item-label">空气质量</div>
          <div class="expanded-item-value">28 优</div>
        </div>
        <div class="expanded-item">
          <div class="expanded-item-label">能见度</div>
          <div class="expanded-item-value">1 km</div>
        </div>
        <div class="expanded-item">
          <div class="expanded-item-label">气压</div>
          <div class="expanded-item-value">1032 hPa</div>
        </div>
      </div>
      <div class="close-hint">点击任意处关闭</div>
    </div>
  </div>

</div>

<div class="footer-hint">点击卡片查看详情 · 鼠标悬停体验交互动效</div>

<script>
  // ===== 动态生成天气动画粒子 =====

  // 晴天 - 浮动光粒子
  function createSunParticles() {
    const container = document.getElementById('sunny-anim');
    for (let i = 0; i < 8; i++) {
      const particle = document.createElement('div');
      particle.className = 'sun-particle';
      particle.style.left = Math.random() * 100 + '%';
      particle.style.bottom = '0';
      particle.style.animationDuration = (4 + Math.random() * 4) + 's';
      particle.style.animationDelay = (Math.random() * 5) + 's';
      particle.style.width = (2 + Math.random() * 4) + 'px';
      particle.style.height = particle.style.width;
      container.appendChild(particle);
    }
  }

  // 大风 - 风线 + 树叶
  function createWindElements() {
    const container = document.getElementById('windy-anim');

    // 风线
    for (let i = 0; i < 12; i++) {
      const line = document.createElement('div');
      line.className = 'wind-line';
      line.style.top = (Math.random() * 100) + '%';
      line.style.left = '-80px';
      line.style.width = (60 + Math.random() * 100) + 'px';
      line.style.animationDuration = (1 + Math.random() * 1.5) + 's';
      line.style.animationDelay = (Math.random() * 3) + 's';
      line.style.opacity = 0.2 + Math.random() * 0.4;
      container.appendChild(line);
    }

    // 树叶
    const leaves = ['🍃', '🍂', '🍁'];
    for (let i = 0; i < 5; i++) {
      const leaf = document.createElement('div');
      leaf.className = 'wind-leaf';
      leaf.textContent = leaves[Math.floor(Math.random() * leaves.length)];
      leaf.style.top = (20 + Math.random() * 60) + '%';
      leaf.style.left = '-30px';
      leaf.style.animationDuration = (3 + Math.random() * 3) + 's';
      leaf.style.animationDelay = (Math.random() * 5) + 's';
      leaf.style.fontSize = (12 + Math.random() * 10) + 'px';
      container.appendChild(leaf);
    }

    // 漩涡
    for (let i = 0; i < 3; i++) {
      const swirl = document.createElement('div');
      swirl.className = 'wind-swirl';
      const size = 30 + Math.random() * 50;
      swirl.style.width = size + 'px';
      swirl.style.height = size + 'px';
      swirl.style.top = (Math.random() * 80) + '%';
      swirl.style.left = (Math.random() * 80) + '%';
      swirl.style.animationDuration = (2 + Math.random() * 3) + 's';
      swirl.style.animationDelay = (Math.random() * 3) + 's';
      container.appendChild(swirl);
    }
  }

  // 暴雨 - 雨滴 + 溅射
  function createRainDrops() {
    const container = document.getElementById('rain-anim');

    for (let i = 0; i < 50; i++) {
      const drop = document.createElement('div');
      drop.className = 'rain-drop';
      drop.style.left = (Math.random() * 110 - 5) + '%';
      drop.style.top = '-20px';
      drop.style.height = (15 + Math.random() * 25) + 'px';
      drop.style.animationDuration = (0.4 + Math.random() * 0.4) + 's';
      drop.style.animationDelay = (Math.random() * 2) + 's';
      drop.style.opacity = 0.3 + Math.random() * 0.5;
      container.appendChild(drop);
    }

    // 溅射
    for (let i = 0; i < 10; i++) {
      const splash = document.createElement('div');
      splash.className = 'rain-splash';
      splash.style.left = (Math.random() * 90 + 5) + '%';
      splash.style.animationDuration = (1 + Math.random() * 1) + 's';
      splash.style.animationDelay = (Math.random() * 2) + 's';
      container.appendChild(splash);
    }
  }

  // 暴雪 - 雪花 + 冰晶
  function createSnowflakes() {
    const container = document.getElementById('snow-anim');
    const flakeChars = ['❄', '❅', '❆', '✦', '•'];

    for (let i = 0; i < 40; i++) {
      const flake = document.createElement('div');
      flake.className = 'snowflake';
      flake.textContent = flakeChars[Math.floor(Math.random() * flakeChars.length)];
      flake.style.left = (Math.random() * 110 - 5) + '%';
      flake.style.top = '-20px';
      flake.style.fontSize = (8 + Math.random() * 14) + 'px';
      flake.style.animationDuration = (3 + Math.random() * 5) + 's';
      flake.style.animationDelay = (Math.random() * 6) + 's';
      flake.style.opacity = 0.4 + Math.random() * 0.5;
      container.appendChild(flake);
    }

    // 冰晶
    for (let i = 0; i < 4; i++) {
      const crystal = document.createElement('div');
      crystal.className = 'ice-crystal';
      crystal.style.top = (Math.random() * 70 + 10) + '%';
      crystal.style.left = (Math.random() * 70 + 10) + '%';
      const size = 20 + Math.random() * 30;
      crystal.style.width = size + 'px';
      crystal.style.height = size + 'px';
      crystal.style.animationDelay = (Math.random() * 5) + 's';
      container.appendChild(crystal);
    }
  }

  // 初始化所有粒子
  createSunParticles();
  createWindElements();
  createRainDrops();
  createSnowflakes();

  // ===== 交互功能 =====

  // 点击展开详情
  function toggleExpand(card) {
    const info = card.querySelector('.card-expanded-info');
    if (info.classList.contains('visible')) {
      info.classList.remove('visible');
    } else {
      // 关闭其他卡片
      document.querySelectorAll('.card-expanded-info.visible').forEach(el => {
        el.classList.remove('visible');
      });
      info.classList.add('visible');
    }
  }

  // 鼠标跟随光效
  function handleGlow(e, card) {
    const rect = card.getBoundingClientRect();
    const x = e.clientX - rect.left;
    const y = e.clientY - rect.top;
    const glow = card.querySelector('.card-glow');
    glow.style.left = x + 'px';
    glow.style.top = y + 'px';

    // 3D 倾斜效果
    const centerX = rect.width / 2;
    const centerY = rect.height / 2;
    const rotateX = ((y - centerY) / centerY) * -6;
    const rotateY = ((x - centerX) / centerX) * 6;

    card.style.transform = `translateY(-16px) scale(1.03) perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`;
  }

  function resetGlow(card) {
    card.style.transform = '';
    const glow = card.querySelector('.card-glow');
    glow.style.opacity = '0';
  }

  // 随机闪电时间调整
  function randomizeLightning() {
    const lightning = document.querySelector('.lightning');
    if (lightning) {
      setInterval(() => {
        lightning.style.animationDuration = (4 + Math.random() * 6) + 's';
      }, 8000);
    }
  }
  randomizeLightning();
</script>

</body>
</html>
1 个赞

M2.5和Opus很像呢 :laughing:

GLM这个好看

这是蒸馏了吧,这么像


也是用佬友提供的提示词去测试了一下,但是我自己改成了
以 iOS 26 (液态玻璃) 的设计风格
感觉效果也还挺好的,不过我这个是网页(免费账号),没有用api。

1 个赞

确实啊
感觉有点opus风格

gemini-3-pro:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>iOS 18 Weather Cards</title>
    <style>
        :root {
            --card-width: 300px;
            --card-height: 500px;
            --radius: 36px;
            --font-stack: -apple-system, BlinkMacSystemFont, "San Francisco", "Helvetica Neue", sans-serif;
        }

        body {
            margin: 0;
            padding: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            background-color: #000;
            font-family: var(--font-stack);
            color: white;
            overflow-x: auto;
        }

        /* 容器:横向排列 */
        .weather-container {
            display: flex;
            gap: 24px;
            padding: 40px;
            perspective: 1000px; /* 为3D效果做准备 */
        }

        /* 卡片基础样式 */
        .card {
            width: var(--card-width);
            height: var(--card-height);
            border-radius: var(--radius);
            position: relative;
            overflow: hidden;
            cursor: pointer;
            transition: transform 0.4s cubic-bezier(0.25, 0.8, 0.25, 1), box-shadow 0.4s ease;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
            /* 保持文字在最上层 */
            display: flex;
            flex-direction: column;
            justify-content: space-between;
            padding: 30px;
            box-sizing: border-box;
            transform-style: preserve-3d;
        }

        .card:hover {
            box-shadow: 0 20px 50px rgba(0, 0, 0, 0.6);
            z-index: 10;
        }

        /* 文字内容层 */
        .card-content {
            z-index: 2;
            transform: translateZ(30px); /* 视差深度 */
            text-shadow: 0 2px 10px rgba(0,0,0,0.1);
        }

        .location {
            font-size: 24px;
            font-weight: 600;
            margin-bottom: 4px;
            display: block;
        }

        .condition {
            font-size: 16px;
            font-weight: 500;
            opacity: 0.9;
        }

        .temp-section {
            display: flex;
            flex-direction: column;
            align-items: flex-start;
        }

        .temperature {
            font-size: 84px;
            font-weight: 200;
            line-height: 1;
            letter-spacing: -2px;
        }

        .range {
            font-size: 18px;
            opacity: 0.8;
            margin-top: 8px;
            font-weight: 500;
        }

        /* --- 天气特定样式 --- */

        /* 1. 晴天 (Sunny) */
        .card.sunny {
            background: linear-gradient(160deg, #54aaff 0%, #2980b9 40%, #f39c12 100%);
        }
        
        .sun {
            position: absolute;
            top: -50px;
            right: -50px;
            width: 200px;
            height: 200px;
            background: radial-gradient(circle, #ffeaa7 20%, rgba(255, 200, 0, 0.6) 50%, transparent 80%);
            border-radius: 50%;
            filter: blur(10px);
            animation: sunPulse 6s infinite alternate;
            z-index: 1;
        }

        @keyframes sunPulse {
            0% { transform: scale(1); opacity: 0.8; }
            100% { transform: scale(1.2); opacity: 1; }
        }

        /* 2. 大风 (Windy) */
        .card.windy {
            background: linear-gradient(160deg, #6dd5ed 0%, #2193b0 100%);
        }

        .cloud {
            position: absolute;
            background: rgba(255, 255, 255, 0.3);
            border-radius: 50px;
            filter: blur(8px);
            z-index: 1;
            animation: windMove linear infinite;
        }
        /* 云朵形状组合 */
        .cloud::after {
            content: '';
            position: absolute;
            width: 60%;
            height: 120%;
            background: inherit;
            top: -40%;
            left: 20%;
            border-radius: 50%;
        }

        @keyframes windMove {
            0% { transform: translateX(-150%) skewX(-20deg); opacity: 0; }
            10% { opacity: 0.6; }
            90% { opacity: 0.6; }
            100% { transform: translateX(400%) skewX(-20deg); opacity: 0; }
        }

        /* 3. 暴雨 (Rain) */
        .card.rain {
            background: linear-gradient(180deg, #203a43 0%, #2c5364 100%);
        }

        .rain-drop {
            position: absolute;
            background: rgba(255, 255, 255, 0.4);
            width: 2px;
            height: 20px;
            top: -50px;
            z-index: 1;
            transform: rotate(15deg); /* 雨是斜的 */
            animation: rainFall linear infinite;
        }

        @keyframes rainFall {
            0% { transform: translateY(0) rotate(15deg); opacity: 0; }
            10% { opacity: 1; }
            90% { opacity: 1; }
            100% { transform: translateY(600px) rotate(15deg); opacity: 0; }
        }

        /* 4. 暴雪 (Snow) */
        .card.snow {
            background: linear-gradient(180deg, #83a4d4 0%, #b6fbff 100%);
        }

        .snowflake {
            position: absolute;
            background: white;
            border-radius: 50%;
            top: -20px;
            z-index: 1;
            filter: blur(1px);
            animation: snowFall linear infinite;
        }

        @keyframes snowFall {
            0% { transform: translateY(0) translateX(0); opacity: 0; }
            10% { opacity: 0.8; }
            100% { transform: translateY(600px) translateX(20px); opacity: 0; }
        }

    </style>
</head>
<body>

    <div class="weather-container">
        
        <!-- 晴天卡片 -->
        <div class="card sunny" data-tilt>
            <div class="sun"></div>
            <div class="card-content">
                <div>
                    <span class="location">库比蒂诺</span>
                    <span class="condition">晴朗</span>
                </div>
            </div>
            <div class="card-content temp-section">
                <span class="temperature">28°</span>
                <span class="range">最高: 31° 最低: 18°</span>
            </div>
        </div>

        <!-- 大风卡片 -->
        <div class="card windy" id="card-windy" data-tilt>
            <!-- 云朵由JS生成或CSS静态写,这里混合 -->
            <div class="card-content">
                <div>
                    <span class="location">旧金山</span>
                    <span class="condition">大风</span>
                </div>
            </div>
            <div class="card-content temp-section">
                <span class="temperature">16°</span>
                <span class="range">风速: 45 km/h</span>
            </div>
        </div>

        <!-- 暴雨卡片 -->
        <div class="card rain" id="card-rain" data-tilt>
            <!-- 雨滴由JS生成 -->
            <div class="card-content">
                <div>
                    <span class="location">伦敦</span>
                    <span class="condition">暴雨</span>
                </div>
            </div>
            <div class="card-content temp-section">
                <span class="temperature">11°</span>
                <span class="range">降水: 100%</span>
            </div>
        </div>

        <!-- 暴雪卡片 -->
        <div class="card snow" id="card-snow" data-tilt>
            <!-- 雪花由JS生成 -->
            <div class="card-content">
                <div>
                    <span class="location">札幌</span>
                    <span class="condition">大暴雪</span>
                </div>
            </div>
            <div class="card-content temp-section">
                <span class="temperature">-8°</span>
                <span class="range">积雪: 15 cm</span>
            </div>
        </div>

    </div>

    <script>
        // 1. 初始化天气动画粒子
        document.addEventListener('DOMContentLoaded', () => {
            initWind();
            initRain();
            initSnow();
            initTiltEffect();
        });

        function initWind() {
            const container = document.getElementById('card-windy');
            // 生成3个不同大小和速度的云
            for(let i=0; i<4; i++) {
                const cloud = document.createElement('div');
                cloud.classList.add('cloud');
                
                // 随机尺寸和位置
                const width = 100 + Math.random() * 150;
                cloud.style.width = width + 'px';
                cloud.style.height = (width * 0.4) + 'px';
                cloud.style.top = (10 + Math.random() * 60) + '%';
                cloud.style.left = '-150px';
                
                // 随机动画时长
                const duration = 2 + Math.random() * 3;
                cloud.style.animationDuration = duration + 's';
                cloud.style.animationDelay = (Math.random() * 2) + 's';

                container.appendChild(cloud);
            }
        }

        function initRain() {
            const container = document.getElementById('card-rain');
            const dropCount = 60; // 雨滴数量

            for(let i=0; i<dropCount; i++) {
                const drop = document.createElement('div');
                drop.classList.add('rain-drop');
                
                // 随机位置
                drop.style.left = Math.random() * 100 + '%';
                // 随机动画时长 (制造层次感)
                const duration = 0.6 + Math.random() * 0.4;
                drop.style.animationDuration = duration + 's';
                // 随机延迟
                drop.style.animationDelay = Math.random() * 2 + 's';

                container.appendChild(drop);
            }
        }

        function initSnow() {
            const container = document.getElementById('card-snow');
            const flakeCount = 50;

            for(let i=0; i<flakeCount; i++) {
                const flake = document.createElement('div');
                flake.classList.add('snowflake');
                
                // 随机大小
                const size = 3 + Math.random() * 5;
                flake.style.width = size + 'px';
                flake.style.height = size + 'px';
                
                flake.style.left = Math.random() * 100 + '%';
                
                const duration = 2 + Math.random() * 4;
                flake.style.animationDuration = duration + 's';
                flake.style.animationDelay = Math.random() * 5 + 's';
                
                // 增加一点透明度变化
                flake.style.opacity = 0.5 + Math.random() * 0.5;

                container.appendChild(flake);
            }
        }

        // 2. 实现 iOS 风格的 3D 视差倾斜效果 (Mouse Tilt)
        function initTiltEffect() {
            const cards = document.querySelectorAll('.card');

            cards.forEach(card => {
                card.addEventListener('mousemove', (e) => {
                    const rect = card.getBoundingClientRect();
                    const x = e.clientX - rect.left;
                    const y = e.clientY - rect.top;

                    // 计算鼠标位置相对于卡片中心的百分比 (-1 到 1)
                    const xPct = (x / rect.width - 0.5) * 2;
                    const yPct = (y / rect.height - 0.5) * 2;

                    // 限制最大旋转角度
                    const rotateX = yPct * -10; // 鼠标下移,X轴向上转
                    const rotateY = xPct * 10;  // 鼠标右移,Y轴向右转

                    card.style.transform = `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) scale(1.02)`;
                });

                // 鼠标移出时复原
                card.addEventListener('mouseleave', () => {
                    card.style.transform = `perspective(1000px) rotateX(0) rotateY(0) scale(1)`;
                });
            });
        }
    </script>
</body>
</html>
2 个赞

图标可以