发帖
 找回密码
 立即注册
搜索
0 1 0
日常闲聊 294 0 4 小时前

用lm arena测了天气卡片,感觉前端提升很大

ec61c113732c7830b731927872448368645c9c97.jpeg

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

html代码

<!doctype html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>iOS 18 风格 - 天气卡片</title>
  <style>
    /* ======= 基础设定 / iOS 18 风格基因 ======= */
    :root{
      --radius: 22px;
      --glass: rgba(255,255,255,0.12);
      --glass-strong: rgba(255,255,255,0.18);
      --glass-border: rgba(255,255,255,0.35);
      --text: rgba(255,255,255,0.92);
      --subtext: rgba(255,255,255,0.72);
      --shadow: 0 10px 30px rgba(0,0,0,0.25), inset 0 0 0 1px rgba(255,255,255,0.08);

      /* 动态背景色带(跟随时间缓慢变色) */
      --bg-1: #131a2a;
      --bg-2: #0b1220;
      --bg-3: #1c2a4a;

      /* 主题色(不同卡片) */
      --sunny-1: #FFB82B; --sunny-2: #FF7A00; --sunny-3: #FF5E62;
      --windy-1: #46E4D4; --windy-2: #3399FF; --windy-3: #5F7FFF;
      --rain-1: #0EA5E9;  --rain-2: #2563EB;  --rain-3: #1E3A8A;
      --snow-1: #8ED1FF;  --snow-2: #6EC3FF;  --snow-3: #9AA9FF;
    }

    @media (prefers-color-scheme: light){
      :root{
        --text: rgba(14,14,16,0.95);
        --subtext: rgba(14,14,16,0.65);
        --glass: rgba(255,255,255,0.7);
        --glass-strong: rgba(255,255,255,0.9);
        --glass-border: rgba(0,0,0,0.08);
        --shadow: 0 10px 30px rgba(0,0,0,0.12), inset 0 0 0 1px rgba(0,0,0,0.06);
        --bg-1: #E9F0FF; --bg-2: #EFF6FF; --bg-3: #E8ECFF;
      }
    }

    *{ box-sizing: border-box; }
    html, body { height: 100%; }
    body{
      margin: 0;
      font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "SF Pro Display", "Helvetica Neue", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft Yahei", sans-serif;
      color: var(--text);
      background: radial-gradient(1200px 800px at 20% 10%, var(--bg-3), transparent 60%),
                  radial-gradient(1200px 800px at 80% 90%, var(--bg-1), transparent 60%),
                  radial-gradient(1200px 800px at 50% 50%, var(--bg-2), transparent 60%),
                  linear-gradient(180deg, #0b0f1a, #0b0f1a);
      background-attachment: fixed;
      overflow: hidden;
    }

    /* 背景缓慢变色 */
    @keyframes bgShift {
      0%   { filter: hue-rotate(0deg) saturate(1); }
      50%  { filter: hue-rotate(10deg) saturate(1.1); }
      100% { filter: hue-rotate(0deg) saturate(1); }
    }
    body::before{
      content:"";
      position: fixed; inset: -20vh -20vw;
      background: radial-gradient(60% 80% at 30% 10%, rgba(255,255,255,0.06), transparent 60%),
                  radial-gradient(60% 80% at 70% 90%, rgba(255,255,255,0.06), transparent 60%);
      pointer-events: none;
      animation: bgShift 16s ease-in-out infinite;
    }

    /* ======= 顶部栏 ======= */
    .topbar{
      position: fixed; inset: 14px 14px auto 14px;
      height: 56px;
      display: flex; align-items: center; justify-content: space-between;
      padding: 0 12px;
      border-radius: 18px;
      background: var(--glass);
      -webkit-backdrop-filter: blur(12px) saturate(1.2);
      backdrop-filter: blur(12px) saturate(1.2);
      box-shadow: var(--shadow);
      z-index: 10;
    }
    .title{
      display: flex; align-items: center; gap: 10px; padding-left: 4px;
      letter-spacing: 0.2px; font-weight: 600;
    }
    .title .dot{
      width: 10px; height: 10px; border-radius: 50%;
      background: linear-gradient(135deg, #26d07c, #2dd4bf);
      box-shadow: 0 0 0 4px rgba(45,212,191,0.15);
    }

    /* iOS 分段控制器(℃/℉ 切换) */
    .segment{
      position: relative; display: inline-flex; padding: 4px;
      gap: 4px; border-radius: 14px;
      background: rgba(255,255,255,0.06);
      -webkit-backdrop-filter: blur(8px);
      backdrop-filter: blur(8px);
      border: 1px solid var(--glass-border);
    }
    .seg-btn{
      border: 0; outline: 0; user-select: none; cursor: pointer;
      padding: 6px 12px; min-width: 44px; height: 32px; border-radius: 10px;
      color: var(--subtext); background: transparent; font-weight: 600;
      transition: color .2s ease, background .2s ease, transform .2s cubic-bezier(.2,.8,.2,1);
    }
    .seg-btn.active{
      color: var(--text);
      background: var(--glass-strong);
      box-shadow: inset 0 0 0 1px var(--glass-border), 0 6px 20px rgba(0,0,0,0.12);
      transform: translateZ(0);
    }

    /* ======= 横向卡片容器 ======= */
    .wrap{
      position: absolute; inset: 0;
      padding: 92px 24px 24px;
      display: grid; grid-template-rows: 1fr auto;
      gap: 18px;
    }
    .hint{
      color: var(--subtext); font-size: 13px; letter-spacing: .2px;
      display: flex; align-items: center; gap: 8px;
    }
    .hint .kbd{
      padding: 2px 6px; border-radius: 6px; border: 1px solid var(--glass-border);
      background: rgba(255,255,255,0.08);
      -webkit-backdrop-filter: blur(6px);
      backdrop-filter: blur(6px);
      font-weight: 600; font-size: 12px; color: var(--text);
    }

    .carousel{
      display: grid; grid-auto-flow: column;
      grid-auto-columns: minmax(290px, 360px);
      gap: 16px; overflow-x: auto; overflow-y: visible; padding-bottom: 10px;
      scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch;
    }
    .carousel::-webkit-scrollbar{ height: 8px; }
    .carousel::-webkit-scrollbar-thumb{
      background: rgba(255,255,255,0.15); border-radius: 8px;
    }
    .carousel > *{ scroll-snap-align: center; }

    /* ======= 卡片通用 ======= */
    .card{
      position: relative; min-height: 240px;
      border-radius: var(--radius);
      background: var(--glass);
      -webkit-backdrop-filter: blur(18px) saturate(1.2);
      backdrop-filter: blur(18px) saturate(1.2);
      box-shadow: var(--shadow);
      overflow: hidden; isolation: isolate;
      transform-style: preserve-3d;
      transform: perspective(1000px) rotateX(var(--tiltX,0deg)) rotateY(var(--tiltY,0deg));
      transition: transform .3s cubic-bezier(.2,.8,.2,1), box-shadow .3s ease;
      cursor: pointer;
    }
    .card:active{ transform: perspective(1000px) scale(.985) rotateX(var(--tiltX,0deg)) rotateY(var(--tiltY,0deg)); }
    .card .chrome{
      position: absolute; inset: 0; pointer-events: none;
      background: radial-gradient(120% 120% at -10% -10%, rgba(255,255,255,.18), transparent 40%),
                  radial-gradient(120% 120% at 110% 110%, rgba(255,255,255,.16), transparent 40%);
      mix-blend-mode: soft-light;
      opacity: .8;
    }
    .card .tint{
      position: absolute; inset: 0; z-index: 0; opacity: .5; filter: saturate(1.2) blur(0);
      transition: opacity .3s ease;
    }
    .card:hover .tint{ opacity: .6; }

    .card .body{
      position: relative; z-index: 1; padding: 16px; display: grid; gap: 12px;
    }
    .row{
      display: flex; align-items: center; justify-content: space-between; gap: 8px;
    }
    .tag{
      display: inline-flex; align-items: center; gap: 8px;
      padding: 6px 10px; border-radius: 12px; font-weight: 600; letter-spacing: .2px;
      color: var(--text); background: rgba(255,255,255,0.14);
      border: 1px solid var(--glass-border);
      -webkit-backdrop-filter: blur(8px);
      backdrop-filter: blur(8px);
    }
    .temp{
      font-weight: 800; font-size: 44px; letter-spacing: -1px; display: flex; align-items: baseline; gap: 2px;
    }
    .sub{
      color: var(--subtext); font-size: 13px; letter-spacing: .2px;
    }
    .metrics{
      display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px;
    }
    .chip{
      display: grid; gap: 4px; padding: 10px; border-radius: 12px;
      background: rgba(255,255,255,0.10);
      border: 1px solid var(--glass-border);
      -webkit-backdrop-filter: blur(8px);
      backdrop-filter: blur(8px);
      text-align: center;
    }
    .chip b{ font-weight: 700; }
    .chip .u{ color: var(--subtext); font-size: 12px; }

    /* 展开详情 */
    .details{
      max-height: 0; overflow: hidden; transition: max-height .5s cubic-bezier(.2,.8,.2,1);
    }
    .card.expanded .details{ max-height: 220px; }
    .hours{
      margin-top: 10px; display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 8px;
    }
    .pill{
      border-radius: 12px; padding: 8px; display: grid; gap: 6px; place-items: center;
      background: rgba(255,255,255,0.10);
      border: 1px solid var(--glass-border);
      -webkit-backdrop-filter: blur(6px);
      backdrop-filter: blur(6px);
      min-width: 64px;
    }

    /* ======= 每个天气的主题色与动画层 ======= */
    /* sunny */
    .card.sunny .tint{
      background: radial-gradient(100% 120% at 20% 15%, var(--sunny-1), transparent 40%),
                  radial-gradient(100% 120% at 90% 100%, var(--sunny-2), transparent 40%),
                  linear-gradient(180deg, var(--sunny-3), transparent);
    }
    .sun{
      position: absolute; right: -12px; top: -16px; width: 180px; height: 180px; border-radius: 50%;
      background: radial-gradient(circle at 50% 50%, #fff6bd 0%, #ffd166 35%, #ffb200 70%, rgba(255,178,0,0) 72%);
      box-shadow: 0 0 60px 20px rgba(255, 188, 45, 0.45);
      animation: floatSun 6s ease-in-out infinite alternate;
      filter: saturate(1.1);
      transform: translateZ(40px);
    }
    @keyframes floatSun{
      0%{ transform: translateZ(40px) translateY(0) rotate(0deg); }
      100%{ transform: translateZ(40px) translateY(6px) rotate(3deg); }
    }
    .sun::before{
      content:""; position: absolute; inset: -26px; border-radius: 50%;
      background: conic-gradient(from 0deg, rgba(255,210,80,.65), rgba(255,216,120,.0) 20% 30%, rgba(255,210,80,.65) 40% 41%, rgba(255,216,120,.0) 60% 70%, rgba(255,210,80,.65) 90% 91%, rgba(255,216,120,.0) 100%);
      filter: blur(2px);
      animation: rays 12s linear infinite;
    }
    @keyframes rays { to { transform: rotate(360deg); } }

    /* windy */
    .card.windy .tint{
      background: radial-gradient(120% 120% at 15% 20%, var(--windy-1), transparent 40%),
                  radial-gradient(120% 120% at 85% 90%, var(--windy-2), transparent 40%),
                  linear-gradient(180deg, var(--windy-3), transparent);
    }
    .wind-lines{ position: absolute; inset: 0; overflow: hidden; z-index: 0; }
    .wind-line{
      position: absolute; height: 2px; width: 140px; border-radius: 2px;
      background: linear-gradient(90deg, rgba(255,255,255,0), rgba(255,255,255,.9), rgba(255,255,255,0));
      left: -160px;
      filter: drop-shadow(0 0 8px rgba(255,255,255,.45));
      animation: blow 4s linear infinite;
      transform: translateZ(30px);
    }
    @keyframes blow{
      0% { transform: translateX(0) translateZ(30px); opacity: 0; }
      10% { opacity: 1; }
      90% { opacity: 1; }
      100%{ transform: translateX(140% ) translateZ(30px); opacity: 0; }
    }

    /* rain */
    .card.rain .tint{
      background: radial-gradient(120% 120% at 20% 20%, var(--rain-1), transparent 40%),
                  radial-gradient(120% 120% at 85% 100%, var(--rain-2), transparent 40%),
                  linear-gradient(180deg, var(--rain-3), transparent);
    }
    .cloud{
      position: absolute; top: 8px; left: -14px; width: 180px; height: 90px;
      border-radius: 50px; background: rgba(255,255,255,0.85);
      filter: blur(0.2px) saturate(1.1); opacity: .9;
      box-shadow: inset 0 -8px 20px rgba(0,0,0,0.05);
      animation: drift 10s ease-in-out infinite alternate;
      transform: translateZ(18px);
    }
    .cloud::before, .cloud::after{
      content: ""; position: absolute; background: inherit; border-radius: 50%;
    }
    .cloud::before{ width: 90px; height: 90px; left: 30px; top: -36px; }
    .cloud::after{ width: 120px; height: 120px; left: 80px; top: -50px; }
    @keyframes drift{ from{ transform: translateZ(18px) translateX(0); } to{ transform: translateZ(18px) translateX(18px); } }

    .rain-wrap{ position: absolute; inset: 0; overflow: hidden; }
    .drop{
      position: absolute; width: 2px; height: 18px; border-radius: 1px;
      background: linear-gradient(180deg, rgba(255,255,255,.2), rgba(255,255,255,.9));
      filter: drop-shadow(0 0 4px rgba(255,255,255,.6));
      animation: fall var(--spd,900ms) linear infinite;
      top: -24px;
      transform: translateZ(22px);
    }
    @keyframes fall{
      to { transform: translateY(240px) translateZ(22px); opacity: .85; }
    }

    /* snow */
    .card.snow .tint{
      background: radial-gradient(120% 120% at 20% 20%, var(--snow-1), transparent 40%),
                  radial-gradient(120% 120% at 85% 90%, var(--snow-2), transparent 40%),
                  linear-gradient(180deg, var(--snow-3), transparent);
    }
    .snow-wrap{ position: absolute; inset: 0; overflow: hidden; }
    .flake{
      position: absolute; width: var(--sz,8px); height: var(--sz,8px);
      border-radius: 50%; background: rgba(255,255,255,.95);
      filter: drop-shadow(0 0 6px rgba(255,255,255,.7));
      top: -20px; left: 50%;
      animation: snowFall var(--spd,6s) linear infinite, sway var(--swy,2.4s) ease-in-out infinite;
      transform: translateZ(22px);
    }
    @keyframes snowFall{ to { transform: translateY(270px) translateZ(22px); opacity: .95; } }
    @keyframes sway{ 0%,100% { margin-left: -6px; } 50% { margin-left: 6px; } }

    /* 小图标(小时预报用) */
    .ico{
      width: 22px; height: 22px; flex: 0 0 22px;
    }
    .ico.sunny{
      background: radial-gradient(circle at 50% 50%, #fff6bd 0%, #ffd166 55%, #ffb200 60%);
      border-radius: 50%;
      box-shadow: 0 0 10px 2px rgba(255,188,45,0.5);
    }
    .ico.wind{
      background: linear-gradient(90deg, rgba(255,255,255,0), #fff, rgba(255,255,255,0));
      height: 2px; margin-top: 10px;
      box-shadow: 0 4px 0 0 rgba(255,255,255,.8);
    }
    .ico.rain{
      background: linear-gradient(180deg, rgba(255,255,255,.2), #fff);
      width: 4px; height: 12px; border-radius: 2px;
      box-shadow: 6px 0 0 rgba(255,255,255,.9), -6px 0 0 rgba(255,255,255,.6);
    }
    .ico.snow{
      background: #fff; width: 6px; height: 6px; border-radius: 50%;
      box-shadow: 6px 0 0 #fff, -6px 0 0 #fff;
    }

    /* 运动减弱支持 */
    @media (prefers-reduced-motion: reduce){
      .sun, .cloud, .wind-line, .drop, .flake, body::before{ animation: none !important; }
      .card{ transition: none !important; }
    }
  </style>
</head>
<body>
  <div class="topbar">
    <div class="title">
      <span class="dot"></span>
      <div>天气 · iOS 18 风格</div>
    </div>
    <div class="segment" role="tablist" aria-label="单位切换">
      <button class="seg-btn active" id="btnC" role="tab" aria-selected="true">℃</button>
      <button class="seg-btn" id="btnF" role="tab" aria-selected="false">℉</button>
    </div>
  </div>

  <div class="wrap">
    <div class="carousel" id="carousel">
      <!-- 晴天 -->
      <article class="card sunny" data-c="28" data-label="晴天">
        <div class="tint"></div><div class="chrome"></div>
        <div class="sun" aria-hidden="true"></div>

        <div class="body">
          <div class="row">
            <span class="tag">晴天</span>
            <div class="temp"><span class="val">28</span>°<span class="unit">C</span></div>
          </div>
          <div class="row sub">
            <span>杭州 · 体感 30°</span>
            <span>紫外线 强</span>
          </div>
          <div class="metrics">
            <div class="chip">
              <div class="sub">湿度</div><b>45%</b>
              <div class="u">较舒适</div>
            </div>
            <div class="chip">
              <div class="sub">风速</div><b>3.2 m/s</b>
              <div class="u">东北风</div>
            </div>
            <div class="chip">
              <div class="sub">能见度</div><b>16 km</b>
              <div class="u">良好</div>
            </div>
          </div>

          <div class="details">
            <div class="hours">
              <div class="pill"><div class="sub">现在</div><div class="ico sunny"></div><b>28°</b></div>
              <div class="pill"><div class="sub">+1时</div><div class="ico sunny"></div><b>29°</b></div>
              <div class="pill"><div class="sub">+2时</div><div class="ico sunny"></div><b>30°</b></div>
              <div class="pill"><div class="sub">+3时</div><div class="ico sunny"></div><b>30°</b></div>
            </div>
          </div>
        </div>
      </article>

      <!-- 大风 -->
      <article class="card windy" data-c="19" data-label="大风">
        <div class="tint"></div><div class="chrome"></div>
        <div class="wind-lines" aria-hidden="true"></div>

        <div class="body">
          <div class="row">
            <span class="tag">大风</span>
            <div class="temp"><span class="val">19</span>°<span class="unit">C</span></div>
          </div>
          <div class="row sub">
            <span>青海 · 阵风 24 m/s</span>
            <span>体感 更冷</span>
          </div>
          <div class="metrics">
            <div class="chip">
              <div class="sub">湿度</div><b>30%</b>
              <div class="u">干燥</div>
            </div>
            <div class="chip">
              <div class="sub">风速</div><b>22.4 m/s</b>
              <div class="u">注意防风</div>
            </div>
            <div class="chip">
              <div class="sub">气压</div><b>880 hPa</b>
              <div class="u">偏低</div>
            </div>
          </div>

          <div class="details">
            <div class="hours">
              <div class="pill"><div class="sub">现在</div><div class="ico wind"></div><b>19°</b></div>
              <div class="pill"><div class="sub">+1时</div><div class="ico wind"></div><b>18°</b></div>
              <div class="pill"><div class="sub">+2时</div><div class="ico wind"></div><b>18°</b></div>
              <div class="pill"><div class="sub">+3时</div><div class="ico wind"></div><b>17°</b></div>
            </div>
          </div>
        </div>
      </article>

      <!-- 暴雨 -->
      <article class="card rain" data-c="23" data-label="暴雨">
        <div class="tint"></div><div class="chrome"></div>
        <div class="cloud" aria-hidden="true"></div>
        <div class="rain-wrap" aria-hidden="true"></div>

        <div class="body">
          <div class="row">
            <span class="tag">暴雨</span>
            <div class="temp"><span class="val">23</span>°<span class="unit">C</span></div>
          </div>
          <div class="row sub">
            <span>广州 · 降雨 > 50 mm</span>
            <span>雷达回波 强</span>
          </div>
          <div class="metrics">
            <div class="chip">
              <div class="sub">降雨概率</div><b>95%</b>
              <div class="u">请携带雨具</div>
            </div>
            <div class="chip">
              <div class="sub">风速</div><b>12.6 m/s</b>
              <div class="u">阵风偏强</div>
            </div>
            <div class="chip">
              <div class="sub">云量</div><b>92%</b>
              <div class="u">厚云</div>
            </div>
          </div>

          <div class="details">
            <div class="hours">
              <div class="pill"><div class="sub">现在</div><div class="ico rain"></div><b>23°</b></div>
              <div class="pill"><div class="sub">+1时</div><div class="ico rain"></div><b>22°</b></div>
              <div class="pill"><div class="sub">+2时</div><div class="ico rain"></div><b>22°</b></div>
              <div class="pill"><div class="sub">+3时</div><div class="ico rain"></div><b>21°</b></div>
            </div>
          </div>
        </div>
      </article>

      <!-- 暴雪 -->
      <article class="card snow" data-c="-6" data-label="暴雪">
        <div class="tint"></div><div class="chrome"></div>
        <div class="snow-wrap" aria-hidden="true"></div>

        <div class="body">
          <div class="row">
            <span class="tag">暴雪</span>
            <div class="temp"><span class="val">-6</span>°<span class="unit">C</span></div>
          </div>
          <div class="row sub">
            <span>哈尔滨 · 路面结冰</span>
            <span>寒潮预警</span>
          </div>
          <div class="metrics">
            <div class="chip">
              <div class="sub">体感</div><b>-12°</b>
              <div class="u">风冷效应</div>
            </div>
            <div class="chip">
              <div class="sub">风速</div><b>35 m/s</b>
              <div class="u">出行谨慎</div>
            </div>
            <div class="chip">
              <div class="sub">降雪强度</div><b>大到暴</b>
              <div class="u">能见度差</div>
            </div>
          </div>

          <div class="details">
            <div class="hours">
              <div class="pill"><div class="sub">现在</div><div class="ico snow"></div><b>-6°</b></div>
              <div class="pill"><div class="sub">+1时</div><div class="ico snow"></div><b>-7°</b></div>
              <div class="pill"><div class="sub">+2时</div><div class="ico snow"></div><b>-7°</b></div>
              <div class="pill"><div class="sub">+3时</div><div class="ico snow"></div><b>-8°</b></div>
            </div>
          </div>
        </div>
      </article>
    </div>

    <div class="hint">
      轻触卡片展开 · 鼠标移动/手指滑动体验视差与横向滚动
      <span class="kbd">⌘</span><span class="sub">可搭配 Trackpad 惯性滑动</span>
    </div>
  </div>

  <script>
    // ======= 基础交互:温度单位切换、卡片展开、视差倾斜 =======

    const btnC = document.getElementById('btnC');
    const btnF = document.getElementById('btnF');
    const cards = document.querySelectorAll('.card');

    let unit = 'C'; // 默认摄氏
    function c2f(c){ return Math.round(c * 9/5 + 32); }

    function updateTemps(){
      cards.forEach(card=>{
        const c = parseFloat(card.dataset.c);
        const elVal = card.querySelector('.temp .val');
        const elUnit = card.querySelector('.temp .unit');
        if(!isFinite(c) || !elVal || !elUnit) return;
        if(unit === 'C'){ elVal.textContent = Math.round(c); elUnit.textContent = 'C'; }
        else { elVal.textContent = c2f(c); elUnit.textContent = 'F'; }
        // 同步小时预报里的温度:简单查找所有 pill 中的度数(带°)
        card.querySelectorAll('.pill b').forEach((b,i)=>{
          const base = (card.dataset.label === '晴天' ? [28,29,30,30] :
                       card.dataset.label === '大风' ? [19,18,18,17] :
                       card.dataset.label === '暴雨' ? [23,22,22,21] :
                       [-6,-7,-7,-8])[i] || 0;
          const value = unit === 'C' ? base : c2f(base);
          b.textContent = value + '°';
        });
      });
    }

    btnC.addEventListener('click', ()=>{
      if(unit !== 'C'){
        unit = 'C';
        btnC.classList.add('active'); btnC.setAttribute('aria-selected','true');
        btnF.classList.remove('active'); btnF.setAttribute('aria-selected','false');
        updateTemps();
      }
    });
    btnF.addEventListener('click', ()=>{
      if(unit !== 'F'){
        unit = 'F';
        btnF.classList.add('active'); btnF.setAttribute('aria-selected','true');
        btnC.classList.remove('active'); btnC.setAttribute('aria-selected','false');
        updateTemps();
      }
    });

    // 卡片展开/收起
    cards.forEach(card=>{
      card.addEventListener('click', (e)=>{
        // 避免拖动时立即触发:简单阈值判断
        const wasDragging = Math.abs((card._dragDX||0)) > 6;
        if(wasDragging){ card._dragDX = 0; return; }
        card.classList.toggle('expanded');
      });

      // 3D 视差倾斜
      const MAX = 10; // 最大倾斜角
      function setTilt(x, y){
        const rect = card.getBoundingClientRect();
        const px = (x - rect.left) / rect.width;   // 0..1
        const py = (y - rect.top) / rect.height;   // 0..1
        const tiltY = (0.5 - px) * (MAX * 2); // 左右
        const tiltX = (py - 0.5) * (MAX * 2); // 上下
        card.style.setProperty('--tiltX', tiltX.toFixed(2) + 'deg');
        card.style.setProperty('--tiltY', tiltY.toFixed(2) + 'deg');
      }
      card.addEventListener('mousemove', e=> setTilt(e.clientX, e.clientY));
      card.addEventListener('mouseleave', ()=> {
        card.style.removeProperty('--tiltX');
        card.style.removeProperty('--tiltY');
      });
    });

    // 轻量拖动识别(用于阻止点击误触)
    const carousel = document.getElementById('carousel');
    let downX = 0, dragging = false;
    carousel.addEventListener('pointerdown', e=>{ downX = e.clientX; dragging = true; });
    carousel.addEventListener('pointermove', e=>{
      if(dragging){
        const dx = e.clientX - downX;
        const hovered = document.elementFromPoint(e.clientX, e.clientY);
        const card = hovered?.closest?.('.card');
        if(card) card._dragDX = dx;
      }
    });
    window.addEventListener('pointerup', ()=> dragging = false);

    // ======= 动画元素生成:风线 / 雨滴 / 雪花 =======

    // 风线:每张 windy 卡生成多条,时长和位置随机
    document.querySelectorAll('.card.windy .wind-lines').forEach(layer=>{
      const rows = 8;
      for(let i=0;i<rows;i++){
        const line = document.createElement('span');
        line.className = 'wind-line';
        const y = 30 + i * 20 + Math.random()*10; // 垂直位置
        const dur = 3.2 + Math.random()*2.2;      // 时长
        const delay = -Math.random()*dur;         // 负延迟以打散
        const w = 120 + Math.random()*120;        // 宽度浮动
        line.style.top = y+'px';
        line.style.width = w+'px';
        line.style.animationDuration = dur+'s';
        line.style.animationDelay = delay+'s';
        layer.appendChild(line);
      }
    });

    // 雨滴:暴雨卡片生成大量雨滴
    document.querySelectorAll('.card.rain .rain-wrap').forEach(layer=>{
      const drops = 70; // 密度
      const rectHeight = 260; // 估计区域高度
      for(let i=0;i<drops;i++){
        const d = document.createElement('span');
        d.className = 'drop';
        const left = Math.random()*100;     // 百分比位置
        const spd = 600 + Math.random()*900; // 时长
        const delay = -Math.random()*spd;  // 负延迟
        const skew = -5 + Math.random()*10; // 风偏斜
        const h = 14 + Math.random()*14;  // 雨滴长度
        d.style.left = left+'%';
        d.style.height = h+'px';
        d.style.transform = `translateZ(22px) skewX(${skew}deg)`;
        d.style.animationDuration = spd+'ms';
        d.style.animationDelay = delay+'ms';
        layer.appendChild(d);
      }
    });

    // 雪花:大小、摆动、速度随机
    document.querySelectorAll('.card.snow .snow-wrap').forEach(layer=>{
      const flakes = 46;
      for(let i=0;i<flakes;i++){
        const f = document.createElement('span');
        f.className = 'flake';
        const size = 4 + Math.random()*8;
        const left = Math.random()*100;
        const spd = 5 + Math.random()*6;
        const sway = 1.8 + Math.random()*2.4;
        const delay = -Math.random()*spd;
        f.style.setProperty('--sz', size+'px');
        f.style.left = left+'%';
        f.style.animationDuration = `${spd}s, ${sway}s`;
        f.style.animationDelay = `${delay}s, ${delay/2}s`;
        layer.appendChild(f);
      }
    });

    // 初始温度渲染
    updateTemps();
  </script>
</body>
</html>
──── 1人觉得很赞 ────

使用道具 举报

怎么感觉挺丑的呢
我用的是楼主的提示词,效果确实挺好的啊
您需要登录后才可以回帖 立即登录
高级模式