喜闻乐见的 DeepSeek V4 Pro 天气卡片
- 内容介绍
- 文章标签
- 相关推荐
image1920×1032 87 KB
<!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 {
--sunny-primary: #FF9F43;
--sunny-secondary: #FECA57;
--sunny-bg: #FFF3E0;
--sunny-glow: rgba(255, 159, 67, 0.45);
--windy-primary: #5F9EA0;
--windy-secondary: #87CEEB;
--windy-bg: #E8F4F8;
--windy-glow: rgba(95, 158, 160, 0.4);
--rain-primary: #4A6FA5;
--rain-secondary: #6B8FBD;
--rain-bg: #1A1D2E;
--rain-glow: rgba(74, 111, 165, 0.5);
--snow-primary: #B0C4DE;
--snow-secondary: #E8F0FE;
--snow-bg: #DCE9F5;
--snow-glow: rgba(176, 196, 222, 0.55);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'SF Pro Text', 'Helvetica Neue', 'PingFang SC', 'Noto Sans SC', sans-serif;
background: #0A0A0F;
overflow-x: hidden;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
user-select: none;
-webkit-user-select: none;
-webkit-tap-highlight-color: transparent;
}
/* 动态网格背景 */
.bg-layer {
position: fixed;
inset: 0;
z-index: 0;
pointer-events: none;
}
.bg-gradient {
position: absolute;
inset: 0;
background:
radial-gradient(ellipse at 15% 50%, rgba(255, 159, 67, 0.18) 0%, transparent 55%),
radial-gradient(ellipse at 40% 30%, rgba(95, 158, 160, 0.14) 0%, transparent 50%),
radial-gradient(ellipse at 65% 60%, rgba(74, 111, 165, 0.2) 0%, transparent 55%),
radial-gradient(ellipse at 85% 35%, rgba(176, 196, 222, 0.16) 0%, transparent 50%),
radial-gradient(ellipse at 50% 80%, rgba(120, 130, 180, 0.08) 0%, transparent 60%);
animation: bgShift 18s ease-in-out infinite;
}
.bg-dots {
position: absolute;
inset: 0;
background-image: radial-gradient(rgba(255, 255, 255, 0.04) 1px, transparent 1px);
background-size: 40px 40px;
mask-image: radial-gradient(ellipse at center, black 30%, transparent 70%);
-webkit-mask-image: radial-gradient(ellipse at center, black 30%, transparent 70%);
}
@keyframes bgShift {
0%,
100% {
opacity: 0.85;
}
25% {
opacity: 1;
}
50% {
opacity: 0.9;
}
75% {
opacity: 0.8;
}
}
/* 主容器 */
.main-container {
position: relative;
z-index: 1;
display: flex;
gap: 20px;
padding: 30px;
flex-wrap: nowrap;
justify-content: center;
align-items: stretch;
perspective: 1200px;
max-width: 1300px;
width: 100%;
}
/* ========== 卡片基础样式 ========== */
.weather-card {
position: relative;
width: 275px;
min-width: 275px;
height: 430px;
border-radius: 28px;
cursor: pointer;
transition: all 0.55s cubic-bezier(0.25, 0.1, 0.1, 1.0);
overflow: hidden;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
backdrop-filter: blur(28px);
-webkit-backdrop-filter: blur(28px);
border: 1.2px solid rgba(255, 255, 255, 0.22);
box-shadow:
0 8px 32px rgba(0, 0, 0, 0.25),
0 2px 8px rgba(0, 0, 0, 0.15),
inset 0 1px 0 rgba(255, 255, 255, 0.12);
z-index: 1;
flex-shrink: 0;
}
.weather-card::before {
content: '';
position: absolute;
inset: 0;
border-radius: 28px;
background: linear-gradient(160deg,
rgba(255, 255, 255, 0.18) 0%,
rgba(255, 255, 255, 0.04) 40%,
rgba(255, 255, 255, 0.0) 60%,
rgba(255, 255, 255, 0.06) 100%);
pointer-events: none;
z-index: 0;
transition: opacity 0.5s;
}
.weather-card::after {
content: '';
position: absolute;
inset: 8px;
border-radius: 22px;
border: 1px solid rgba(255, 255, 255, 0.08);
pointer-events: none;
z-index: 0;
transition: border-color 0.5s;
}
.weather-card:hover {
transform: translateY(-10px) scale(1.04);
box-shadow:
0 22px 48px rgba(0, 0, 0, 0.35),
0 6px 16px rgba(0, 0, 0, 0.2),
inset 0 1px 0 rgba(255, 255, 255, 0.18);
z-index: 10;
border-color: rgba(255, 255, 255, 0.38);
}
.weather-card:hover::after {
border-color: rgba(255, 255, 255, 0.16);
}
.weather-card.expanded {
width: 380px;
min-width: 380px;
height: 510px;
z-index: 20;
border-color: rgba(255, 255, 255, 0.42);
box-shadow:
0 28px 60px rgba(0, 0, 0, 0.45),
0 10px 24px rgba(0, 0, 0, 0.25),
inset 0 1px 0 rgba(255, 255, 255, 0.22);
}
/* 卡片内容层级 */
.card-inner {
position: relative;
z-index: 2;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
padding: 28px 20px 20px;
pointer-events: none;
}
/* ========== 天气动画区域 ========== */
.weather-visual {
position: relative;
width: 160px;
height: 150px;
flex-shrink: 0;
margin-bottom: 8px;
pointer-events: none;
overflow: visible;
}
/* ========== 各天气类型背景色 ========== */
.card-sunny {
background: rgba(255, 180, 100, 0.22);
}
.card-windy {
background: rgba(140, 190, 200, 0.2);
}
.card-rain {
background: rgba(30, 40, 70, 0.45);
}
.card-snow {
background: rgba(200, 215, 235, 0.28);
}
/* ========== 晴天 - 太阳 ========== */
.sun-container {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 80px;
height: 80px;
}
.sun-core {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 56px;
height: 56px;
border-radius: 50%;
background: radial-gradient(circle at 40% 35%, #FFE082 0%, #FFB74D 40%, #F57C00 100%);
box-shadow:
0 0 50px rgba(255, 170, 50, 0.7),
0 0 100px rgba(255, 150, 30, 0.4),
0 0 160px rgba(255, 140, 20, 0.2);
animation: sunPulse 3s ease-in-out infinite;
z-index: 3;
}
@keyframes sunPulse {
0%,
100% {
box-shadow: 0 0 50px rgba(255, 170, 50, 0.7), 0 0 100px rgba(255, 150, 30, 0.4), 0 0 160px rgba(255, 140, 20, 0.2);
}
50% {
box-shadow: 0 0 65px rgba(255, 180, 60, 0.9), 0 0 120px rgba(255, 160, 40, 0.55), 0 0 190px rgba(255, 150, 30, 0.3);
}
}
.sun-ray {
position: absolute;
top: 50%;
left: 50%;
width: 4px;
height: 28px;
background: linear-gradient(to bottom, rgba(255, 200, 80, 0.85), rgba(255, 160, 40, 0));
border-radius: 2px;
transform-origin: bottom center;
animation: rayRotate 12s linear infinite;
}
@keyframes rayRotate {
from {
transform: translate(-50%, -100%) rotate(0deg);
}
to {
transform: translate(-50%, -100%) rotate(360deg);
}
}
.sun-ray:nth-child(odd) {
height: 20px;
animation-duration: 8s;
animation-direction: reverse;
opacity: 0.7;
}
/* 晴天光点 */
.light-particle {
position: absolute;
border-radius: 50%;
background: rgba(255, 220, 120, 0.9);
pointer-events: none;
z-index: 2;
animation: floatUp linear infinite;
box-shadow: 0 0 6px rgba(255, 200, 80, 0.6);
}
@keyframes floatUp {
0% {
transform: translateY(0) translateX(0) scale(1);
opacity: 0;
}
10% {
opacity: 1;
}
80% {
opacity: 0.5;
}
100% {
transform: translateY(-140px) translateX(25px) scale(0.2);
opacity: 0;
}
}
/* ========== 大风 - 云和风线 ========== */
.wind-cloud {
position: absolute;
top: 35px;
left: 50%;
transform: translateX(-50%);
width: 90px;
height: 45px;
background: rgba(220, 230, 240, 0.85);
border-radius: 50px;
box-shadow: 0 4px 20px rgba(150, 180, 200, 0.3);
animation: cloudDrift 5s ease-in-out infinite;
z-index: 2;
}
.wind-cloud::before {
content: '';
position: absolute;
top: -22px;
left: 15px;
width: 44px;
height: 44px;
background: rgba(220, 230, 240, 0.85);
border-radius: 50%;
}
.wind-cloud::after {
content: '';
position: absolute;
top: -14px;
right: 15px;
width: 36px;
height: 36px;
background: rgba(220, 230, 240, 0.85);
border-radius: 50%;
}
@keyframes cloudDrift {
0%,
100% {
transform: translateX(-50%) translateX(-8px);
}
50% {
transform: translateX(-50%) translateX(8px);
}
}
.wind-streak {
position: absolute;
height: 2.5px;
background: linear-gradient(to right, transparent, rgba(180, 200, 220, 0.7), rgba(200, 215, 230, 0.9), rgba(180, 200, 220, 0.5), transparent);
border-radius: 2px;
z-index: 1;
animation: windBlow linear infinite;
opacity: 0;
}
@keyframes windBlow {
0% {
transform: translateX(-60px);
opacity: 0;
}
15% {
opacity: 0.8;
}
70% {
opacity: 0.4;
}
100% {
transform: translateX(120px);
opacity: 0;
}
}
/* ========== 暴雨 - 云和雨滴 ========== */
.rain-cloud-group {
position: absolute;
top: 20px;
left: 50%;
transform: translateX(-50%);
z-index: 3;
}
.rain-cloud-dark {
position: relative;
width: 100px;
height: 42px;
background: rgba(60, 70, 95, 0.9);
border-radius: 50px;
box-shadow: 0 6px 25px rgba(30, 35, 55, 0.5);
}
.rain-cloud-dark::before {
content: '';
position: absolute;
top: -24px;
left: 18px;
width: 48px;
height: 48px;
background: rgba(60, 70, 95, 0.9);
border-radius: 50%;
}
.rain-cloud-dark::after {
content: '';
position: absolute;
top: -16px;
right: 16px;
width: 38px;
height: 38px;
background: rgba(60, 70, 95, 0.9);
border-radius: 50%;
}
.lightning-flash {
position: absolute;
top: 55px;
left: 50%;
transform: translateX(-50%);
width: 3px;
height: 40px;
background: rgba(255, 255, 200, 0.9);
border-radius: 2px;
z-index: 2;
opacity: 0;
box-shadow: 0 0 20px rgba(255, 255, 180, 0.8), 0 0 40px rgba(255, 250, 200, 0.4);
animation: lightningBolt 6s ease-in-out infinite;
}
@keyframes lightningBolt {
0%,
92%,
96%,
100% {
opacity: 0;
}
93% {
opacity: 1;
box-shadow: 0 0 30px rgba(255, 255, 200, 1), 0 0 60px rgba(255, 250, 200, 0.7);
}
94% {
opacity: 0.3;
}
95% {
opacity: 0.9;
box-shadow: 0 0 25px rgba(255, 255, 200, 0.9), 0 0 50px rgba(255, 250, 200, 0.5);
}
}
.raindrop {
position: absolute;
width: 2px;
background: linear-gradient(to bottom, rgba(180, 200, 230, 0.1), rgba(160, 190, 225, 0.8));
border-radius: 0 0 2px 2px;
z-index: 2;
pointer-events: none;
animation: rainFall linear infinite;
}
@keyframes rainFall {
0% {
transform: translateY(-80px);
opacity: 0;
}
8% {
opacity: 1;
}
85% {
opacity: 0.5;
}
100% {
transform: translateY(160px);
opacity: 0;
}
}
/* ========== 暴雪 - 云和雪花 ========== */
.snow-cloud-group {
position: absolute;
top: 22px;
left: 50%;
transform: translateX(-50%);
z-index: 3;
}
.snow-cloud-light {
position: relative;
width: 95px;
height: 40px;
background: rgba(210, 220, 235, 0.9);
border-radius: 50px;
box-shadow: 0 4px 18px rgba(160, 180, 200, 0.4);
}
.snow-cloud-light::before {
content: '';
position: absolute;
top: -22px;
left: 16px;
width: 46px;
height: 46px;
background: rgba(210, 220, 235, 0.9);
border-radius: 50%;
}
.snow-cloud-light::after {
content: '';
position: absolute;
top: -14px;
right: 18px;
width: 36px;
height: 36px;
background: rgba(210, 220, 235, 0.9);
border-radius: 50%;
}
.snowflake {
position: absolute;
border-radius: 50%;
background: rgba(255, 255, 255, 0.9);
z-index: 2;
pointer-events: none;
animation: snowDrift linear infinite;
box-shadow: 0 0 4px rgba(255, 255, 255, 0.5);
}
@keyframes snowDrift {
0% {
transform: translateY(-60px) translateX(0px) rotate(0deg);
opacity: 0;
}
10% {
opacity: 0.9;
}
50% {
transform: translateY(50px) translateX(20px) rotate(180deg);
}
90% {
opacity: 0.6;
}
100% {
transform: translateY(150px) translateX(-15px) rotate(360deg);
opacity: 0;
}
}
/* ========== 文字信息区域 ========== */
.weather-icon-label {
font-size: 36px;
margin-top: 8px;
pointer-events: none;
line-height: 1;
filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.15));
z-index: 3;
position: relative;
}
.weather-name {
font-size: 20px;
font-weight: 600;
letter-spacing: 0.3px;
margin-top: 4px;
pointer-events: none;
z-index: 3;
position: relative;
}
.temperature {
font-size: 52px;
font-weight: 200;
letter-spacing: -2px;
line-height: 1;
margin-top: 4px;
pointer-events: none;
z-index: 3;
position: relative;
}
.temp-unit {
font-size: 22px;
font-weight: 300;
vertical-align: super;
letter-spacing: 0;
}
.weather-desc {
font-size: 13px;
font-weight: 400;
opacity: 0.7;
letter-spacing: 0.2px;
margin-top: 2px;
pointer-events: none;
z-index: 3;
position: relative;
}
/* ========== 展开详情 ========== */
.details-panel {
position: relative;
z-index: 3;
width: 100%;
padding: 0 16px;
margin-top: 6px;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px 14px;
opacity: 0;
transform: translateY(12px);
transition: all 0.45s cubic-bezier(0.25, 0.1, 0.1, 1.0);
pointer-events: none;
max-height: 0;
overflow: hidden;
}
.weather-card.expanded .details-panel {
opacity: 1;
transform: translateY(0);
max-height: 200px;
pointer-events: auto;
}
.detail-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 2px;
padding: 8px 6px;
border-radius: 14px;
background: rgba(255, 255, 255, 0.08);
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
border: 1px solid rgba(255, 255, 255, 0.1);
transition: background 0.3s;
}
.detail-label {
font-size: 10px;
font-weight: 500;
text-transform: uppercase;
letter-spacing: 0.5px;
opacity: 0.6;
}
.detail-value {
font-size: 16px;
font-weight: 500;
letter-spacing: -0.3px;
}
/* ========== 各卡片文字颜色 ========== */
.card-sunny .weather-name,
.card-sunny .temperature,
.card-sunny .weather-desc,
.card-sunny .detail-label,
.card-sunny .detail-value {
color: #5D3A1A;
}
.card-windy .weather-name,
.card-windy .temperature,
.card-windy .weather-desc,
.card-windy .detail-label,
.card-windy .detail-value {
color: #2C4A4E;
}
.card-rain .weather-name,
.card-rain .temperature,
.card-rain .weather-desc,
.card-rain .detail-label,
.card-rain .detail-value {
color: #D5E0F0;
}
.card-snow .weather-name,
.card-snow .temperature,
.card-snow .weather-desc,
.card-snow .detail-label,
.card-snow .detail-value {
color: #3A4A5C;
}
/* 雨天文字发光 */
.card-rain .temperature {
text-shadow: 0 0 30px rgba(200, 215, 235, 0.5);
}
/* ========== 提示文字 ========== */
.hint-text {
position: relative;
z-index: 3;
font-size: 11px;
opacity: 0.45;
margin-top: auto;
pointer-events: none;
transition: opacity 0.4s;
letter-spacing: 0.3px;
}
.weather-card.expanded .hint-text {
opacity: 0;
}
/* ========== 关闭按钮 ========== */
.close-btn {
position: absolute;
top: 14px;
right: 16px;
z-index: 30;
width: 30px;
height: 30px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.15);
border: 1px solid rgba(255, 255, 255, 0.25);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transform: scale(0.6);
transition: all 0.35s cubic-bezier(0.25, 0.1, 0.1, 1.0);
pointer-events: none;
backdrop-filter: blur(6px);
-webkit-backdrop-filter: blur(6px);
}
.close-btn::before,
.close-btn::after {
content: '';
position: absolute;
width: 13px;
height: 1.5px;
background: rgba(255, 255, 255, 0.8);
border-radius: 1px;
}
.close-btn::before {
transform: rotate(45deg);
}
.close-btn::after {
transform: rotate(-45deg);
}
.weather-card.expanded .close-btn {
opacity: 1;
transform: scale(1);
pointer-events: auto;
}
.close-btn:hover {
background: rgba(255, 255, 255, 0.28);
border-color: rgba(255, 255, 255, 0.45);
transform: scale(1.1);
}
.card-rain .close-btn::before,
.card-rain .close-btn::after {
background: rgba(220, 225, 240, 0.9);
}
/* ========== 响应式 ========== */
@media (max-width: 1200px) {
.main-container {
gap: 14px;
padding: 20px;
overflow-x: auto;
scroll-snap-type: x mandatory;
-webkit-overflow-scrolling: touch;
justify-content: flex-start;
padding-left: calc(50% - 140px);
scroll-padding-left: calc(50% - 140px);
}
.weather-card {
scroll-snap-align: center;
width: 250px;
min-width: 250px;
height: 400px;
border-radius: 24px;
}
.weather-card.expanded {
width: 320px;
min-width: 320px;
height: 470px;
}
.weather-visual {
width: 130px;
height: 130px;
}
.temperature {
font-size: 42px;
}
.main-container::-webkit-scrollbar {
height: 0;
}
}
@media (max-width: 600px) {
.main-container {
gap: 10px;
padding: 16px;
padding-left: calc(50% - 125px);
scroll-padding-left: calc(50% - 125px);
}
.weather-card {
width: 220px;
min-width: 220px;
height: 360px;
border-radius: 22px;
}
.weather-card.expanded {
width: 280px;
min-width: 280px;
height: 420px;
}
.weather-visual {
width: 110px;
height: 110px;
}
.temperature {
font-size: 36px;
}
.weather-name {
font-size: 17px;
}
}
</style>
</head>
<body>
<!-- 背景层 -->
<div class="bg-layer">
<div class="bg-gradient"></div>
<div class="bg-dots"></div>
</div>
<!-- 主容器 -->
<div class="main-container" id="mainContainer">
<!-- ===== 晴天卡片 ===== -->
<div class="weather-card card-sunny" data-weather="sunny" id="cardSunny">
<div class="close-btn" onclick="event.stopPropagation(); collapseCard('cardSunny')"></div>
<div class="card-inner">
<div class="weather-visual" id="sunnyVisual">
<div class="sun-container" id="sunContainer">
<div class="sun-core"></div>
</div>
</div>
<div class="weather-icon-label">☀️</div>
<div class="weather-name">晴天</div>
<div class="temperature">28<span class="temp-unit">°C</span></div>
<div class="weather-desc">阳光明媚 · 温暖舒适</div>
<div class="details-panel">
<div class="detail-item"><span class="detail-label">湿度</span><span class="detail-value">42%</span></div>
<div class="detail-item"><span class="detail-label">紫外线</span><span class="detail-value">强 ☀️</span></div>
<div class="detail-item"><span class="detail-label">体感</span><span class="detail-value">30°C</span></div>
<div class="detail-item"><span class="detail-label">能见度</span><span class="detail-value">16 km</span></div>
</div>
<span class="hint-text">轻点查看详情</span>
</div>
</div>
<!-- ===== 大风卡片 ===== -->
<div class="weather-card card-windy" data-weather="windy" id="cardWindy">
<div class="close-btn" onclick="event.stopPropagation(); collapseCard('cardWindy')"></div>
<div class="card-inner">
<div class="weather-visual" id="windyVisual">
<div class="wind-cloud"></div>
</div>
<div class="weather-icon-label">💨</div>
<div class="weather-name">大风</div>
<div class="temperature">18<span class="temp-unit">°C</span></div>
<div class="weather-desc">阵风强劲 · 注意防风</div>
<div class="details-panel">
<div class="detail-item"><span class="detail-label">风速</span><span class="detail-value">32 km/h</span></div>
<div class="detail-item"><span class="detail-label">阵风</span><span class="detail-value">55 km/h</span></div>
<div class="detail-item"><span class="detail-label">湿度</span><span class="detail-value">38%</span></div>
<div class="detail-item"><span class="detail-label">气压</span><span class="detail-value">1012 hPa</span></div>
</div>
<span class="hint-text">轻点查看详情</span>
</div>
</div>
<!-- ===== 暴雨卡片 ===== -->
<div class="weather-card card-rain" data-weather="rain" id="cardRain">
<div class="close-btn" onclick="event.stopPropagation(); collapseCard('cardRain')"></div>
<div class="card-inner">
<div class="weather-visual" id="rainVisual">
<div class="rain-cloud-group">
<div class="rain-cloud-dark"></div>
</div>
<div class="lightning-flash"></div>
</div>
<div class="weather-icon-label">⛈️</div>
<div class="weather-name">暴雨</div>
<div class="temperature">22<span class="temp-unit">°C</span></div>
<div class="weather-desc">雷电交加 · 倾盆大雨</div>
<div class="details-panel">
<div class="detail-item"><span class="detail-label">降水量</span><span class="detail-value">48 mm</span></div>
<div class="detail-item"><span class="detail-label">湿度</span><span class="detail-value">92%</span></div>
<div class="detail-item"><span class="detail-label">雷电</span><span class="detail-value">活跃 ⚡</span></div>
<div class="detail-item"><span class="detail-label">能见度</span><span class="detail-value">2.5 km</span></div>
</div>
<span class="hint-text">轻点查看详情</span>
</div>
</div>
<!-- ===== 暴雪卡片 ===== -->
<div class="weather-card card-snow" data-weather="snow" id="cardSnow">
<div class="close-btn" onclick="event.stopPropagation(); collapseCard('cardSnow')"></div>
<div class="card-inner">
<div class="weather-visual" id="snowVisual">
<div class="snow-cloud-group">
<div class="snow-cloud-light"></div>
</div>
</div>
<div class="weather-icon-label">❄️</div>
<div class="weather-name">暴雪</div>
<div class="temperature">-5<span class="temp-unit">°C</span></div>
<div class="weather-desc">大雪纷飞 · 天寒地冻</div>
<div class="details-panel">
<div class="detail-item"><span class="detail-label">降雪量</span><span class="detail-value">25 cm</span></div>
<div class="detail-item"><span class="detail-label">湿度</span><span class="detail-value">78%</span></div>
<div class="detail-item"><span class="detail-label">体感</span><span class="detail-value">-12°C</span></div>
<div class="detail-item"><span class="detail-label">能见度</span><span class="detail-value">0.8 km</span></div>
</div>
<span class="hint-text">轻点查看详情</span>
</div>
</div>
</div>
<script>
(function() {
// ==================== 晴天:太阳光线 + 光点粒子 ====================
const sunContainer = document.getElementById('sunContainer');
if (sunContainer) {
// 创建12条光线
for (let i = 0; i < 12; i++) {
const ray = document.createElement('div');
ray.className = 'sun-ray';
const angle = i * 30;
ray.style.transform = `translate(-50%, -100%) rotate(${angle}deg)`;
ray.style.animationDelay = `${i * 0.25}s`;
sunContainer.appendChild(ray);
}
// 创建光点粒子
const sunnyVisual = document.getElementById('sunnyVisual');
for (let i = 0; i < 22; i++) {
const particle = document.createElement('div');
particle.className = 'light-particle';
const size = Math.random() * 5 + 2.5;
particle.style.width = size + 'px';
particle.style.height = size + 'px';
particle.style.left = (Math.random() * 120 + 20) + 'px';
particle.style.top = (Math.random() * 100 + 50) + 'px';
particle.style.animationDuration = (Math.random() * 3 + 2.5) + 's';
particle.style.animationDelay = (Math.random() * 4) + 's';
particle.style.opacity = Math.random() * 0.5 + 0.3;
sunnyVisual.appendChild(particle);
}
}
// ==================== 大风:风线条 ====================
const windyVisual = document.getElementById('windyVisual');
if (windyVisual) {
for (let i = 0; i < 8; i++) {
const streak = document.createElement('div');
streak.className = 'wind-streak';
const width = Math.random() * 50 + 35;
streak.style.width = width + 'px';
streak.style.top = (Math.random() * 110 + 15) + 'px';
streak.style.left = (Math.random() * 40 + 10) + 'px';
streak.style.animationDuration = (Math.random() * 2 + 2.2) + 's';
streak.style.animationDelay = (Math.random() * 3) + 's';
streak.style.height = (Math.random() * 2 + 1.5) + 'px';
windyVisual.appendChild(streak);
}
// 额外飘浮小点
for (let i = 0; i < 10; i++) {
const dot = document.createElement('div');
dot.style.cssText = `
position: absolute;
border-radius: 50%;
background: rgba(180,200,215,0.7);
pointer-events: none;
z-index: 1;
width: ${Math.random()*4+2}px;
height: ${Math.random()*4+2}px;
top: ${Math.random()*120+10}px;
left: ${Math.random()*100+30}px;
animation: windBlow ${Math.random()*2.5+2}s linear infinite;
animation-delay: ${Math.random()*3}s;
`;
windyVisual.appendChild(dot);
}
}
// ==================== 暴雨:雨滴粒子 ====================
const rainVisual = document.getElementById('rainVisual');
if (rainVisual) {
for (let i = 0; i < 80; i++) {
const drop = document.createElement('div');
drop.className = 'raindrop';
const h = Math.random() * 18 + 8;
drop.style.height = h + 'px';
drop.style.width = (Math.random() * 1.5 + 1) + 'px';
drop.style.left = (Math.random() * 140 - 10) + 'px';
drop.style.top = (Math.random() * 40 - 30) + 'px';
drop.style.animationDuration = (Math.random() * 0.7 + 0.4) + 's';
drop.style.animationDelay = (Math.random() * 1.5) + 's';
drop.style.opacity = Math.random() * 0.5 + 0.4;
rainVisual.appendChild(drop);
}
}
// ==================== 暴雪:雪花粒子 ====================
const snowVisual = document.getElementById('snowVisual');
if (snowVisual) {
for (let i = 0; i < 55; i++) {
const flake = document.createElement('div');
flake.className = 'snowflake';
const size = Math.random() * 7 + 3;
flake.style.width = size + 'px';
flake.style.height = size + 'px';
flake.style.left = (Math.random() * 140 - 10) + 'px';
flake.style.top = (Math.random() * 50 - 40) + 'px';
flake.style.animationDuration = (Math.random() * 4 + 3.5) + 's';
flake.style.animationDelay = (Math.random() * 5) + 's';
flake.style.opacity = Math.random() * 0.5 + 0.5;
snowVisual.appendChild(flake);
}
}
// ==================== 卡片点击展开/折叠逻辑 ====================
let currentlyExpanded = null;
const allCardIds = ['cardSunny', 'cardWindy', 'cardRain', 'cardSnow'];
function expandCard(cardId) {
// 如果已展开同一张卡片,则折叠
if (currentlyExpanded === cardId) {
collapseCard(cardId);
return;
}
// 先折叠当前展开的
if (currentlyExpanded) {
collapseCard(currentlyExpanded);
}
const card = document.getElementById(cardId);
if (!card) return;
card.classList.add('expanded');
currentlyExpanded = cardId;
// 其他卡片轻微缩放
allCardIds.forEach(id => {
if (id !== cardId) {
const other = document.getElementById(id);
if (other) {
other.style.transform = 'scale(0.94)';
other.style.opacity = '0.7';
other.style.filter = 'blur(1.5px)';
other.style.transition = 'all 0.5s cubic-bezier(0.25, 0.1, 0.1, 1.0)';
}
}
});
}
function collapseCard(cardId) {
const card = document.getElementById(cardId);
if (!card) return;
card.classList.remove('expanded');
if (currentlyExpanded === cardId) {
currentlyExpanded = null;
}
// 恢复其他卡片
allCardIds.forEach(id => {
const other = document.getElementById(id);
if (other) {
other.style.transform = '';
other.style.opacity = '';
other.style.filter = '';
other.style.transition = '';
}
});
}
// 为每张卡片绑定点击事件
allCardIds.forEach(cardId => {
const card = document.getElementById(cardId);
if (card) {
card.addEventListener('click', function(e) {
// 如果点击的是关闭按钮,不处理
if (e.target.closest('.close-btn')) return;
expandCard(cardId);
});
}
});
// 点击背景空白处折叠
document.getElementById('mainContainer').addEventListener('click', function(e) {
if (e.target === this && currentlyExpanded) {
collapseCard(currentlyExpanded);
}
});
// ESC 键折叠
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape' && currentlyExpanded) {
collapseCard(currentlyExpanded);
}
});
// ==================== 鼠标移动3D微倾效果 ====================
const allCards = document.querySelectorAll('.weather-card');
allCards.forEach(card => {
card.addEventListener('mousemove', function(e) {
if (card.classList.contains('expanded')) return; // 展开时不倾斜
const rect = card.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
const centerX = rect.width / 2;
const centerY = rect.height / 2;
const rotateX = ((y - centerY) / centerY) * -8;
const rotateY = ((x - centerX) / centerX) * 8;
card.style.transform =
`translateY(-10px) scale(1.04) perspective(600px) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`;
});
card.addEventListener('mouseleave', function() {
if (card.classList.contains('expanded')) return;
card.style.transform = '';
});
});
console.log('🌤️ iOS 18 风格天气卡片已就绪');
console.log(' ☀️ 晴天 · 💨 大风 · ⛈️ 暴雨 · ❄️ 暴雪');
console.log(' 👆 点击卡片查看详细天气数据');
console.log(' ⌨️ 按 ESC 键折叠展开的卡片');
})();
</script>
</body>
</html>
网友解答:
--【壹】--:
反转了,其实是ds蒸馏了claude 蒸馏 ds 的数据
--【贰】--:
说实话,感觉有点拉了,在目前的这个价格下
期待下下半年降价吧
--【叁】--:
《我是Claude》
image1920×1032 60.9 KB
--【肆】--:
感觉效果中规中矩 不知道在 coding 上表现如何 我随便试了试感觉挺好的
image1920×1032 87 KB
<!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 {
--sunny-primary: #FF9F43;
--sunny-secondary: #FECA57;
--sunny-bg: #FFF3E0;
--sunny-glow: rgba(255, 159, 67, 0.45);
--windy-primary: #5F9EA0;
--windy-secondary: #87CEEB;
--windy-bg: #E8F4F8;
--windy-glow: rgba(95, 158, 160, 0.4);
--rain-primary: #4A6FA5;
--rain-secondary: #6B8FBD;
--rain-bg: #1A1D2E;
--rain-glow: rgba(74, 111, 165, 0.5);
--snow-primary: #B0C4DE;
--snow-secondary: #E8F0FE;
--snow-bg: #DCE9F5;
--snow-glow: rgba(176, 196, 222, 0.55);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'SF Pro Text', 'Helvetica Neue', 'PingFang SC', 'Noto Sans SC', sans-serif;
background: #0A0A0F;
overflow-x: hidden;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
user-select: none;
-webkit-user-select: none;
-webkit-tap-highlight-color: transparent;
}
/* 动态网格背景 */
.bg-layer {
position: fixed;
inset: 0;
z-index: 0;
pointer-events: none;
}
.bg-gradient {
position: absolute;
inset: 0;
background:
radial-gradient(ellipse at 15% 50%, rgba(255, 159, 67, 0.18) 0%, transparent 55%),
radial-gradient(ellipse at 40% 30%, rgba(95, 158, 160, 0.14) 0%, transparent 50%),
radial-gradient(ellipse at 65% 60%, rgba(74, 111, 165, 0.2) 0%, transparent 55%),
radial-gradient(ellipse at 85% 35%, rgba(176, 196, 222, 0.16) 0%, transparent 50%),
radial-gradient(ellipse at 50% 80%, rgba(120, 130, 180, 0.08) 0%, transparent 60%);
animation: bgShift 18s ease-in-out infinite;
}
.bg-dots {
position: absolute;
inset: 0;
background-image: radial-gradient(rgba(255, 255, 255, 0.04) 1px, transparent 1px);
background-size: 40px 40px;
mask-image: radial-gradient(ellipse at center, black 30%, transparent 70%);
-webkit-mask-image: radial-gradient(ellipse at center, black 30%, transparent 70%);
}
@keyframes bgShift {
0%,
100% {
opacity: 0.85;
}
25% {
opacity: 1;
}
50% {
opacity: 0.9;
}
75% {
opacity: 0.8;
}
}
/* 主容器 */
.main-container {
position: relative;
z-index: 1;
display: flex;
gap: 20px;
padding: 30px;
flex-wrap: nowrap;
justify-content: center;
align-items: stretch;
perspective: 1200px;
max-width: 1300px;
width: 100%;
}
/* ========== 卡片基础样式 ========== */
.weather-card {
position: relative;
width: 275px;
min-width: 275px;
height: 430px;
border-radius: 28px;
cursor: pointer;
transition: all 0.55s cubic-bezier(0.25, 0.1, 0.1, 1.0);
overflow: hidden;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
backdrop-filter: blur(28px);
-webkit-backdrop-filter: blur(28px);
border: 1.2px solid rgba(255, 255, 255, 0.22);
box-shadow:
0 8px 32px rgba(0, 0, 0, 0.25),
0 2px 8px rgba(0, 0, 0, 0.15),
inset 0 1px 0 rgba(255, 255, 255, 0.12);
z-index: 1;
flex-shrink: 0;
}
.weather-card::before {
content: '';
position: absolute;
inset: 0;
border-radius: 28px;
background: linear-gradient(160deg,
rgba(255, 255, 255, 0.18) 0%,
rgba(255, 255, 255, 0.04) 40%,
rgba(255, 255, 255, 0.0) 60%,
rgba(255, 255, 255, 0.06) 100%);
pointer-events: none;
z-index: 0;
transition: opacity 0.5s;
}
.weather-card::after {
content: '';
position: absolute;
inset: 8px;
border-radius: 22px;
border: 1px solid rgba(255, 255, 255, 0.08);
pointer-events: none;
z-index: 0;
transition: border-color 0.5s;
}
.weather-card:hover {
transform: translateY(-10px) scale(1.04);
box-shadow:
0 22px 48px rgba(0, 0, 0, 0.35),
0 6px 16px rgba(0, 0, 0, 0.2),
inset 0 1px 0 rgba(255, 255, 255, 0.18);
z-index: 10;
border-color: rgba(255, 255, 255, 0.38);
}
.weather-card:hover::after {
border-color: rgba(255, 255, 255, 0.16);
}
.weather-card.expanded {
width: 380px;
min-width: 380px;
height: 510px;
z-index: 20;
border-color: rgba(255, 255, 255, 0.42);
box-shadow:
0 28px 60px rgba(0, 0, 0, 0.45),
0 10px 24px rgba(0, 0, 0, 0.25),
inset 0 1px 0 rgba(255, 255, 255, 0.22);
}
/* 卡片内容层级 */
.card-inner {
position: relative;
z-index: 2;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
padding: 28px 20px 20px;
pointer-events: none;
}
/* ========== 天气动画区域 ========== */
.weather-visual {
position: relative;
width: 160px;
height: 150px;
flex-shrink: 0;
margin-bottom: 8px;
pointer-events: none;
overflow: visible;
}
/* ========== 各天气类型背景色 ========== */
.card-sunny {
background: rgba(255, 180, 100, 0.22);
}
.card-windy {
background: rgba(140, 190, 200, 0.2);
}
.card-rain {
background: rgba(30, 40, 70, 0.45);
}
.card-snow {
background: rgba(200, 215, 235, 0.28);
}
/* ========== 晴天 - 太阳 ========== */
.sun-container {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 80px;
height: 80px;
}
.sun-core {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 56px;
height: 56px;
border-radius: 50%;
background: radial-gradient(circle at 40% 35%, #FFE082 0%, #FFB74D 40%, #F57C00 100%);
box-shadow:
0 0 50px rgba(255, 170, 50, 0.7),
0 0 100px rgba(255, 150, 30, 0.4),
0 0 160px rgba(255, 140, 20, 0.2);
animation: sunPulse 3s ease-in-out infinite;
z-index: 3;
}
@keyframes sunPulse {
0%,
100% {
box-shadow: 0 0 50px rgba(255, 170, 50, 0.7), 0 0 100px rgba(255, 150, 30, 0.4), 0 0 160px rgba(255, 140, 20, 0.2);
}
50% {
box-shadow: 0 0 65px rgba(255, 180, 60, 0.9), 0 0 120px rgba(255, 160, 40, 0.55), 0 0 190px rgba(255, 150, 30, 0.3);
}
}
.sun-ray {
position: absolute;
top: 50%;
left: 50%;
width: 4px;
height: 28px;
background: linear-gradient(to bottom, rgba(255, 200, 80, 0.85), rgba(255, 160, 40, 0));
border-radius: 2px;
transform-origin: bottom center;
animation: rayRotate 12s linear infinite;
}
@keyframes rayRotate {
from {
transform: translate(-50%, -100%) rotate(0deg);
}
to {
transform: translate(-50%, -100%) rotate(360deg);
}
}
.sun-ray:nth-child(odd) {
height: 20px;
animation-duration: 8s;
animation-direction: reverse;
opacity: 0.7;
}
/* 晴天光点 */
.light-particle {
position: absolute;
border-radius: 50%;
background: rgba(255, 220, 120, 0.9);
pointer-events: none;
z-index: 2;
animation: floatUp linear infinite;
box-shadow: 0 0 6px rgba(255, 200, 80, 0.6);
}
@keyframes floatUp {
0% {
transform: translateY(0) translateX(0) scale(1);
opacity: 0;
}
10% {
opacity: 1;
}
80% {
opacity: 0.5;
}
100% {
transform: translateY(-140px) translateX(25px) scale(0.2);
opacity: 0;
}
}
/* ========== 大风 - 云和风线 ========== */
.wind-cloud {
position: absolute;
top: 35px;
left: 50%;
transform: translateX(-50%);
width: 90px;
height: 45px;
background: rgba(220, 230, 240, 0.85);
border-radius: 50px;
box-shadow: 0 4px 20px rgba(150, 180, 200, 0.3);
animation: cloudDrift 5s ease-in-out infinite;
z-index: 2;
}
.wind-cloud::before {
content: '';
position: absolute;
top: -22px;
left: 15px;
width: 44px;
height: 44px;
background: rgba(220, 230, 240, 0.85);
border-radius: 50%;
}
.wind-cloud::after {
content: '';
position: absolute;
top: -14px;
right: 15px;
width: 36px;
height: 36px;
background: rgba(220, 230, 240, 0.85);
border-radius: 50%;
}
@keyframes cloudDrift {
0%,
100% {
transform: translateX(-50%) translateX(-8px);
}
50% {
transform: translateX(-50%) translateX(8px);
}
}
.wind-streak {
position: absolute;
height: 2.5px;
background: linear-gradient(to right, transparent, rgba(180, 200, 220, 0.7), rgba(200, 215, 230, 0.9), rgba(180, 200, 220, 0.5), transparent);
border-radius: 2px;
z-index: 1;
animation: windBlow linear infinite;
opacity: 0;
}
@keyframes windBlow {
0% {
transform: translateX(-60px);
opacity: 0;
}
15% {
opacity: 0.8;
}
70% {
opacity: 0.4;
}
100% {
transform: translateX(120px);
opacity: 0;
}
}
/* ========== 暴雨 - 云和雨滴 ========== */
.rain-cloud-group {
position: absolute;
top: 20px;
left: 50%;
transform: translateX(-50%);
z-index: 3;
}
.rain-cloud-dark {
position: relative;
width: 100px;
height: 42px;
background: rgba(60, 70, 95, 0.9);
border-radius: 50px;
box-shadow: 0 6px 25px rgba(30, 35, 55, 0.5);
}
.rain-cloud-dark::before {
content: '';
position: absolute;
top: -24px;
left: 18px;
width: 48px;
height: 48px;
background: rgba(60, 70, 95, 0.9);
border-radius: 50%;
}
.rain-cloud-dark::after {
content: '';
position: absolute;
top: -16px;
right: 16px;
width: 38px;
height: 38px;
background: rgba(60, 70, 95, 0.9);
border-radius: 50%;
}
.lightning-flash {
position: absolute;
top: 55px;
left: 50%;
transform: translateX(-50%);
width: 3px;
height: 40px;
background: rgba(255, 255, 200, 0.9);
border-radius: 2px;
z-index: 2;
opacity: 0;
box-shadow: 0 0 20px rgba(255, 255, 180, 0.8), 0 0 40px rgba(255, 250, 200, 0.4);
animation: lightningBolt 6s ease-in-out infinite;
}
@keyframes lightningBolt {
0%,
92%,
96%,
100% {
opacity: 0;
}
93% {
opacity: 1;
box-shadow: 0 0 30px rgba(255, 255, 200, 1), 0 0 60px rgba(255, 250, 200, 0.7);
}
94% {
opacity: 0.3;
}
95% {
opacity: 0.9;
box-shadow: 0 0 25px rgba(255, 255, 200, 0.9), 0 0 50px rgba(255, 250, 200, 0.5);
}
}
.raindrop {
position: absolute;
width: 2px;
background: linear-gradient(to bottom, rgba(180, 200, 230, 0.1), rgba(160, 190, 225, 0.8));
border-radius: 0 0 2px 2px;
z-index: 2;
pointer-events: none;
animation: rainFall linear infinite;
}
@keyframes rainFall {
0% {
transform: translateY(-80px);
opacity: 0;
}
8% {
opacity: 1;
}
85% {
opacity: 0.5;
}
100% {
transform: translateY(160px);
opacity: 0;
}
}
/* ========== 暴雪 - 云和雪花 ========== */
.snow-cloud-group {
position: absolute;
top: 22px;
left: 50%;
transform: translateX(-50%);
z-index: 3;
}
.snow-cloud-light {
position: relative;
width: 95px;
height: 40px;
background: rgba(210, 220, 235, 0.9);
border-radius: 50px;
box-shadow: 0 4px 18px rgba(160, 180, 200, 0.4);
}
.snow-cloud-light::before {
content: '';
position: absolute;
top: -22px;
left: 16px;
width: 46px;
height: 46px;
background: rgba(210, 220, 235, 0.9);
border-radius: 50%;
}
.snow-cloud-light::after {
content: '';
position: absolute;
top: -14px;
right: 18px;
width: 36px;
height: 36px;
background: rgba(210, 220, 235, 0.9);
border-radius: 50%;
}
.snowflake {
position: absolute;
border-radius: 50%;
background: rgba(255, 255, 255, 0.9);
z-index: 2;
pointer-events: none;
animation: snowDrift linear infinite;
box-shadow: 0 0 4px rgba(255, 255, 255, 0.5);
}
@keyframes snowDrift {
0% {
transform: translateY(-60px) translateX(0px) rotate(0deg);
opacity: 0;
}
10% {
opacity: 0.9;
}
50% {
transform: translateY(50px) translateX(20px) rotate(180deg);
}
90% {
opacity: 0.6;
}
100% {
transform: translateY(150px) translateX(-15px) rotate(360deg);
opacity: 0;
}
}
/* ========== 文字信息区域 ========== */
.weather-icon-label {
font-size: 36px;
margin-top: 8px;
pointer-events: none;
line-height: 1;
filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.15));
z-index: 3;
position: relative;
}
.weather-name {
font-size: 20px;
font-weight: 600;
letter-spacing: 0.3px;
margin-top: 4px;
pointer-events: none;
z-index: 3;
position: relative;
}
.temperature {
font-size: 52px;
font-weight: 200;
letter-spacing: -2px;
line-height: 1;
margin-top: 4px;
pointer-events: none;
z-index: 3;
position: relative;
}
.temp-unit {
font-size: 22px;
font-weight: 300;
vertical-align: super;
letter-spacing: 0;
}
.weather-desc {
font-size: 13px;
font-weight: 400;
opacity: 0.7;
letter-spacing: 0.2px;
margin-top: 2px;
pointer-events: none;
z-index: 3;
position: relative;
}
/* ========== 展开详情 ========== */
.details-panel {
position: relative;
z-index: 3;
width: 100%;
padding: 0 16px;
margin-top: 6px;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px 14px;
opacity: 0;
transform: translateY(12px);
transition: all 0.45s cubic-bezier(0.25, 0.1, 0.1, 1.0);
pointer-events: none;
max-height: 0;
overflow: hidden;
}
.weather-card.expanded .details-panel {
opacity: 1;
transform: translateY(0);
max-height: 200px;
pointer-events: auto;
}
.detail-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 2px;
padding: 8px 6px;
border-radius: 14px;
background: rgba(255, 255, 255, 0.08);
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
border: 1px solid rgba(255, 255, 255, 0.1);
transition: background 0.3s;
}
.detail-label {
font-size: 10px;
font-weight: 500;
text-transform: uppercase;
letter-spacing: 0.5px;
opacity: 0.6;
}
.detail-value {
font-size: 16px;
font-weight: 500;
letter-spacing: -0.3px;
}
/* ========== 各卡片文字颜色 ========== */
.card-sunny .weather-name,
.card-sunny .temperature,
.card-sunny .weather-desc,
.card-sunny .detail-label,
.card-sunny .detail-value {
color: #5D3A1A;
}
.card-windy .weather-name,
.card-windy .temperature,
.card-windy .weather-desc,
.card-windy .detail-label,
.card-windy .detail-value {
color: #2C4A4E;
}
.card-rain .weather-name,
.card-rain .temperature,
.card-rain .weather-desc,
.card-rain .detail-label,
.card-rain .detail-value {
color: #D5E0F0;
}
.card-snow .weather-name,
.card-snow .temperature,
.card-snow .weather-desc,
.card-snow .detail-label,
.card-snow .detail-value {
color: #3A4A5C;
}
/* 雨天文字发光 */
.card-rain .temperature {
text-shadow: 0 0 30px rgba(200, 215, 235, 0.5);
}
/* ========== 提示文字 ========== */
.hint-text {
position: relative;
z-index: 3;
font-size: 11px;
opacity: 0.45;
margin-top: auto;
pointer-events: none;
transition: opacity 0.4s;
letter-spacing: 0.3px;
}
.weather-card.expanded .hint-text {
opacity: 0;
}
/* ========== 关闭按钮 ========== */
.close-btn {
position: absolute;
top: 14px;
right: 16px;
z-index: 30;
width: 30px;
height: 30px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.15);
border: 1px solid rgba(255, 255, 255, 0.25);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transform: scale(0.6);
transition: all 0.35s cubic-bezier(0.25, 0.1, 0.1, 1.0);
pointer-events: none;
backdrop-filter: blur(6px);
-webkit-backdrop-filter: blur(6px);
}
.close-btn::before,
.close-btn::after {
content: '';
position: absolute;
width: 13px;
height: 1.5px;
background: rgba(255, 255, 255, 0.8);
border-radius: 1px;
}
.close-btn::before {
transform: rotate(45deg);
}
.close-btn::after {
transform: rotate(-45deg);
}
.weather-card.expanded .close-btn {
opacity: 1;
transform: scale(1);
pointer-events: auto;
}
.close-btn:hover {
background: rgba(255, 255, 255, 0.28);
border-color: rgba(255, 255, 255, 0.45);
transform: scale(1.1);
}
.card-rain .close-btn::before,
.card-rain .close-btn::after {
background: rgba(220, 225, 240, 0.9);
}
/* ========== 响应式 ========== */
@media (max-width: 1200px) {
.main-container {
gap: 14px;
padding: 20px;
overflow-x: auto;
scroll-snap-type: x mandatory;
-webkit-overflow-scrolling: touch;
justify-content: flex-start;
padding-left: calc(50% - 140px);
scroll-padding-left: calc(50% - 140px);
}
.weather-card {
scroll-snap-align: center;
width: 250px;
min-width: 250px;
height: 400px;
border-radius: 24px;
}
.weather-card.expanded {
width: 320px;
min-width: 320px;
height: 470px;
}
.weather-visual {
width: 130px;
height: 130px;
}
.temperature {
font-size: 42px;
}
.main-container::-webkit-scrollbar {
height: 0;
}
}
@media (max-width: 600px) {
.main-container {
gap: 10px;
padding: 16px;
padding-left: calc(50% - 125px);
scroll-padding-left: calc(50% - 125px);
}
.weather-card {
width: 220px;
min-width: 220px;
height: 360px;
border-radius: 22px;
}
.weather-card.expanded {
width: 280px;
min-width: 280px;
height: 420px;
}
.weather-visual {
width: 110px;
height: 110px;
}
.temperature {
font-size: 36px;
}
.weather-name {
font-size: 17px;
}
}
</style>
</head>
<body>
<!-- 背景层 -->
<div class="bg-layer">
<div class="bg-gradient"></div>
<div class="bg-dots"></div>
</div>
<!-- 主容器 -->
<div class="main-container" id="mainContainer">
<!-- ===== 晴天卡片 ===== -->
<div class="weather-card card-sunny" data-weather="sunny" id="cardSunny">
<div class="close-btn" onclick="event.stopPropagation(); collapseCard('cardSunny')"></div>
<div class="card-inner">
<div class="weather-visual" id="sunnyVisual">
<div class="sun-container" id="sunContainer">
<div class="sun-core"></div>
</div>
</div>
<div class="weather-icon-label">☀️</div>
<div class="weather-name">晴天</div>
<div class="temperature">28<span class="temp-unit">°C</span></div>
<div class="weather-desc">阳光明媚 · 温暖舒适</div>
<div class="details-panel">
<div class="detail-item"><span class="detail-label">湿度</span><span class="detail-value">42%</span></div>
<div class="detail-item"><span class="detail-label">紫外线</span><span class="detail-value">强 ☀️</span></div>
<div class="detail-item"><span class="detail-label">体感</span><span class="detail-value">30°C</span></div>
<div class="detail-item"><span class="detail-label">能见度</span><span class="detail-value">16 km</span></div>
</div>
<span class="hint-text">轻点查看详情</span>
</div>
</div>
<!-- ===== 大风卡片 ===== -->
<div class="weather-card card-windy" data-weather="windy" id="cardWindy">
<div class="close-btn" onclick="event.stopPropagation(); collapseCard('cardWindy')"></div>
<div class="card-inner">
<div class="weather-visual" id="windyVisual">
<div class="wind-cloud"></div>
</div>
<div class="weather-icon-label">💨</div>
<div class="weather-name">大风</div>
<div class="temperature">18<span class="temp-unit">°C</span></div>
<div class="weather-desc">阵风强劲 · 注意防风</div>
<div class="details-panel">
<div class="detail-item"><span class="detail-label">风速</span><span class="detail-value">32 km/h</span></div>
<div class="detail-item"><span class="detail-label">阵风</span><span class="detail-value">55 km/h</span></div>
<div class="detail-item"><span class="detail-label">湿度</span><span class="detail-value">38%</span></div>
<div class="detail-item"><span class="detail-label">气压</span><span class="detail-value">1012 hPa</span></div>
</div>
<span class="hint-text">轻点查看详情</span>
</div>
</div>
<!-- ===== 暴雨卡片 ===== -->
<div class="weather-card card-rain" data-weather="rain" id="cardRain">
<div class="close-btn" onclick="event.stopPropagation(); collapseCard('cardRain')"></div>
<div class="card-inner">
<div class="weather-visual" id="rainVisual">
<div class="rain-cloud-group">
<div class="rain-cloud-dark"></div>
</div>
<div class="lightning-flash"></div>
</div>
<div class="weather-icon-label">⛈️</div>
<div class="weather-name">暴雨</div>
<div class="temperature">22<span class="temp-unit">°C</span></div>
<div class="weather-desc">雷电交加 · 倾盆大雨</div>
<div class="details-panel">
<div class="detail-item"><span class="detail-label">降水量</span><span class="detail-value">48 mm</span></div>
<div class="detail-item"><span class="detail-label">湿度</span><span class="detail-value">92%</span></div>
<div class="detail-item"><span class="detail-label">雷电</span><span class="detail-value">活跃 ⚡</span></div>
<div class="detail-item"><span class="detail-label">能见度</span><span class="detail-value">2.5 km</span></div>
</div>
<span class="hint-text">轻点查看详情</span>
</div>
</div>
<!-- ===== 暴雪卡片 ===== -->
<div class="weather-card card-snow" data-weather="snow" id="cardSnow">
<div class="close-btn" onclick="event.stopPropagation(); collapseCard('cardSnow')"></div>
<div class="card-inner">
<div class="weather-visual" id="snowVisual">
<div class="snow-cloud-group">
<div class="snow-cloud-light"></div>
</div>
</div>
<div class="weather-icon-label">❄️</div>
<div class="weather-name">暴雪</div>
<div class="temperature">-5<span class="temp-unit">°C</span></div>
<div class="weather-desc">大雪纷飞 · 天寒地冻</div>
<div class="details-panel">
<div class="detail-item"><span class="detail-label">降雪量</span><span class="detail-value">25 cm</span></div>
<div class="detail-item"><span class="detail-label">湿度</span><span class="detail-value">78%</span></div>
<div class="detail-item"><span class="detail-label">体感</span><span class="detail-value">-12°C</span></div>
<div class="detail-item"><span class="detail-label">能见度</span><span class="detail-value">0.8 km</span></div>
</div>
<span class="hint-text">轻点查看详情</span>
</div>
</div>
</div>
<script>
(function() {
// ==================== 晴天:太阳光线 + 光点粒子 ====================
const sunContainer = document.getElementById('sunContainer');
if (sunContainer) {
// 创建12条光线
for (let i = 0; i < 12; i++) {
const ray = document.createElement('div');
ray.className = 'sun-ray';
const angle = i * 30;
ray.style.transform = `translate(-50%, -100%) rotate(${angle}deg)`;
ray.style.animationDelay = `${i * 0.25}s`;
sunContainer.appendChild(ray);
}
// 创建光点粒子
const sunnyVisual = document.getElementById('sunnyVisual');
for (let i = 0; i < 22; i++) {
const particle = document.createElement('div');
particle.className = 'light-particle';
const size = Math.random() * 5 + 2.5;
particle.style.width = size + 'px';
particle.style.height = size + 'px';
particle.style.left = (Math.random() * 120 + 20) + 'px';
particle.style.top = (Math.random() * 100 + 50) + 'px';
particle.style.animationDuration = (Math.random() * 3 + 2.5) + 's';
particle.style.animationDelay = (Math.random() * 4) + 's';
particle.style.opacity = Math.random() * 0.5 + 0.3;
sunnyVisual.appendChild(particle);
}
}
// ==================== 大风:风线条 ====================
const windyVisual = document.getElementById('windyVisual');
if (windyVisual) {
for (let i = 0; i < 8; i++) {
const streak = document.createElement('div');
streak.className = 'wind-streak';
const width = Math.random() * 50 + 35;
streak.style.width = width + 'px';
streak.style.top = (Math.random() * 110 + 15) + 'px';
streak.style.left = (Math.random() * 40 + 10) + 'px';
streak.style.animationDuration = (Math.random() * 2 + 2.2) + 's';
streak.style.animationDelay = (Math.random() * 3) + 's';
streak.style.height = (Math.random() * 2 + 1.5) + 'px';
windyVisual.appendChild(streak);
}
// 额外飘浮小点
for (let i = 0; i < 10; i++) {
const dot = document.createElement('div');
dot.style.cssText = `
position: absolute;
border-radius: 50%;
background: rgba(180,200,215,0.7);
pointer-events: none;
z-index: 1;
width: ${Math.random()*4+2}px;
height: ${Math.random()*4+2}px;
top: ${Math.random()*120+10}px;
left: ${Math.random()*100+30}px;
animation: windBlow ${Math.random()*2.5+2}s linear infinite;
animation-delay: ${Math.random()*3}s;
`;
windyVisual.appendChild(dot);
}
}
// ==================== 暴雨:雨滴粒子 ====================
const rainVisual = document.getElementById('rainVisual');
if (rainVisual) {
for (let i = 0; i < 80; i++) {
const drop = document.createElement('div');
drop.className = 'raindrop';
const h = Math.random() * 18 + 8;
drop.style.height = h + 'px';
drop.style.width = (Math.random() * 1.5 + 1) + 'px';
drop.style.left = (Math.random() * 140 - 10) + 'px';
drop.style.top = (Math.random() * 40 - 30) + 'px';
drop.style.animationDuration = (Math.random() * 0.7 + 0.4) + 's';
drop.style.animationDelay = (Math.random() * 1.5) + 's';
drop.style.opacity = Math.random() * 0.5 + 0.4;
rainVisual.appendChild(drop);
}
}
// ==================== 暴雪:雪花粒子 ====================
const snowVisual = document.getElementById('snowVisual');
if (snowVisual) {
for (let i = 0; i < 55; i++) {
const flake = document.createElement('div');
flake.className = 'snowflake';
const size = Math.random() * 7 + 3;
flake.style.width = size + 'px';
flake.style.height = size + 'px';
flake.style.left = (Math.random() * 140 - 10) + 'px';
flake.style.top = (Math.random() * 50 - 40) + 'px';
flake.style.animationDuration = (Math.random() * 4 + 3.5) + 's';
flake.style.animationDelay = (Math.random() * 5) + 's';
flake.style.opacity = Math.random() * 0.5 + 0.5;
snowVisual.appendChild(flake);
}
}
// ==================== 卡片点击展开/折叠逻辑 ====================
let currentlyExpanded = null;
const allCardIds = ['cardSunny', 'cardWindy', 'cardRain', 'cardSnow'];
function expandCard(cardId) {
// 如果已展开同一张卡片,则折叠
if (currentlyExpanded === cardId) {
collapseCard(cardId);
return;
}
// 先折叠当前展开的
if (currentlyExpanded) {
collapseCard(currentlyExpanded);
}
const card = document.getElementById(cardId);
if (!card) return;
card.classList.add('expanded');
currentlyExpanded = cardId;
// 其他卡片轻微缩放
allCardIds.forEach(id => {
if (id !== cardId) {
const other = document.getElementById(id);
if (other) {
other.style.transform = 'scale(0.94)';
other.style.opacity = '0.7';
other.style.filter = 'blur(1.5px)';
other.style.transition = 'all 0.5s cubic-bezier(0.25, 0.1, 0.1, 1.0)';
}
}
});
}
function collapseCard(cardId) {
const card = document.getElementById(cardId);
if (!card) return;
card.classList.remove('expanded');
if (currentlyExpanded === cardId) {
currentlyExpanded = null;
}
// 恢复其他卡片
allCardIds.forEach(id => {
const other = document.getElementById(id);
if (other) {
other.style.transform = '';
other.style.opacity = '';
other.style.filter = '';
other.style.transition = '';
}
});
}
// 为每张卡片绑定点击事件
allCardIds.forEach(cardId => {
const card = document.getElementById(cardId);
if (card) {
card.addEventListener('click', function(e) {
// 如果点击的是关闭按钮,不处理
if (e.target.closest('.close-btn')) return;
expandCard(cardId);
});
}
});
// 点击背景空白处折叠
document.getElementById('mainContainer').addEventListener('click', function(e) {
if (e.target === this && currentlyExpanded) {
collapseCard(currentlyExpanded);
}
});
// ESC 键折叠
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape' && currentlyExpanded) {
collapseCard(currentlyExpanded);
}
});
// ==================== 鼠标移动3D微倾效果 ====================
const allCards = document.querySelectorAll('.weather-card');
allCards.forEach(card => {
card.addEventListener('mousemove', function(e) {
if (card.classList.contains('expanded')) return; // 展开时不倾斜
const rect = card.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
const centerX = rect.width / 2;
const centerY = rect.height / 2;
const rotateX = ((y - centerY) / centerY) * -8;
const rotateY = ((x - centerX) / centerX) * 8;
card.style.transform =
`translateY(-10px) scale(1.04) perspective(600px) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`;
});
card.addEventListener('mouseleave', function() {
if (card.classList.contains('expanded')) return;
card.style.transform = '';
});
});
console.log('🌤️ iOS 18 风格天气卡片已就绪');
console.log(' ☀️ 晴天 · 💨 大风 · ⛈️ 暴雨 · ❄️ 暴雪');
console.log(' 👆 点击卡片查看详细天气数据');
console.log(' ⌨️ 按 ESC 键折叠展开的卡片');
})();
</script>
</body>
</html>
网友解答:
--【壹】--:
反转了,其实是ds蒸馏了claude 蒸馏 ds 的数据
--【贰】--:
说实话,感觉有点拉了,在目前的这个价格下
期待下下半年降价吧
--【叁】--:
《我是Claude》
image1920×1032 60.9 KB
--【肆】--:
感觉效果中规中矩 不知道在 coding 上表现如何 我随便试了试感觉挺好的

