Model claude-fable-5 MAX天气卡片

说实话一般,而且页面卡卡的掉帧 <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1...
Model claude-fable-5 MAX天气卡片
Model claude-fable-5 MAX天气卡片

说实话一般,而且页面卡卡的掉帧

image

image

<!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>
  :root { --spring: cubic-bezier(.32, .72, .25, 1); }

  * { margin: 0; padding: 0; box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
  html, body { height: 100%; }

  body {
    font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro SC",
                 "PingFang SC", "Helvetica Neue", "Microsoft YaHei", sans-serif;
    background: #070a14;
    color: #fff;
    display: flex; align-items: center; justify-content: center;
    overflow: hidden;
    -webkit-font-smoothing: antialiased;
  }

  /* ========== 背景氛围光斑 ========== */
  .ambient { position: fixed; inset: 0; z-index: 0; pointer-events: none; overflow: hidden; }
  .blob { position: absolute; border-radius: 50%; filter: blur(110px); opacity: .55;
          animation: blobFloat 16s ease-in-out infinite alternate; }
  .b1 { width: 520px; height: 520px; background: #27408f; top: -180px; left: -120px; }
  .b2 { width: 460px; height: 460px; background: #5b2a7a; bottom: -160px; right: -100px; animation-delay: -5s; }
  .b3 { width: 380px; height: 380px; background: #175e5e; bottom: 6%; left: 34%; animation-delay: -10s; opacity: .4; }
  @keyframes blobFloat { to { transform: translate(70px, 50px) scale(1.18); } }

  /* ========== 顶部栏 ========== */
  .stage { width: min(1240px, 94vw); position: relative; z-index: 1; }
  .topbar { display: flex; align-items: flex-end; justify-content: space-between; margin: 0 6px 20px; }
  .topbar h1 { font-size: 34px; font-weight: 700; letter-spacing: 1px; }
  .sub { margin-top: 6px; font-size: 14px; color: rgba(255,255,255,.62);
         display: flex; align-items: center; gap: 8px; }
  .sub svg { opacity: .9; }
  .glass-chip {
    display: flex; align-items: center; gap: 9px; padding: 10px 16px;
    border-radius: 999px; background: rgba(255,255,255,.08);
    border: 1px solid rgba(255,255,255,.15);
    backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
    font-size: 15px; font-weight: 600; font-variant-numeric: tabular-nums;
  }
  .live-dot { width: 8px; height: 8px; border-radius: 50%; background: #34d399;
              box-shadow: 0 0 10px #34d399; animation: pulseDot 2s infinite; }
  @keyframes pulseDot { 50% { opacity: .35; } }

  /* ========== 卡片容器 ========== */
  .cards { display: flex; gap: 18px; height: min(600px, 68vh); min-height: 480px; perspective: 1600px; }

  .card {
    position: relative; flex: 1; border-radius: 32px; overflow: hidden;
    cursor: pointer; user-select: none; outline: none;
    border: 1px solid rgba(255,255,255,.28);
    box-shadow: 0 24px 48px -12px rgba(0,0,0,.5), inset 0 1px 0 rgba(255,255,255,.35);
    transition: flex-grow .7s var(--spring), min-height .7s var(--spring),
                box-shadow .45s ease, border-color .45s ease, transform .25s ease-out;
    animation: cardIn .9s cubic-bezier(.22, 1, .36, 1) backwards;
    transform-style: preserve-3d;
  }
  .card:nth-child(1) { animation-delay: .05s; } .card:nth-child(2) { animation-delay: .15s; }
  .card:nth-child(3) { animation-delay: .25s; } .card:nth-child(4) { animation-delay: .35s; }
  @keyframes cardIn { from { opacity: 0; transform: translateY(44px) scale(.96); } }

  .card:hover { box-shadow: 0 30px 60px -14px rgba(0,0,0,.62); }
  .card:not(.active):hover { transform: translateY(-8px); }
  .card:focus-visible { border-color: rgba(255,255,255,.85); }
  .card.active {
    flex-grow: 2.6;
    border-color: rgba(255,255,255,.5);
    box-shadow: 0 34px 70px -16px rgba(0,0,0,.68), inset 0 1px 0 rgba(255,255,255,.45);
  }
  /* 底部压暗,保证文字可读性 */
  .card::after { content: ''; position: absolute; inset: 0; z-index: 1; pointer-events: none;
    background: linear-gradient(to top, rgba(8,15,30,.45), rgba(8,15,30,0) 48%); }

  /* 四种天气底色 */
  .sunny     { background: linear-gradient(180deg, #1f6dd1 0%, #4f9be6 40%, #9ccdf0 72%, #ffd9a0 100%); }
  .windy     { background: linear-gradient(180deg, #23606e 0%, #3d8d8a 48%, #7cc4ad 82%, #b9e2cf 100%); }
  .rainstorm { background: linear-gradient(180deg, #151d2c 0%, #243349 52%, #3a516c 100%); }
  .blizzard  { background: linear-gradient(180deg, #46688f 0%, #6e93b4 45%, #a9c7da 78%, #e6f2f8 100%); }

  /* ========== 卡片内容 ========== */
  .content { position: relative; z-index: 3; height: 100%; display: flex; flex-direction: column; padding: 22px; }
  .row-top { display: flex; justify-content: space-between; gap: 8px; }
  .chip { display: inline-flex; align-items: center; gap: 6px; padding: 6px 11px;
    font-size: 12px; font-weight: 600; border-radius: 999px; white-space: nowrap;
    background: rgba(255,255,255,.16); border: 1px solid rgba(255,255,255,.22);
    backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); }
  .chip.warn   { background: rgba(255,159,67,.28); border-color: rgba(255,159,67,.5); }
  .chip.danger { background: rgba(255,107,107,.3); border-color: rgba(255,107,107,.52); }
  .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--c,#fff); box-shadow: 0 0 8px var(--c,#fff); }

  .bottom { margin-top: auto; }
  .w-eng  { font-size: 11px; letter-spacing: 3px; opacity: .7; font-weight: 600; }
  .w-name { font-size: 20px; font-weight: 600; letter-spacing: 2px; margin-top: 2px;
            text-shadow: 0 2px 12px rgba(0,0,0,.3); }
  .temp { font-weight: 200; line-height: 1.05; letter-spacing: -2px;
    font-size: clamp(56px, 6.2vw, 78px); text-shadow: 0 4px 24px rgba(0,0,0,.28);
    transition: font-size .6s var(--spring); font-variant-numeric: tabular-nums; }
  .card:not(.active) .temp { font-size: clamp(40px, 4.2vw, 52px); font-weight: 300; }
  .range { font-size: 13.5px; color: rgba(255,255,255,.88); margin-top: 2px; text-shadow: 0 1px 8px rgba(0,0,0,.3); }

  /* 展开区域 */
  .reveal { max-height: 0; opacity: 0; transform: translateY(16px); overflow: hidden;
    transition: max-height .7s var(--spring), opacity .5s ease .08s, transform .65s var(--spring); }
  .card.active .reveal { max-height: 340px; opacity: 1; transform: none; }
  .desc { font-size: 13px; color: rgba(255,255,255,.78); margin-top: 10px; }
  .metrics { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin-top: 14px; }
  .metric { text-align: center; padding: 10px 6px; border-radius: 16px; overflow: hidden;
    background: rgba(255,255,255,.14); border: 1px solid rgba(255,255,255,.18);
    backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); }
  .metric .k { font-size: 11px; color: rgba(255,255,255,.68); }
  .metric .v { font-size: 14px; font-weight: 600; margin-top: 3px; }
  .hours { display: flex; gap: 8px; margin-top: 10px; }
  .hour { flex: 1; text-align: center; padding: 9px 4px; border-radius: 14px;
    background: rgba(255,255,255,.1); border: 1px solid rgba(255,255,255,.14); }
  .hour .t { font-size: 11px; color: rgba(255,255,255,.65); }
  .hour .v { font-size: 13px; font-weight: 600; margin-top: 4px; }

  /* 鼠标跟随高光 */
  .glare { position: absolute; inset: 0; z-index: 2; pointer-events: none; opacity: 0; transition: opacity .35s;
    background: radial-gradient(420px circle at var(--mx,50%) var(--my,50%), rgba(255,255,255,.2), transparent 46%); }
  .card:hover .glare { opacity: 1; }

  /* ========== 场景动画层 ========== */
  .scene { position: absolute; inset: 0; z-index: 1; pointer-events: none; }

  /* 云朵(通用) */
  .cloud { position: absolute; width: 130px; height: 42px; background: #fff; border-radius: 40px;
           filter: drop-shadow(0 16px 22px rgba(0,0,0,.22)); }
  .cloud::before, .cloud::after { content: ''; position: absolute; background: inherit; border-radius: 50%; }
  .cloud::before { width: 56px; height: 56px; top: -27px; left: 20px; }
  .cloud::after  { width: 36px; height: 36px; top: -17px; right: 22px; }
  .cloud.sm { width: 84px; height: 28px; }
  .cloud.sm::before { width: 38px; height: 38px; top: -18px; left: 12px; }
  .cloud.sm::after  { width: 26px; height: 26px; top: -12px; right: 12px; }
  @keyframes cloudBob { from { transform: translateX(-12px); } to { transform: translateX(12px); } }

  /* —— 晴天 —— */
  .sun-anchor { position: absolute; top: 132px; left: 50%; width: 0; height: 0; }
  .sun { position: absolute; left: -46px; top: -46px; width: 92px; height: 92px; border-radius: 50%;
    background: radial-gradient(circle at 35% 32%, #fff8d6, #ffd94e 48%, #ffae33 78%, #ff9d1f);
    animation: sunPulse 4.5s ease-in-out infinite; }
  @keyframes sunPulse {
    0%, 100% { transform: scale(1);    box-shadow: 0 0 34px 6px rgba(255,205,80,.8), 0 0 90px 28px rgba(255,170,60,.32); }
    50%      { transform: scale(1.06); box-shadow: 0 0 48px 12px rgba(255,205,80,.95), 0 0 120px 40px rgba(255,170,60,.45); }
  }
  .rays { position: absolute; left: 0; top: 0; animation: spin 28s linear infinite; }
  @keyframes spin { to { transform: rotate(360deg); } }
  .ray { position: absolute; left: -2.5px; top: -9px; width: 5px; height: 18px; border-radius: 3px;
    background: linear-gradient(to top, rgba(255,228,130,.95), rgba(255,228,130,0));
    transform: rotate(var(--a)) translateY(-76px); transform-origin: 2.5px 9px; }
  .sunny .c1 { top: 228px; left: 12%; opacity: .85; animation: cloudBob 9s ease-in-out infinite alternate; }
  .sunny .c2 { top: 58px; right: 8%; opacity: .6; animation: cloudBob 12s ease-in-out infinite alternate-reverse; }

  /* —— 大风 —— */
  .windline { position: absolute; height: 3px; border-radius: 4px; opacity: 0;
    background: linear-gradient(90deg, rgba(255,255,255,0), rgba(255,255,255,.85), rgba(255,255,255,0));
    animation: windMove linear infinite; }
  @keyframes windMove {
    0%   { transform: translateX(0); opacity: 0; }
    10%  { opacity: .85; } 80% { opacity: .85; }
    100% { transform: translateX(840px); opacity: 0; }
  }
  .leaf { position: absolute; width: 11px; height: 11px; border-radius: 0 60% 0 60%;
    background: linear-gradient(135deg, #9fdc85, #4f9e4f); animation: leafFly linear infinite; }
  @keyframes leafFly { to { transform: translate(840px, 90px) rotate(680deg); } }
  .windy .cloud.main { top: 128px; left: 50%; margin-left: -65px; background: #eef7f4;
                       animation: cloudBob 4s ease-in-out infinite alternate; }
  .windy .cloud.back { top: 92px; left: 50%; margin-left: -126px; background: #d7e8e2; opacity: .75;
                       animation: cloudBob 5.5s ease-in-out infinite alternate-reverse; }

  /* —— 暴雨 —— */
  .rain { position: absolute; inset: -60px; transform: rotate(9deg); }
  .drop { position: absolute; top: -30px; width: 2px; border-radius: 2px;
    background: linear-gradient(to bottom, rgba(173,216,255,0), rgba(173,216,255,.75));
    animation: fall linear infinite; }
  @keyframes fall { to { transform: translateY(780px); } }
  .rainstorm .cloud.main { top: 118px; left: 50%; margin-left: -65px; background: #39465a; }
  .rainstorm .cloud.back { top: 90px; left: 50%; margin-left: -118px; background: #26303f; opacity: .92;
                           animation: cloudBob 7s ease-in-out infinite alternate; }
  .bolt { position: absolute; top: 150px; left: 50%; margin-left: -15px; width: 30px; height: 48px;
    background: linear-gradient(#ffe879, #ffb62e);
    clip-path: polygon(58% 0, 0 55%, 38% 55%, 28% 100%, 100% 38%, 52% 38%);
    filter: drop-shadow(0 0 14px rgba(255,210,80,.9));
    opacity: 0; animation: boltIdle 7s linear infinite; }
  @keyframes boltIdle { 0%, 85%, 100% { opacity: 0; } 87% { opacity: 1; } 89% { opacity: .15; } 91% { opacity: .9; } 95% { opacity: 0; } }
  .flash-layer { position: absolute; inset: 0; z-index: 4; pointer-events: none; opacity: 0;
    background: radial-gradient(circle at 50% 0%, rgba(255,255,255,.95), rgba(255,255,255,0) 72%); }
  .card.flashing .flash-layer { animation: skyFlash .85s ease-out; }
  .card.flashing .bolt { animation: boltFlash .85s ease both; }
  @keyframes skyFlash { 0% { opacity: 0; } 8% { opacity: .85; } 16% { opacity: .15; } 26% { opacity: .6; } 42% { opacity: .1; } 56% { opacity: .3; } 100% { opacity: 0; } }
  @keyframes boltFlash { 0% { opacity: 0; } 6% { opacity: 1; } 14% { opacity: .2; } 22% { opacity: 1; } 60% { opacity: .85; } 100% { opacity: 0; } }

  /* —— 暴雪 —— */
  .flake { position: absolute; top: -12px; border-radius: 50%; background: #fff; animation: snow linear infinite; }
  @keyframes snow { to { transform: translate(var(--dx, 50px), 760px); } }
  .blizzard .windline { filter: opacity(.45); }
  .blizzard .cloud.main { top: 112px; left: 50%; margin-left: -65px; background: #f3f8fc;
                          animation: cloudBob 6s ease-in-out infinite alternate; }
  .blizzard .cloud.back { top: 84px; left: 50%; margin-left: -116px; background: #c9d9e6; opacity: .8;
                          animation: cloudBob 8s ease-in-out infinite alternate-reverse; }
  .snow-ground { position: absolute; left: -12%; right: -12%; height: 84px; border-radius: 50% 50% 0 0 / 56px; }
  .g2 { background: rgba(210,230,243,.75); bottom: -26px; left: -20%; right: -4%; }
  .g1 { background: rgba(255,255,255,.92); bottom: -40px; }

  .hint { text-align: center; margin-top: 18px; font-size: 13px; color: rgba(255,255,255,.45); letter-spacing: 1px; }

  /* ========== 响应式 & 无障碍 ========== */
  @media (max-width: 880px) {
    body { overflow: auto; padding: 28px 0; align-items: flex-start; }
    .cards { flex-direction: column; height: auto; min-height: 0; }
    .card { flex: none; min-height: 150px; }
    .card.active { min-height: 430px; }
    .metrics { grid-template-columns: repeat(2, 1fr); }
  }
  @media (prefers-reduced-motion: reduce) {
    *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .2s !important; }
  }
</style>
</head>
<body>

  <div class="ambient">
    <div class="blob b1"></div><div class="blob b2"></div><div class="blob b3"></div>
  </div>

  <div class="stage">
    <header class="topbar">
      <div>
        <h1>天气</h1>
        <div class="sub">
          <svg width="13" height="13" viewBox="0 0 24 24" fill="none">
            <path d="M12 21s-7-5.1-7-11a7 7 0 1 1 14 0c0 5.9-7 11-7 11z" stroke="white" stroke-opacity=".7" stroke-width="2"/>
            <circle cx="12" cy="10" r="2.6" fill="white" fill-opacity=".85"/>
          </svg>
          <span>北京市 · 朝阳区</span><span>·</span><span id="dateText"></span>
        </div>
      </div>
      <div class="glass-chip"><span class="live-dot"></span><span id="clockText">--:--:--</span></div>
    </header>

    <main class="cards">

      <!-- ☀️ 晴天 -->
      <article class="card sunny active" tabindex="0" role="button" aria-expanded="true">
        <div class="scene">
          <div class="sun-anchor"><div class="rays"></div><div class="sun"></div></div>
          <div class="cloud sm c1"></div><div class="cloud sm c2"></div>
        </div>
        <div class="content">
          <div class="row-top">
            <span class="chip"><i class="dot" style="--c:#ffd54d"></i>晴</span>
            <span class="chip warn">紫外线 强</span>
          </div>
          <div class="bottom">
            <p class="w-eng">SUNNY</p><h2 class="w-name">晴天</h2>
            <div class="temp"><span class="temp-num" data-target="28">0</span>°</div>
            <p class="range">最高 31° · 最低 22° · 体感 30°</p>
            <div class="reveal"><div>
              <p class="desc">阳光明媚,紫外线较强,外出请注意防晒与补水。</p>
              <div class="metrics">
                <div class="metric"><p class="k">湿度</p><p class="v">42%</p></div>
                <div class="metric"><p class="k">风速</p><p class="v">8 km/h</p></div>
                <div class="metric"><p class="k">气压</p><p class="v">1013 hPa</p></div>
                <div class="metric"><p class="k">能见度</p><p class="v">24 km</p></div>
              </div>
              <div class="hours">
                <div class="hour"><p class="t">现在</p><p class="v">28°</p></div>
                <div class="hour"><p class="t">15时</p><p class="v">29°</p></div>
                <div class="hour"><p class="t">16时</p><p class="v">29°</p></div>
                <div class="hour"><p class="t">17时</p><p class="v">27°</p></div>
                <div class="hour"><p class="t">18时</p><p class="v">25°</p></div>
              </div>
            </div></div>
          </div>
        </div>
        <div class="glare"></div>
      </article>

      <!-- 🌬️ 大风 -->
      <article class="card windy" tabindex="0" role="button" aria-expanded="false">
        <div class="scene">
          <div class="windfield"></div>
          <div class="cloud back sm"></div><div class="cloud main"></div>
        </div>
        <div class="content">
          <div class="row-top">
            <span class="chip"><i class="dot" style="--c:#7fe3c4"></i>大风</span>
            <span class="chip warn">阵风 7 级</span>
          </div>
          <div class="bottom">
            <p class="w-eng">WINDY</p><h2 class="w-name">大风</h2>
            <div class="temp"><span class="temp-num" data-target="21">0</span>°</div>
            <p class="range">最高 23° · 最低 17° · 体感 18°</p>
            <div class="reveal"><div>
              <p class="desc">阵风明显,出行请远离临时搭建物,注意高空坠物。</p>
              <div class="metrics">
                <div class="metric"><p class="k">湿度</p><p class="v">55%</p></div>
                <div class="metric"><p class="k">阵风</p><p class="v">52 km/h</p></div>
                <div class="metric"><p class="k">风向</p><p class="v">西北</p></div>
                <div class="metric"><p class="k">能见度</p><p class="v">18 km</p></div>
              </div>
              <div class="hours">
                <div class="hour"><p class="t">现在</p><p class="v">21°</p></div>
                <div class="hour"><p class="t">15时</p><p class="v">21°</p></div>
                <div class="hour"><p class="t">16时</p><p class="v">20°</p></div>
                <div class="hour"><p class="t">17时</p><p class="v">19°</p></div>
                <div class="hour"><p class="t">18时</p><p class="v">18°</p></div>
              </div>
            </div></div>
          </div>
        </div>
        <div class="glare"></div>
      </article>

      <!-- ⛈️ 暴雨 -->
      <article class="card rainstorm" tabindex="0" role="button" aria-expanded="false">
        <div class="scene">
          <div class="rain"></div>
          <div class="bolt"></div>
          <div class="cloud back sm"></div><div class="cloud main"></div>
        </div>
        <div class="flash-layer"></div>
        <div class="content">
          <div class="row-top">
            <span class="chip"><i class="dot" style="--c:#6db3ff"></i>暴雨</span>
            <span class="chip danger">雷电预警</span>
          </div>
          <div class="bottom">
            <p class="w-eng">STORM</p><h2 class="w-name">暴雨</h2>
            <div class="temp"><span class="temp-num" data-target="23">0</span>°</div>
            <p class="range">最高 24° · 最低 20° · 体感 25°</p>
            <div class="reveal"><div>
              <p class="desc">雷雨持续,局地伴有强雷电,请减少外出避开积水。</p>
              <div class="metrics">
                <div class="metric"><p class="k">湿度</p><p class="v">92%</p></div>
                <div class="metric"><p class="k">降水量</p><p class="v">38 mm</p></div>
                <div class="metric"><p class="k">风速</p><p class="v">24 km/h</p></div>
                <div class="metric"><p class="k">能见度</p><p class="v">1.2 km</p></div>
              </div>
              <div class="hours">
                <div class="hour"><p class="t">现在</p><p class="v">23°</p></div>
                <div class="hour"><p class="t">15时</p><p class="v">22°</p></div>
                <div class="hour"><p class="t">16时</p><p class="v">22°</p></div>
                <div class="hour"><p class="t">17时</p><p class="v">21°</p></div>
                <div class="hour"><p class="t">18时</p><p class="v">21°</p></div>
              </div>
            </div></div>
          </div>
        </div>
        <div class="glare"></div>
      </article>

      <!-- 🌨️ 暴雪 -->
      <article class="card blizzard" tabindex="0" role="button" aria-expanded="false">
        <div class="scene">
          <div class="snowfield"></div>
          <div class="gusts"></div>
          <div class="cloud back sm"></div><div class="cloud main"></div>
          <div class="snow-ground g2"></div><div class="snow-ground g1"></div>
        </div>
        <div class="content">
          <div class="row-top">
            <span class="chip"><i class="dot" style="--c:#cfe9ff"></i>暴雪</span>
            <span class="chip danger">暴雪预警</span>
          </div>
          <div class="bottom">
            <p class="w-eng">BLIZZARD</p><h2 class="w-name">暴雪</h2>
            <div class="temp"><span class="temp-num" data-target="-8">0</span>°</div>
            <p class="range">最高 -6° · 最低 -15° · 体感 -14°</p>
            <div class="reveal"><div>
              <p class="desc">暴雪橙色预警,道路湿滑结冰,请注意保暖与防滑。</p>
              <div class="metrics">
                <div class="metric"><p class="k">湿度</p><p class="v">78%</p></div>
                <div class="metric"><p class="k">风速</p><p class="v">36 km/h</p></div>
                <div class="metric"><p class="k">积雪</p><p class="v">12 cm</p></div>
                <div class="metric"><p class="k">能见度</p><p class="v">0.8 km</p></div>
              </div>
              <div class="hours">
                <div class="hour"><p class="t">现在</p><p class="v">-8°</p></div>
                <div class="hour"><p class="t">15时</p><p class="v">-9°</p></div>
                <div class="hour"><p class="t">16时</p><p class="v">-10°</p></div>
                <div class="hour"><p class="t">17时</p><p class="v">-11°</p></div>
                <div class="hour"><p class="t">18时</p><p class="v">-12°</p></div>
              </div>
            </div></div>
          </div>
        </div>
        <div class="glare"></div>
      </article>

    </main>

    <p class="hint">点击卡片展开 / 收起详情 · 悬停体验光影与 3D 视差</p>
  </div>

<script>
  const rand = (a, b) => Math.random() * (b - a) + a;
  const cards = [...document.querySelectorAll('.card')];

  /* ---------- 粒子生成 ---------- */
  function spawn(sel, n, fn) {
    const box = document.querySelector(sel);
    if (!box) return;
    for (let i = 0; i < n; i++) box.appendChild(fn(i));
  }
  // 太阳光芒 ×12
  spawn('.sunny .rays', 12, i => {
    const r = document.createElement('i');
    r.className = 'ray';
    r.style.setProperty('--a', i * 30 + 'deg');
    return r;
  });
  // 雨滴 ×64
  spawn('.rainstorm .rain', 64, () => {
    const d = document.createElement('span');
    d.className = 'drop';
    d.style.left = rand(0, 100) + '%';
    d.style.height = rand(10, 20) + 'px';
    d.style.opacity = rand(.3, .85);
    d.style.animationDuration = rand(.55, 1.05) + 's';
    d.style.animationDelay = -rand(0, 2) + 's';
    return d;
  });
  // 雪花 ×46
  spawn('.blizzard .snowfield', 46, () => {
    const f = document.createElement('span');
    f.className = 'flake';
    const s = rand(3, 8);
    f.style.width = f.style.height = s + 'px';
    f.style.left = rand(-10, 100) + '%';
    f.style.opacity = rand(.45, .95);
    f.style.setProperty('--dx', rand(30, 140) + 'px');
    f.style.animationDuration = rand(4.5, 9) + 's';
    f.style.animationDelay = -rand(0, 9) + 's';
    if (Math.random() < .3) f.style.filter = 'blur(1px)';
    return f;
  });
  // 风线(大风 ×9,暴雪 ×5)
  const makeWindline = () => {
    const w = document.createElement('span');
    w.className = 'windline';
    w.style.top = rand(8, 82) + '%';
    w.style.left = '-220px';
    w.style.width = rand(80, 200) + 'px';
    w.style.animationDuration = rand(1.6, 3.2) + 's';
    w.style.animationDelay = -rand(0, 3) + 's';
    return w;
  };
  spawn('.windy .windfield', 9, makeWindline);
  spawn('.blizzard .gusts', 5, makeWindline);
  // 落叶 ×6
  spawn('.windy .windfield', 6, () => {
    const l = document.createElement('span');
    l.className = 'leaf';
    l.style.left = '-40px';
    l.style.top = rand(18, 72) + '%';
    l.style.animationDuration = rand(3, 6) + 's';
    l.style.animationDelay = -rand(0, 6) + 's';
    return l;
  });

  /* ---------- 卡片交互:点击展开 + 3D 视差 + 高光 ---------- */
  cards.forEach(card => {
    card.addEventListener('click', () => {
      const on = card.classList.contains('active');
      cards.forEach(c => { c.classList.remove('active'); c.setAttribute('aria-expanded', 'false'); });
      if (!on) { card.classList.add('active'); card.setAttribute('aria-expanded', 'true'); }
    });
    card.addEventListener('keydown', e => {
      if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); card.click(); }
    });
    card.addEventListener('mousemove', e => {
      const r = card.getBoundingClientRect();
      const x = e.clientX - r.left, y = e.clientY - r.top;
      card.style.setProperty('--mx', x + 'px');
      card.style.setProperty('--my', y + 'px');
      const ry = ((x / r.width) - .5) * 8;
      const rx = ((y / r.height) - .5) * -6;
      card.style.transform = `translateY(-6px) rotateX(${rx}deg) rotateY(${ry}deg)`;
    });
    card.addEventListener('mouseleave', () => { card.style.transform = ''; });
  });

  /* ---------- 随机闪电 ---------- */
  const storm = document.querySelector('.rainstorm');
  (function lightning() {
    setTimeout(() => {
      storm.classList.add('flashing');
      setTimeout(() => storm.classList.remove('flashing'), 900);
      lightning();
    }, rand(2200, 7000));
  })();

  /* ---------- 温度数字滚动 ---------- */
  document.querySelectorAll('.temp-num').forEach(el => {
    const target = parseInt(el.dataset.target, 10);
    const t0 = performance.now(), dur = 1500;
    (function step(now) {
      const p = Math.min((now - t0) / dur, 1);
      el.textContent = Math.round(target * (1 - Math.pow(1 - p, 3)));
      if (p < 1) requestAnimationFrame(step);
    })(t0);
  });

  /* ---------- 实时时钟 ---------- */
  const clockEl = document.getElementById('clockText');
  const dateEl = document.getElementById('dateText');
  const weeks = ['周日','周一','周二','周三','周四','周五','周六'];
  function tick() {
    const d = new Date(), p = n => String(n).padStart(2, '0');
    clockEl.textContent = `${p(d.getHours())}:${p(d.getMinutes())}:${p(d.getSeconds())}`;
    dateEl.textContent = `${d.getMonth() + 1}月${d.getDate()}日 ${weeks[d.getDay()]}`;
  }
  tick(); setInterval(tick, 1000);
</script>
</body>
</html>

15 个帖子 - 10 位参与者

阅读完整话题

来源: LinuxDo 最新话题查看原文