qwen3.8 有点强啊!?
Auntilz
2026-07-20 13:33
1
提示词:
以 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 风格天气卡片</title>
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>⛅</text></svg>">
<style>
/* ============ 基础 ============ */
@property --amb-a { syntax:'<color>'; inherits:true; initial-value:rgba(30,120,210,.55); }
@property --amb-b { syntax:'<color>'; inherits:true; initial-value:rgba(255,170,60,.35); }
* { margin:0; padding:0; box-sizing:border-box; }
:root{
--ease: cubic-bezier(.32,.72,0,1);
--font: -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text",
"PingFang SC", "HarmonyOS Sans SC", "MiSans", "Microsoft YaHei", "Segoe UI", sans-serif;
}
html,body{ height:100%; }
body{
font-family:var(--font);
background:#070b15;
color:#fff;
min-height:100vh;
display:flex; flex-direction:column;
overflow-x:hidden;
-webkit-font-smoothing:antialiased;
}
::selection{ background:rgba(120,170,255,.35); }
button{ font-family:inherit; }
/* ============ 环境背景(随卡片变色) ============ */
.ambient{
position:fixed; inset:0; z-index:0; pointer-events:none;
background:
radial-gradient(900px 620px at 12% -8%, var(--amb-a), transparent 70%),
radial-gradient(1000px 700px at 88% 110%, var(--amb-b), transparent 70%);
transition: --amb-a 1.4s ease, --amb-b 1.4s ease;
}
.vignette{
position:fixed; inset:0; z-index:1; pointer-events:none;
background:radial-gradient(120% 95% at 50% 38%, transparent 58%, rgba(0,0,0,.52));
}
.grain{
position:fixed; inset:0; z-index:1; pointer-events:none; opacity:.05;
background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}
/* ============ 顶栏 ============ */
.topbar{
position:relative; z-index:3;
display:flex; justify-content:space-between; align-items:flex-end;
max-width:1560px; width:100%; margin:0 auto;
padding:34px 36px 4px;
animation:fadeDown .8s var(--ease) backwards;
}
.date-line{ font-size:12.5px; font-weight:600; letter-spacing:.16em; color:rgba(255,255,255,.5); }
.topbar h1{ font-size:38px; font-weight:800; letter-spacing:.02em; margin-top:3px; }
.topbar .sub{ font-size:11px; letter-spacing:.3em; color:rgba(255,255,255,.32); margin-top:4px; font-weight:600; }
.controls{ display:flex; flex-direction:column; align-items:flex-end; gap:12px; }
.clock{ font-size:30px; font-weight:200; font-variant-numeric:tabular-nums; letter-spacing:.03em; color:rgba(255,255,255,.92); }
.seg{
position:relative; display:flex; padding:2px; border-radius:10px;
background:rgba(255,255,255,.1); border:1px solid rgba(255,255,255,.08);
}
.seg button{
position:relative; z-index:1; width:56px; padding:6px 0; border:0; background:none;
font-size:14px; font-weight:600; color:rgba(255,255,255,.6); cursor:pointer; transition:color .3s;
}
.seg button.on{ color:#0b0f1a; }
.seg-thumb{
position:absolute; top:2px; left:2px; width:56px; height:calc(100% - 4px);
background:#fff; border-radius:8px; box-shadow:0 2px 8px rgba(0,0,0,.4);
transition:transform .35s var(--ease);
}
.seg.f .seg-thumb{ transform:translateX(56px); }
/* ============ 卡片阵列 ============ */
.deck{
position:relative; z-index:3; flex:1;
display:grid; grid-template-columns:repeat(4,1fr); gap:22px;
max-width:1560px; width:100%; margin:0 auto;
padding:26px 36px 6px; align-content:center;
}
.card{
position:relative; height:520px; border-radius:30px; overflow:hidden;
cursor:pointer; user-select:none;
transform:perspective(1100px) rotateX(var(--rx,0deg)) rotateY(var(--ry,0deg))
translateY(var(--lift,0px)) scale(var(--sc,1));
transition:transform .6s var(--ease), box-shadow .5s ease;
box-shadow:0 24px 50px -20px rgba(0,0,0,.6), inset 0 1px 0 rgba(255,255,255,.28);
animation:cardIn .9s var(--ease) backwards;
outline:none;
}
.card.tilting{ transition:transform .08s linear, box-shadow .5s ease; }
.card:nth-child(1){ animation-delay:.08s; } .card:nth-child(2){ animation-delay:.18s; }
.card:nth-child(3){ animation-delay:.28s; } .card:nth-child(4){ animation-delay:.38s; }
.card:hover{ --lift:-10px; --sc:1.015; box-shadow:0 40px 70px -22px rgba(0,0,0,.7), inset 0 1px 0 rgba(255,255,255,.35); }
.card:active{ --sc:.982; --lift:-4px; }
.card:focus-visible{ box-shadow:0 0 0 3px rgba(140,190,255,.8), 0 24px 50px -20px rgba(0,0,0,.6); }
.card::before{
content:''; position:absolute; inset:0; border-radius:inherit; z-index:3; pointer-events:none;
border:1px solid rgba(255,255,255,.16);
}
.ring{
position:absolute; inset:0; border-radius:inherit; z-index:4; pointer-events:none;
border:2px solid rgba(255,255,255,0); transition:border-color .35s, box-shadow .35s;
}
.card.active .ring{
border-color:rgba(255,255,255,.85);
box-shadow:0 0 0 4px rgba(255,255,255,.14), inset 0 0 26px rgba(255,255,255,.12);
}
/* 卡片底色(四种天气) */
.card[data-id="sunny"]{ background:linear-gradient(185deg,#1873cc 0%,#3f9fe8 40%,#7cc4f2 68%,#f7bd63 100%); }
.card[data-id="windy"]{ background:linear-gradient(185deg,#2b5e6f 0%,#4f8a92 44%,#8fbcb0 74%,#cfe2d3 100%); }
.card[data-id="rain"] { background:linear-gradient(185deg,#121a2c 0%,#28384f 42%,#41546f 74%,#5a6c88 100%); }
.card[data-id="snow"] { background:linear-gradient(185deg,#4c71a1 0%,#7d9ec6 44%,#b0c7df 74%,#dfeaf6 100%); }
.scene{
position:absolute; inset:-3%; z-index:0; overflow:hidden;
transform:translate3d(var(--px,0px), var(--py,0px), 0) scale(1.05);
transition:transform .3s ease-out;
}
.scrim{
position:absolute; inset:0; z-index:1; pointer-events:none;
background:linear-gradient(180deg, rgba(8,14,26,.32) 0%, transparent 30%, transparent 60%, rgba(8,14,26,.36) 100%);
}
/* ---- 卡片文字层 ---- */
.inner{
position:relative; z-index:2; height:100%;
padding:22px 24px 20px; display:flex; flex-direction:column;
text-shadow:0 1px 14px rgba(0,20,45,.28);
}
.row-top{ display:flex; justify-content:space-between; align-items:flex-start; }
.city{ font-size:21px; font-weight:600; letter-spacing:.02em; }
.en{ display:block; font-size:9.5px; font-weight:700; letter-spacing:.26em; opacity:.55; margin-top:3px; }
.live{
display:inline-flex; align-items:center; gap:6px;
font-size:11px; font-weight:600; color:rgba(255,255,255,.8);
padding:5px 10px; border-radius:14px; background:rgba(10,18,32,.22);
-webkit-backdrop-filter:blur(8px); backdrop-filter:blur(8px);
}
.live i{ width:6px; height:6px; border-radius:50%; background:#30d158; animation:pulseDot 1.8s ease-in-out infinite; }
.pill{
display:inline-flex; align-items:center; gap:6px; align-self:flex-start;
margin-top:12px; padding:5px 12px; border-radius:20px;
font-size:12px; font-weight:600; letter-spacing:.02em;
-webkit-backdrop-filter:blur(8px); backdrop-filter:blur(8px);
transition:transform .3s var(--ease);
}
.card:hover .pill{ transform:translateY(-2px); }
.pill.uv { background:rgba(175,82,222,.78); color:#fff; }
.pill.wind{ background:rgba(255,214,10,.88); color:#4a3b00; text-shadow:none; }
.pill.rain{ background:rgba(255,69,58,.82); color:#fff; }
.pill.snow{ background:rgba(255,159,10,.88); color:#4a2b00; text-shadow:none; }
.temp{ margin-top:10px; font-size:clamp(52px,4.4vw,66px); font-weight:200; line-height:1.05; letter-spacing:-.02em; }
.temp .deg{ font-size:.48em; font-weight:300; vertical-align:14%; opacity:.9; }
.t-val{ display:inline-block; font-variant-numeric:tabular-nums; }
.t-val.roll{ animation:rollText .38s ease; }
.cond{ font-size:17px; font-weight:500; opacity:.95; margin-top:2px; }
.hilo{ font-size:13.5px; font-weight:500; opacity:.8; margin-top:5px; display:flex; gap:14px; }
.spark-wrap{ margin-top:auto; }
.spark{ height:46px; }
.spark svg{ display:block; width:100%; height:46px; overflow:visible; }
.spark-cap{ display:block; font-size:11px; font-weight:500; opacity:.66; margin-top:7px; letter-spacing:.04em; }
/* ============ 场景一:晴天 ============ */
.sun-wrap{ position:absolute; top:52px; right:26px; width:104px; height:104px; }
.sun-glow{
position:absolute; top:-84px; right:-84px; width:360px; height:360px;
background:radial-gradient(circle, rgba(255,205,90,.42), transparent 65%);
transition:transform 1s ease, opacity 1s ease;
}
.card[data-id="sunny"]:hover .sun-glow{ transform:scale(1.25); opacity:1; }
.sun-rays{
position:absolute; inset:-96px; border-radius:50%;
background:repeating-conic-gradient(from 0deg, rgba(255,255,255,.15) 0deg 6deg, transparent 6deg 18deg);
-webkit-mask:radial-gradient(circle, transparent 21%, #000 22%, #000 60%, transparent 61%);
mask:radial-gradient(circle, transparent 21%, #000 22%, #000 60%, transparent 61%);
animation:spin 46s linear infinite;
}
.card[data-id="sunny"]:hover .sun-rays{ animation-duration:15s; }
.sun{
position:absolute; inset:0; border-radius:50%;
background:radial-gradient(circle at 38% 34%, #fffbe8 0%, #ffe98a 34%, #ffc93d 68%, #ffb300 100%);
box-shadow:0 0 44px 10px rgba(255,196,64,.65), 0 0 120px 42px rgba(255,180,60,.26);
animation:sunPulse 5s ease-in-out infinite;
transition:transform .8s var(--ease);
}
.card[data-id="sunny"]:hover .sun{ transform:scale(1.07); }
.flare{ position:absolute; border-radius:50%; background:rgba(255,255,255,.5); filter:blur(2px); }
.flare.f1{ top:196px; right:158px; width:13px; height:13px; opacity:.55; }
.flare.f2{ top:238px; right:206px; width:8px; height:8px; opacity:.4; }
.cloud{ position:absolute; background:#fff; border-radius:50px; filter:blur(1px); }
.cloud::before,.cloud::after{ content:''; position:absolute; background:inherit; border-radius:50%; }
.cloud.small{ width:88px; height:26px; opacity:.92; }
.cloud.small::before{ width:38px; height:38px; top:-17px; left:14px; }
.cloud.small::after{ width:26px; height:26px; top:-10px; left:46px; }
.cloud.ca{ top:57%; animation:driftA 70s linear infinite; }
.cloud.cb{ top:72%; scale:.68; opacity:.75; animation:driftB 95s linear infinite; }
/* ============ 场景二:大风 ============ */
.wind-lines{ position:absolute; inset:0; width:100%; height:100%; }
.wl{
fill:none; stroke:rgba(255,255,255,.5); stroke-width:3.4; stroke-linecap:round;
stroke-dasharray:82 440; animation:windash 3.4s linear infinite;
}
.wl.w1{ animation-duration:calc(var(--ws,1)*2.9s); }
.wl.w2{ animation-duration:calc(var(--ws,1)*3.8s); animation-delay:-1.2s; opacity:.7; stroke-width:2.8; }
.wl.w3{ animation-duration:calc(var(--ws,1)*3.2s); animation-delay:-2s; opacity:.55; }
.wl.w4{ animation-duration:calc(var(--ws,1)*4.4s); animation-delay:-.6s; opacity:.4; stroke-width:2.4; }
.card[data-id="windy"]:hover{ --ws:.45; }
.streak{
position:absolute; left:0; width:44%; height:10px; border-radius:999px;
background:rgba(255,255,255,.5); filter:blur(6px);
animation:streakMove calc(var(--ws,1)*5.2s) linear infinite;
}
.streak.s1{ top:24%; animation-delay:-1s; }
.streak.s2{ top:50%; scale:1.25 .8; opacity:.7; animation-delay:-2.6s; animation-duration:calc(var(--ws,1)*4.2s); }
.streak.s3{ top:72%; scale:.8 .7; opacity:.55; animation-delay:-.4s; animation-duration:calc(var(--ws,1)*6.4s); }
.leaf{ position:absolute; left:0; font-size:20px; filter:drop-shadow(0 2px 4px rgba(0,0,0,.2));
animation:leafFly calc(var(--ws,1)*7s) linear infinite; }
.leaf.l1{ top:34%; }
.leaf.l2{ top:58%; font-size:16px; animation-delay:-2.8s; animation-duration:calc(var(--ws,1)*8.4s); }
.leaf.l3{ top:80%; font-size:15px; animation-delay:-5s; animation-duration:calc(var(--ws,1)*9.2s); }
/* ============ 场景三:暴雨 ============ */
.storm-clouds i{ position:absolute; border-radius:50%; filter:blur(16px); animation:cloudSway 9s ease-in-out infinite alternate; }
.storm-clouds i:nth-child(1){ width:250px; height:95px; top:-34px; left:-46px; background:#141c2e; }
.storm-clouds i:nth-child(2){ width:320px; height:115px; top:-50px; left:26%; background:#1a2436; animation-delay:-3s; }
.storm-clouds i:nth-child(3){ width:270px; height:100px; top:-30px; right:-60px; background:#16202f; animation-delay:-6s; }
.rain{ position:absolute; inset:-12%; transform:rotate(12deg); }
.rain span{
position:absolute; top:-16%; width:2px; border-radius:2px;
background:linear-gradient(180deg, transparent, rgba(186,212,255,.8));
animation-name:fall; animation-timing-function:linear; animation-iteration-count:infinite;
}
.card[data-id="rain"]:hover{ --rs:.52; }
.card[data-id="rain"]:hover .rain span{ opacity:1; }
.flash{
position:absolute; inset:0; opacity:0;
background:radial-gradient(620px 320px at 62% 0%, rgba(255,255,255,.95), rgba(255,255,255,.28) 58%, transparent 80%);
}
.scene.flashing .flash{ animation:flashAnim .75s ease-out; }
.bolt{
position:absolute; top:7%; left:54%; width:58px; fill:#fff; opacity:0;
filter:drop-shadow(0 0 14px rgba(190,215,255,.95));
}
.scene.flashing .bolt{ animation:boltAnim .75s ease-out; }
.rain-fog{ position:absolute; left:0; right:0; bottom:0; height:30%;
background:linear-gradient(180deg, transparent, rgba(130,152,185,.28)); }
/* ============ 场景四:暴雪 ============ */
.snow-clouds i{ position:absolute; border-radius:50%; filter:blur(14px); background:#c7d6ea; opacity:.85;
animation:cloudSway 11s ease-in-out infinite alternate; }
.snow-clouds i:nth-child(1){ width:260px; height:90px; top:-36px; left:-40px; }
.snow-clouds i:nth-child(2){ width:320px; height:105px; top:-48px; right:-70px; animation-delay:-4s; background:#d4e1f1; }
.snow{ position:absolute; inset:0; transition:opacity 1s ease; }
.snow.lb{ opacity:0; }
.card[data-id="snow"]:hover .snow.lb{ opacity:1; }
.flake{ position:absolute; top:-6%; animation:fallY var(--d) linear var(--del) infinite; }
.flake i{
display:block; width:var(--sz); height:var(--sz); border-radius:50%;
background:#fff; opacity:var(--o); filter:blur(var(--bl));
box-shadow:0 0 6px rgba(255,255,255,.55);
animation:swayX var(--sd) ease-in-out infinite alternate;
}
.card[data-id="snow"]:hover .flake i{ box-shadow:0 0 10px rgba(255,255,255,.85); }
.mist{
position:absolute; left:-20%; width:140%; height:90px; filter:blur(18px);
background:linear-gradient(90deg, transparent, rgba(255,255,255,.4), transparent);
opacity:.55; transition:opacity 1s ease; animation:mistDrift 17s ease-in-out infinite alternate;
}
.card[data-id="snow"]:hover .mist{ opacity:.95; }
.mist.m1{ bottom:15%; }
.mist.m2{ bottom:34%; animation-duration:23s; animation-direction:alternate-reverse; }
.frost{ position:absolute; left:0; right:0; bottom:0; height:24%;
background:linear-gradient(180deg, transparent, rgba(240,247,255,.4) 68%, rgba(255,255,255,.58)); }
/* ============ 底部提示 ============ */
.hint{
position:relative; z-index:3; text-align:center;
font-size:12.5px; letter-spacing:.06em; color:rgba(255,255,255,.42);
padding:14px 20px 26px; animation:fadeDown 1s var(--ease) .5s backwards;
}
.hint b{ color:rgba(255,255,255,.66); font-weight:600; }
/* ============ 详情面板(iOS Sheet) ============ */
.backdrop{
position:fixed; inset:0; z-index:40; background:rgba(3,7,14,.52);
-webkit-backdrop-filter:blur(5px); backdrop-filter:blur(5px);
opacity:0; pointer-events:none; transition:opacity .45s ease;
}
.backdrop.open{ opacity:1; pointer-events:auto; }
.sheet{
position:fixed; left:50%; bottom:0; z-index:50;
width:min(1080px,96vw); max-height:min(86vh,880px); overflow-y:auto;
transform:translate(-50%,105%);
transition:transform .62s var(--ease);
background:linear-gradient(180deg, rgba(30,37,52,.88), rgba(13,17,27,.94));
-webkit-backdrop-filter:blur(40px) saturate(1.6); backdrop-filter:blur(40px) saturate(1.6);
border-radius:26px 26px 0 0; border-top:1px solid rgba(255,255,255,.16);
box-shadow:0 -24px 90px rgba(0,0,0,.55);
padding:10px 34px 24px;
}
.sheet.open{ transform:translate(-50%,0); }
.sheet::-webkit-scrollbar{ width:8px; }
.sheet::-webkit-scrollbar-thumb{ background:rgba(255,255,255,.16); border-radius:8px; }
.grabber{ width:38px; height:5px; border-radius:3px; background:rgba(255,255,255,.28); margin:10px auto 20px; }
.sh-head{ display:flex; justify-content:space-between; align-items:flex-start; animation:riseIn .55s var(--ease) .05s backwards; }
.sh-city{ font-size:26px; font-weight:700; letter-spacing:.02em; }
.sh-en{ font-size:10px; font-weight:700; letter-spacing:.3em; color:rgba(255,255,255,.42); margin-left:10px; vertical-align:3px; }
.sh-temp{ display:flex; align-items:center; gap:14px; margin-top:6px; }
.sh-icon{ font-size:42px; filter:drop-shadow(0 4px 10px rgba(0,0,0,.35)); animation:floatIcon 3.2s ease-in-out infinite; }
.sh-t{ font-size:58px; font-weight:200; letter-spacing:-.02em; line-height:1; }
.sh-cond{ font-size:14px; color:rgba(235,240,250,.66); margin-top:8px; font-weight:500; }
.sh-close{
width:34px; height:34px; border-radius:50%; border:0; cursor:pointer;
background:rgba(255,255,255,.12); color:#fff; font-size:15px; line-height:1;
transition:background .3s, transform .45s var(--ease);
}
.sh-close:hover{ background:rgba(255,255,255,.24); transform:rotate(90deg); }
.sh-alert{
display:inline-flex; align-items:center; gap:8px; margin-top:16px;
padding:8px 16px; border-radius:22px; font-size:13px; font-weight:700; letter-spacing:.03em;
animation:riseIn .55s var(--ease) .12s backwards;
}
.sh-alert.uv { background:rgba(175,82,222,.3); color:#e2b8ff; border:1px solid rgba(175,82,222,.5); }
.sh-alert.wind{ background:rgba(255,214,10,.22); color:#ffe58a; border:1px solid rgba(255,214,10,.45); }
.sh-alert.rain{ background:rgba(255,69,58,.25); color:#ffb0a8; border:1px solid rgba(255,69,58,.5); }
.sh-alert.snow{ background:rgba(255,159,10,.22); color:#ffd39a; border:1px solid rgba(255,159,10,.45); }
.sh-summary{
margin-top:14px; font-size:15px; line-height:1.75; color:rgba(235,240,250,.85);
max-width:64ch; animation:riseIn .55s var(--ease) .18s backwards;
}
.sh-sec{ animation:riseIn .55s var(--ease) backwards; }
.sh-sec:nth-of-type(1){ animation-delay:.24s; }
.sh-sec:nth-of-type(2){ animation-delay:.32s; }
.sh-sec:nth-of-type(3){ animation-delay:.4s; }
.sh-sec h4{
display:flex; align-items:center; gap:8px; margin:28px 0 12px;
font-size:12.5px; font-weight:700; letter-spacing:.14em; color:rgba(255,255,255,.45);
}
.sh-sec h4::after{ content:''; flex:1; height:1px; background:rgba(255,255,255,.09); }
.hours{
display:flex; gap:7px; overflow-x:auto; padding:4px 2px 12px;
scrollbar-width:none;
-webkit-mask-image:linear-gradient(90deg, transparent, #000 3%, #000 97%, transparent);
mask-image:linear-gradient(90deg, transparent, #000 3%, #000 97%, transparent);
}
.hours::-webkit-scrollbar{ display:none; }
.hour{
min-width:66px; display:flex; flex-direction:column; align-items:center; gap:9px;
padding:14px 6px 12px; border-radius:18px; background:rgba(255,255,255,.055);
transition:background .3s, transform .3s var(--ease);
}
.hour:hover{ background:rgba(255,255,255,.14); transform:translateY(-4px); }
.hour.now{ background:rgba(255,255,255,.16); }
.h-time{ font-size:12px; color:rgba(255,255,255,.55); font-weight:600; }
.h-ic{ font-size:22px; filter:drop-shadow(0 3px 6px rgba(0,0,0,.3)); }
.h-bar{ width:4px; height:40px; border-radius:4px; background:rgba(255,255,255,.13);
display:flex; align-items:flex-end; overflow:hidden; }
.h-bar i{
display:block; width:100%; border-radius:4px;
background:linear-gradient(180deg, #fff, var(--acc,#7aa7ff));
animation:barGrow .7s var(--ease) backwards;
animation-delay:calc(var(--i)*38ms + .3s);
}
.h-t{ font-size:15px; font-weight:600; font-variant-numeric:tabular-nums; }
.arc-wrap{ display:flex; flex-direction:column; align-items:center; }
.arc-svg{ width:min(430px,100%); overflow:visible; }
.arc-base{ fill:none; stroke:rgba(255,255,255,.16); stroke-width:2; stroke-dasharray:2 7; stroke-linecap:round; }
.arc-prog{ fill:none; stroke:url(#arcG); stroke-width:3; stroke-linecap:round; }
.horizon{ stroke:rgba(255,255,255,.12); stroke-width:1; }
.sun-dot{ fill:#ffd76a; opacity:0; animation:dotIn .5s ease 1s forwards; }
.arc-labels{ display:flex; justify-content:space-between; width:min(430px,100%);
font-size:12.5px; color:rgba(255,255,255,.55); font-weight:600; margin-top:6px; }
.arc-note{ font-size:11px; color:rgba(255,255,255,.35); margin-top:6px; letter-spacing:.08em; }
.metrics{ display:grid; grid-template-columns:repeat(3,1fr); gap:12px; }
.tile{
background:rgba(255,255,255,.06); border:1px solid rgba(255,255,255,.07);
border-radius:18px; padding:14px 16px 13px;
transition:background .3s, transform .3s var(--ease);
}
.tile:hover{ background:rgba(255,255,255,.11); transform:translateY(-3px); }
.tile-h{ display:flex; align-items:center; gap:6px; font-size:11px; font-weight:700;
letter-spacing:.1em; color:rgba(255,255,255,.45); }
.tile-v{ font-size:21px; font-weight:650; margin-top:9px; letter-spacing:-.01em; }
.tile-n{ font-size:11.5px; color:rgba(255,255,255,.45); margin-top:3px; }
.sh-foot{ margin-top:26px; padding-top:16px; border-top:1px solid rgba(255,255,255,.08);
font-size:11.5px; color:rgba(255,255,255,.32); text-align:center; letter-spacing:.06em; }
/* ============ 动画 ============ */
@keyframes cardIn{ from{ opacity:0; transform:perspective(1100px) translateY(70px) scale(.9); }
to{ opacity:1; transform:perspective(1100px) translateY(0) scale(1); } }
@keyframes fadeDown{ from{ opacity:0; transform:translateY(-16px); } to{ opacity:1; transform:none; } }
@keyframes riseIn{ from{ opacity:0; transform:translateY(22px); } to{ opacity:1; transform:none; } }
@keyframes spin{ to{ transform:rotate(360deg); } }
@keyframes sunPulse{ 0%,100%{ transform:scale(1); } 50%{ transform:scale(1.045); } }
@keyframes driftA{ from{ left:-26%; } to{ left:112%; } }
@keyframes driftB{ from{ left:112%; } to{ left:-26%; } }
@keyframes windash{ to{ stroke-dashoffset:-522; } }
@keyframes streakMove{ from{ transform:translateX(-130%); } to{ transform:translateX(310%); } }
@keyframes leafFly{
0%{ transform:translate(-60px,0) rotate(0); opacity:0; }
8%{ opacity:.95; }
30%{ transform:translate(120px,-36px) rotate(160deg); }
55%{ transform:translate(260px,20px) rotate(320deg); }
82%{ opacity:.9; }
100%{ transform:translate(540px,-8px) rotate(620deg); opacity:0; }
}
@keyframes fall{ to{ transform:translateY(660px); } }
@keyframes fallY{ to{ transform:translateY(590px); } }
@keyframes swayX{ from{ transform:translateX(calc(var(--sw)*-1)); } to{ transform:translateX(var(--sw)); } }
@keyframes flashAnim{ 0%{opacity:0} 6%{opacity:.9} 14%{opacity:.12} 22%{opacity:.55} 36%,100%{opacity:0} }
@keyframes boltAnim{ 0%,100%{opacity:0} 5%,13%{opacity:1} 17%{opacity:.15} 22%,28%{opacity:.85} 38%{opacity:0} }
@keyframes cloudSway{ from{ transform:translateX(-9px); } to{ transform:translateX(9px); } }
@keyframes mistDrift{ from{ transform:translateX(-6%); } to{ transform:translateX(6%); } }
@keyframes pulseDot{ 0%,100%{ box-shadow:0 0 0 0 rgba(48,209,88,.6); } 60%{ box-shadow:0 0 0 6px rgba(48,209,88,0); } }
@keyframes rollText{ 0%{transform:translateY(0);opacity:1} 45%{transform:translateY(-16px);opacity:0}
55%{transform:translateY(16px);opacity:0} 100%{transform:translateY(0);opacity:1} }
@keyframes barGrow{ from{ height:0; } }
@keyframes floatIcon{ 0%,100%{ transform:translateY(0); } 50%{ transform:translateY(-5px); } }
@keyframes dotIn{ to{ opacity:1; } }
/* ============ 响应式 ============ */
@media (max-width:1360px){
.deck{ grid-template-columns:repeat(2,1fr); }
.card{ height:500px; }
}
@media (max-width:720px){
.deck{ grid-template-columns:1fr; padding:20px; gap:18px; }
.card{ height:470px; }
.topbar{ flex-direction:column; align-items:flex-start; gap:16px; padding:26px 20px 0; }
.controls{ flex-direction:row; width:100%; justify-content:space-between; align-items:center; }
.clock{ font-size:24px; }
.topbar h1{ font-size:32px; }
.metrics{ grid-template-columns:repeat(2,1fr); }
.sheet{ padding:10px 20px 22px; }
.sh-t{ font-size:48px; }
}
@media (prefers-reduced-motion:reduce){
*,*::before,*::after{ animation-duration:.01ms!important; animation-iteration-count:1!important; transition-duration:.01ms!important; }
}
</style>
</head>
<body>
<div class="ambient"></div>
<div class="vignette"></div>
<div class="grain"></div>
<header class="topbar">
<div>
<div class="date-line" id="dateLine">—</div>
<h1>天气</h1>
<div class="sub">WEATHER · iOS 18 STYLE</div>
</div>
<div class="controls">
<div class="clock" id="clock">00:00:00</div>
<div class="seg" id="unitSeg">
<button class="on" data-u="C">°C</button>
<button data-u="F">°F</button>
<span class="seg-thumb"></span>
</div>
</div>
</header>
<main class="deck">
<!-- 晴天 -->
<article class="card" data-id="sunny" tabindex="0" role="button" aria-label="三亚 晴,点击查看详情">
<div class="scene">
<div class="sun-glow"></div>
<div class="sun-wrap">
<div class="sun-rays"></div>
<div class="sun"></div>
</div>
<span class="flare f1"></span><span class="flare f2"></span>
<div class="cloud small ca"></div>
<div class="cloud small cb"></div>
</div>
<div class="scrim"></div>
<div class="inner">
<div class="row-top">
<div><h2 class="city">—</h2><span class="en">—</span></div>
<span class="live"><i></i>实时</span>
</div>
<span class="pill">—</span>
<div class="temp"><span class="t-val">0</span><span class="deg">°</span></div>
<p class="cond">—</p>
<p class="hilo"><span class="hi">—</span><span class="lo">—</span></p>
<div class="spark-wrap"><div class="spark"></div><span class="spark-cap">—</span></div>
</div>
<span class="ring"></span>
</article>
<!-- 大风 -->
<article class="card" data-id="windy" tabindex="0" role="button" aria-label="青岛 大风,点击查看详情">
<div class="scene">
<svg class="wind-lines" viewBox="0 0 400 520" preserveAspectRatio="none">
<path class="wl w1" d="M-40 110 C 60 80, 150 145, 240 112 S 420 84, 470 112"/>
<path class="wl w2" d="M-40 205 C 80 238, 170 175, 260 208 S 430 238, 470 208"/>
<path class="wl w3" d="M-40 315 C 60 285, 180 348, 280 312 S 440 288, 470 308"/>
<path class="wl w4" d="M-40 425 C 90 455, 190 392, 300 428 S 450 452, 470 432"/>
</svg>
<div class="streak s1"></div><div class="streak s2"></div><div class="streak s3"></div>
<span class="leaf l1">🍃</span><span class="leaf l2">🍃</span><span class="leaf l3">🍂</span>
</div>
<div class="scrim"></div>
<div class="inner">
<div class="row-top">
<div><h2 class="city">—</h2><span class="en">—</span></div>
<span class="live"><i></i>实时</span>
</div>
<span class="pill">—</span>
<div class="temp"><span class="t-val">0</span><span class="deg">°</span></div>
<p class="cond">—</p>
<p class="hilo"><span class="hi">—</span><span class="lo">—</span></p>
<div class="spark-wrap"><div class="spark"></div><span class="spark-cap">—</span></div>
</div>
<span class="ring"></span>
</article>
<!-- 暴雨 -->
<article class="card" data-id="rain" tabindex="0" role="button" aria-label="深圳 暴雨,点击查看详情">
<div class="scene">
<div class="storm-clouds"><i></i><i></i><i></i></div>
<div class="rain" id="rainBox"></div>
<svg class="bolt" viewBox="0 0 100 200"><path d="M55 0 L18 98 L44 98 L30 200 L84 76 L54 76 Z"/></svg>
<div class="flash"></div>
<div class="rain-fog"></div>
</div>
<div class="scrim"></div>
<div class="inner">
<div class="row-top">
<div><h2 class="city">—</h2><span class="en">—</span></div>
<span class="live"><i></i>实时</span>
</div>
<span class="pill">—</span>
<div class="temp"><span class="t-val">0</span><span class="deg">°</span></div>
<p class="cond">—</p>
<p class="hilo"><span class="hi">—</span><span class="lo">—</span></p>
<div class="spark-wrap"><div class="spark"></div><span class="spark-cap">—</span></div>
</div>
<span class="ring"></span>
</article>
<!-- 暴雪 -->
<article class="card" data-id="snow" tabindex="0" role="button" aria-label="哈尔滨 暴雪,点击查看详情">
<div class="scene">
<div class="snow-clouds"><i></i><i></i></div>
<div class="snow la" id="snowA"></div>
<div class="snow lb" id="snowB"></div>
<div class="mist m1"></div><div class="mist m2"></div>
<div class="frost"></div>
</div>
<div class="scrim"></div>
<div class="inner">
<div class="row-top">
<div><h2 class="city">—</h2><span class="en">—</span></div>
<span class="live"><i></i>实时</span>
</div>
<span class="pill">—</span>
<div class="temp"><span class="t-val">0</span><span class="deg">°</span></div>
<p class="cond">—</p>
<p class="hilo"><span class="hi">—</span><span class="lo">—</span></p>
<div class="spark-wrap"><div class="spark"></div><span class="spark-cap">—</span></div>
</div>
<span class="ring"></span>
</article>
</main>
<p class="hint"><b>点按卡片</b> 查看逐小时预报与完整详情 · <b>悬停</b> 感受场景变化与 3D 视差 · 数据为演示样例</p>
<div class="backdrop" id="backdrop"></div>
<section class="sheet" id="sheet" aria-label="天气详情">
<div class="grabber"></div>
<div id="sheetBody"></div>
</section>
<script>
const $ = s => document.querySelector(s);
const $$ = s => [...document.querySelectorAll(s)];
let unit = 'C', activeId = null;
const conv = c => unit === 'C' ? Math.round(c) : Math.round(c * 9 / 5 + 32);
/* ================= 数据 ================= */
const DATA = {
sunny: {
city:'三亚', en:'SANYA', condition:'晴', icon:'☀️',
temp:33, feels:38, high:36, low:27,
accent:'#ffcf5c', sunT:.58, sunrise:'06:12', sunset:'19:24',
ambient:['rgba(30,120,210,.55)','rgba(255,170,60,.38)'],
alert:{ cls:'uv', icon:'🔆', text:'紫外线指数 极强' },
sparkCap:'未来 12 小时 · 持续晴好',
summary:'全天晴朗,午后最高气温 36°,日落前后回落至 30° 左右。紫外线指数极强,外出请注意防晒并及时补充水分。',
hours:[['现在','☀️',33],['14时','☀️',35],['15时','☀️',36],['16时','🌤️',35],['17时','🌤️',34],['18时','🌇',32],
['19时','🌙',30],['20时','🌙',29],['21时','🌙',29],['22时','🌙',28],['23时','🌙',28],['00时','🌙',27]],
metrics:[['💧','湿度','55%','体感舒适'],['🌬️','风速','12 km/h','东南风 3 级'],['🔆','紫外线','11 极强','10–16 时避免暴晒'],
['🌀','气压','1006 hPa','持续平稳'],['👁️','能见度','25 km','视野清晰'],['☔','降水量','0 mm','未来 24 小时无降水']],
},
windy: {
city:'青岛', en:'QINGDAO', condition:'大风', icon:'💨',
temp:21, feels:18, high:23, low:16,
accent:'#7fd4c1', sunT:.44, sunrise:'05:48', sunset:'19:02',
ambient:['rgba(46,110,120,.55)','rgba(150,200,180,.3)'],
alert:{ cls:'wind', icon:'⚠️', text:'大风黄色预警' },
sparkCap:'未来 12 小时 · 风力逐渐减弱',
summary:'西北风 6–7 级,沿海阵风可达 8 级,预计明晨逐渐减弱。请关好门窗,减少高空与户外作业。',
hours:[['现在','💨',21],['14时','💨',22],['15时','🌤️',23],['16时','💨',22],['17时','💨',22],['18时','🌤️',21],
['19时','💨',20],['20时','💨',19],['21时','🌙',19],['22时','💨',18],['23时','🌙',18],['00时','🌙',17]],
metrics:[['💧','湿度','42%','空气偏干燥'],['🌬️','风速','62 km/h','西北风 8 级阵风'],['🔆','紫外线','5 中等','建议涂抹防晒'],
['🌀','气压','1012 hPa','明显偏高'],['👁️','能见度','18 km','良好'],['☔','降水量','0 mm','无降水']],
},
rain: {
city:'深圳', en:'SHENZHEN', condition:'暴雨', icon:'⛈️',
temp:26, feels:29, high:28, low:24,
accent:'#7aa7ff', sunT:.30, sunrise:'06:01', sunset:'19:10',
ambient:['rgba(40,60,110,.6)','rgba(90,120,170,.35)'],
alert:{ cls:'rain', icon:'🚨', text:'暴雨红色预警' },
sparkCap:'未来 12 小时 · 降雨持续',
summary:'受强降水云团影响,未来 3 小时降雨将持续,累计雨量可达 80 毫米以上,并伴有雷电。请远离低洼地带,减少外出。',
hours:[['现在','⛈️',27],['14时','🌧️',26],['15时','⛈️',26],['16时','🌧️',25],['17时','🌧️',25],['18时','⛈️',24],
['19时','🌧️',24],['20时','🌧️',24],['21时','🌧️',23],['22时','🌦️',23],['23时','🌧️',23],['00时','🌧️',22]],
metrics:[['💧','湿度','94%','非常潮湿'],['🌬️','风速','45 km/h','东南风 7 级'],['🔆','紫外线','1 最弱','云层遮蔽'],
['🌀','气压','996 hPa','明显偏低'],['👁️','能见度','3.2 km','较差'],['☔','降水量','86 mm','大暴雨量级']],
},
snow: {
city:'哈尔滨', en:'HARBIN', condition:'暴雪', icon:'🌨️',
temp:-9, feels:-16, high:-6, low:-15,
accent:'#bfe0ff', sunT:.36, sunrise:'07:02', sunset:'16:45',
ambient:['rgba(90,130,180,.5)','rgba(200,225,250,.28)'],
alert:{ cls:'snow', icon:'❄️', text:'暴雪橙色预警' },
sparkCap:'未来 12 小时 · 降雪持续',
summary:'降雪将持续至夜间,新增积雪深度 12–15 厘米,伴随道路结冰。请注意防寒保暖,出行注意防滑。',
hours:[['现在','🌨️',-9],['14时','🌨️',-10],['15时','❄️',-10],['16时','🌨️',-11],['17时','🌨️',-11],['18时','❄️',-12],
['19时','🌨️',-12],['20时','❄️',-13],['21时','🌨️',-13],['22时','❄️',-14],['23时','🌨️',-14],['00时','❄️',-15]],
metrics:[['💧','湿度','82%','湿冷感明显'],['🌬️','风速','28 km/h','北风 5 级'],['🔆','紫外线','2 弱','雪面反射注意护眼'],
['🌀','气压','1021 hPa','偏高'],['👁️','能见度','1.5 km','受降雪影响'],['☔','降水量','12 mm','暴雪量级']],
},
};
/* ================= 卡片初始化 ================= */
function buildSpark(el, temps, id){
const w = 260, h = 46, pad = 4;
const mn = Math.min(...temps), mx = Math.max(...temps), rg = (mx - mn) || 1;
const pts = temps.map((t,i)=>[ pad + i*(w-2*pad)/(temps.length-1), h - 8 - ((t-mn)/rg)*(h-18) ]);
let line = `M${pts[0][0]},${pts[0][1]}`;
for(let i=1;i<pts.length;i++){
const [x0,y0]=pts[i-1], [x1,y1]=pts[i], mx2=(x0+x1)/2;
line += ` C${mx2},${y0} ${mx2},${y1} ${x1},${y1}`;
}
const area = line + ` L${pts[pts.length-1][0]},${h} L${pts[0][0]},${h} Z`;
const last = pts[pts.length-1];
el.innerHTML = `<svg viewBox="0 0 ${w} ${h}" preserveAspectRatio="none">
<defs><linearGradient id="sg${id}" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="rgba(255,255,255,.42)"/><stop offset="1" stop-color="rgba(255,255,255,0)"/>
</linearGradient></defs>
<path d="${area}" fill="url(#sg${id})"/>
<path class="sline" d="${line}" fill="none" stroke="rgba(255,255,255,.95)" stroke-width="2.4" stroke-linecap="round"/>
<circle cx="${last[0]}" cy="${last[1]}" r="3.4" fill="#fff"/>
</svg>`;
const path = el.querySelector('.sline'), len = path.getTotalLength();
path.style.strokeDasharray = len; path.style.strokeDashoffset = len;
requestAnimationFrame(()=>requestAnimationFrame(()=>{
path.style.transition = 'stroke-dashoffset 1.4s cubic-bezier(.4,0,.2,1) .4s';
path.style.strokeDashoffset = 0;
}));
}
function animateTemp(el, target, delay){
const start = performance.now() + delay, dur = 1100;
(function frame(now){
let t = (now - start) / dur;
if(t < 0){ requestAnimationFrame(frame); return; }
t = Math.min(1, t);
el.textContent = Math.round(target * (1 - Math.pow(1 - t, 3)));
if(t < 1) requestAnimationFrame(frame);
})(performance.now());
}
$$('.card').forEach((card, idx)=>{
const d = DATA[card.dataset.id];
card.querySelector('.city').textContent = d.city;
card.querySelector('.en').textContent = d.en;
const pill = card.querySelector('.pill');
pill.className = 'pill ' + d.alert.cls;
pill.textContent = d.alert.icon + ' ' + d.alert.text;
card.querySelector('.cond').textContent = `${d.condition} · 体感 ${conv(d.feels)}°`;
card.querySelector('.hi').textContent = `最高 ${conv(d.high)}°`;
card.querySelector('.lo').textContent = `最低 ${conv(d.low)}°`;
card.querySelector('.spark-cap').textContent = d.sparkCap;
buildSpark(card.querySelector('.spark'), d.hours.map(h=>h[2]), card.dataset.id);
animateTemp(card.querySelector('.t-val'), conv(d.temp), 380 + idx * 150);
});
/* ================= 粒子:雨 & 雪 ================= */
(function makeRain(){
const box = $('#rainBox'); let html = '';
for(let i=0;i<70;i++){
const d = (0.55 + Math.random()*0.5).toFixed(2);
html += `<span style="left:${(Math.random()*118-9).toFixed(1)}%;height:${46+Math.random()*44|0}px;` +
`opacity:${(0.25+Math.random()*0.55).toFixed(2)};` +
`animation-duration:calc(var(--rs,1)*${d}s);animation-delay:${(-Math.random()*2).toFixed(2)}s"></span>`;
}
box.innerHTML = html;
})();
(function makeSnow(){
const gen = n => {
let html = '';
for(let i=0;i<n;i++){
const sz = 2.5 + Math.random()*4.5;
html += `<span class="flake" style="left:${(Math.random()*104-2).toFixed(1)}%;--d:${(6+Math.random()*7).toFixed(1)}s;` +
`--del:${(-Math.random()*10).toFixed(1)}s;--sd:${(2.4+Math.random()*2).toFixed(1)}s;--sw:${12+Math.random()*22|0}px">` +
`<i style="--sz:${sz.toFixed(1)}px;--o:${(0.5+Math.random()*0.5).toFixed(2)};--bl:${sz<4?1.2:0.4}px"></i></span>`;
}
return html;
};
$('#snowA').innerHTML = gen(36);
$('#snowB').innerHTML = gen(30);
})();
/* ================= 闪电调度 ================= */
const rainScene = document.querySelector('.card[data-id="rain"] .scene');
(function storm(){
setTimeout(()=>{
rainScene.classList.add('flashing');
setTimeout(()=>rainScene.classList.remove('flashing'), 820);
storm();
}, 3600 + Math.random()*5200);
})();
/* ================= 时钟 ================= */
const WD = ['周日','周一','周二','周三','周四','周五','周六'];
function tick(){
const d = new Date(), p = n => String(n).padStart(2,'0');
$('#clock').textContent = `${p(d.getHours())}:${p(d.getMinutes())}:${p(d.getSeconds())}`;
$('#dateLine').textContent = `${d.getFullYear()}年${d.getMonth()+1}月${d.getDate()}日 · ${WD[d.getDay()]}`;
}
tick(); setInterval(tick, 1000);
/* ================= 3D 倾斜 + 视差 ================= */
if(matchMedia('(hover:hover) and (pointer:fine)').matches){
$$('.card').forEach(card=>{
card.addEventListener('pointerenter', ()=>card.classList.add('tilting'));
card.addEventListener('pointermove', e=>{
const r = card.getBoundingClientRect();
const x = (e.clientX - r.left)/r.width - .5;
const y = (e.clientY - r.top)/r.height - .5;
card.style.setProperty('--ry', (x*9).toFixed(2)+'deg');
card.style.setProperty('--rx', (-y*7).toFixed(2)+'deg');
card.style.setProperty('--px', (x*-12).toFixed(1)+'px');
card.style.setProperty('--py', (y*-9).toFixed(1)+'px');
});
card.addEventListener('pointerleave', ()=>{
card.classList.remove('tilting');
['--rx','--ry'].forEach(v=>card.style.setProperty(v,'0deg'));
['--px','--py'].forEach(v=>card.style.setProperty(v,'0px'));
setAmbient(DATA[activeId || 'sunny']);
});
card.addEventListener('pointerenter', ()=>setAmbient(DATA[card.dataset.id]));
});
}
/* ================= 环境色 ================= */
function setAmbient(d){
document.documentElement.style.setProperty('--amb-a', d.ambient[0]);
document.documentElement.style.setProperty('--amb-b', d.ambient[1]);
}
/* ================= 详情面板 ================= */
const sheet = $('#sheet'), sheetBody = $('#sheetBody'), backdrop = $('#backdrop');
function renderSheet(id){
const d = DATA[id];
const temps = d.hours.map(h=>h[2]);
const mn = Math.min(...temps), mx = Math.max(...temps), rg = (mx-mn)||1;
sheetBody.style.setProperty('--acc', d.accent);
sheetBody.innerHTML = `
<div class="sh-head">
<div>
<div class="sh-city">${d.city}<span class="sh-en">${d.en}</span></div>
<div class="sh-temp"><span class="sh-icon">${d.icon}</span><span class="sh-t">${conv(d.temp)}°</span></div>
<div class="sh-cond">${d.condition} · 体感 ${conv(d.feels)}° · 最高 ${conv(d.high)}° / 最低 ${conv(d.low)}°</div>
</div>
<button class="sh-close" id="shClose" aria-label="关闭">✕</button>
</div>
<div class="sh-alert ${d.alert.cls}">${d.alert.icon} ${d.alert.text}</div>
<p class="sh-summary">${d.summary}</p>
<section class="sh-sec">
<h4>🕐 每小时预报</h4>
<div class="hours">${d.hours.map((h,i)=>`
<div class="hour ${i===0?'now':''}" style="--i:${i}">
<span class="h-time">${h[0]}</span><span class="h-ic">${h[1]}</span>
<div class="h-bar"><i style="height:${(14+((h[2]-mn)/rg)*86).toFixed(0)}%"></i></div>
<span class="h-t">${conv(h[2])}°</span>
</div>`).join('')}
</div>
</section>
<section class="sh-sec">
<h4>🌅 日出日落</h4>
<div class="arc-wrap">
<svg class="arc-svg" viewBox="0 0 320 132">
<defs><linearGradient id="arcG" x1="0" y1="0" x2="1" y2="0">
<stop offset="0" stop-color="#ffd76a"/><stop offset="1" stop-color="#ff9d3c"/>
</linearGradient></defs>
<line class="horizon" x1="8" y1="112" x2="312" y2="112"/>
<path class="arc-base" d="M16 112 Q160 -26 304 112"/>
<path class="arc-prog" id="arcProg" d="M16 112 Q160 -26 304 112"/>
<circle class="sun-dot" id="sunDot" r="6.5" style="filter:drop-shadow(0 0 9px rgba(255,205,90,.95))"/>
</svg>
<div class="arc-labels"><span>↑ 日出 ${d.sunrise}</span><span>↓ 日落 ${d.sunset}</span></div>
<div class="arc-note">— 太阳当前位置 —</div>
</div>
</section>
<section class="sh-sec">
<h4>📊 天气详情</h4>
<div class="metrics">${d.metrics.map(m=>`
<div class="tile">
<div class="tile-h"><span>${m[0]}</span>${m[1]}</div>
<div class="tile-v">${m[2]}</div>
<div class="tile-n">${m[3]}</div>
</div>`).join('')}
</div>
</section>
<footer class="sh-foot">数据为演示样例 · iOS 18 风格天气卡片</footer>`;
$('#shClose').addEventListener('click', closeSheet);
const prog = $('#arcProg'), len = prog.getTotalLength();
prog.style.strokeDasharray = len; prog.style.strokeDashoffset = len;
requestAnimationFrame(()=>requestAnimationFrame(()=>{
prog.style.transition = 'stroke-dashoffset 1.2s cubic-bezier(.4,0,.2,1) .35s';
prog.style.strokeDashoffset = len * (1 - d.sunT);
}));
const p = prog.getPointAtLength(len * d.sunT);
const dot = $('#sunDot');
dot.setAttribute('cx', p.x); dot.setAttribute('cy', p.y);
}
function openSheet(id){
activeId = id;
$$('.card').forEach(c=>c.classList.toggle('active', c.dataset.id === id));
setAmbient(DATA[id]);
renderSheet(id);
sheet.classList.add('open'); backdrop.classList.add('open');
}
function closeSheet(){
sheet.classList.remove('open'); backdrop.classList.remove('open');
}
$$('.card').forEach(card=>{
card.addEventListener('click', ()=>openSheet(card.dataset.id));
card.addEventListener('keydown', e=>{
if(e.key === 'Enter' || e.key === ' '){ e.preventDefault(); openSheet(card.dataset.id); }
});
});
backdrop.addEventListener('click', closeSheet);
document.addEventListener('keydown', e=>{ if(e.key === 'Escape') closeSheet(); });
/* ================= 单位切换 ================= */
const seg = $('#unitSeg');
seg.querySelectorAll('button').forEach(b=>b.addEventListener('click', ()=>{
if(unit === b.dataset.u) return;
unit = b.dataset.u;
seg.classList.toggle('f', unit === 'F');
seg.querySelectorAll('button').forEach(x=>x.classList.toggle('on', x === b));
$$('.card').forEach(card=>{
const d = DATA[card.dataset.id];
const tv = card.querySelector('.t-val');
tv.classList.remove('roll'); void tv.offsetWidth; tv.classList.add('roll');
setTimeout(()=>{
tv.textContent = conv(d.temp);
card.querySelector('.cond').textContent = `${d.condition} · 体感 ${conv(d.feels)}°`;
card.querySelector('.hi').textContent = `最高 ${conv(d.high)}°`;
card.querySelector('.lo').textContent = `最低 ${conv(d.low)}°`;
}, 175);
});
if(activeId) setTimeout(()=>renderSheet(activeId), 200);
}));
</script>
</body>
</html>

到了国模起飞的版本了嘛,家家都对标fable5 
最新回复 (14)
-
Jerryi 07-20 13:351楼认真的吗^-^我上午试了试特别简单的问题都改不好
-
金陵雪 07-20 13:532楼我在qoder里测试和grok4.5差不多,推理能力略低于grok4.5
-
kaisen 07-20 13:573楼qwen3.8在x上看到有人测试,效果并不是很理想哇
-
Kate Tseng 07-20 13:594楼别老是测天气卡片啦,现在大家都是以长任务为主了,这种任务没啥意义了
-
zljbjh 07-20 14:005楼各家对于这种测试都过拟合了。阿里这模型明显是没有多少后训练的。
-
unsafetrait 07-20 14:006楼慢慢用,实际上幻觉率极高,我这边问几个问题,人家幻想一对有的没的内容,我觉得好神奇,要不是我们自己有REVIEW习惯就真信了,感觉这个版本幻觉率比QWEN3.7 PLUS高不止一点
-
unsafetrait 07-20 14:017楼感觉基本没有,真的有时候挺无语的
-
摇摆熊 07-20 14:018楼那是不是意思说写短片小说一定很强了
-
翠花上酸菜 07-20 14:029楼是刚才测试的吗?我看网上说昨天上的版本上错了,现在才改成真正要上的版本
-
zfy 07-20 14:0210楼qwen 真的原地踏步 甚至是退步 看来还是没有找到方法
-
unsafetrait 07-20 14:0211楼你可以试试,反正感觉这模型脑子不大好使的样子 ^-^ 不过前端强一般逻辑都差,但是QWEN 3.8好像逻辑不差,所以你们试试吧,我们只管代码
-
wintsa 07-20 14:0312楼画个简单的前端而已。。。gpt5.3都能做的事
-
Xiwis Homed 07-20 14:0413楼听他吹牛逼呢,上模型还能上错你以为是过家家吗
-
翠花上酸菜 07-20 14:0614楼那不知道了,昨晚上了之后看类脑有网友测了流口水。刚才他重测说变牛逼了
* 帖子来源Linux.do
附近帖子