1303 lines
36 KiB
HTML
1303 lines
36 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>动画天气卡片</title>
|
||
<style>
|
||
* {
|
||
margin: 0;
|
||
padding: 0;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
/* 性能优化 */
|
||
.weather-card,
|
||
.weather-card * {
|
||
will-change: transform, opacity;
|
||
backface-visibility: hidden;
|
||
transform-style: preserve-3d;
|
||
}
|
||
|
||
/* 减少重绘 */
|
||
.wind-cloud,
|
||
.rain-drop,
|
||
.sun-ray,
|
||
.snowflake {
|
||
transform: translateZ(0);
|
||
}
|
||
|
||
body {
|
||
background: linear-gradient(135deg, #1e1e2e, #2d2d44);
|
||
background-attachment: fixed;
|
||
font-family: 'Arial', sans-serif;
|
||
min-height: 100vh;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
padding: 20px;
|
||
color: white;
|
||
overflow-x: hidden;
|
||
}
|
||
|
||
/* 添加背景动画 */
|
||
body::before {
|
||
content: '';
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
background:
|
||
radial-gradient(circle at 20% 80%, rgba(120, 119, 198, 0.1) 0%, transparent 50%),
|
||
radial-gradient(circle at 80% 20%, rgba(255, 119, 198, 0.1) 0%, transparent 50%),
|
||
radial-gradient(circle at 40% 40%, rgba(120, 219, 255, 0.1) 0%, transparent 50%);
|
||
animation: backgroundShift 20s infinite ease-in-out;
|
||
z-index: -1;
|
||
}
|
||
|
||
@keyframes backgroundShift {
|
||
0%, 100% {
|
||
opacity: 0.3;
|
||
transform: scale(1);
|
||
}
|
||
50% {
|
||
opacity: 0.5;
|
||
transform: scale(1.1);
|
||
}
|
||
}
|
||
|
||
.header {
|
||
text-align: center;
|
||
margin-bottom: 30px;
|
||
}
|
||
|
||
.header h1 {
|
||
font-size: 2.5rem;
|
||
margin-bottom: 10px;
|
||
background: linear-gradient(45deg, #ff6b6b, #4ecdc4, #45b7d1, #96ceb4);
|
||
-webkit-background-clip: text;
|
||
-webkit-text-fill-color: transparent;
|
||
background-clip: text;
|
||
}
|
||
|
||
.controls {
|
||
display: flex;
|
||
gap: 15px;
|
||
margin-bottom: 30px;
|
||
flex-wrap: wrap;
|
||
justify-content: center;
|
||
}
|
||
|
||
.control-btn {
|
||
padding: 12px 24px;
|
||
border: none;
|
||
border-radius: 25px;
|
||
background: linear-gradient(45deg, #667eea, #764ba2);
|
||
color: white;
|
||
font-size: 1rem;
|
||
cursor: pointer;
|
||
transition: all 0.3s ease;
|
||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
|
||
}
|
||
|
||
.control-btn:hover {
|
||
transform: translateY(-3px) scale(1.02);
|
||
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.4);
|
||
}
|
||
|
||
.control-btn:active {
|
||
transform: translateY(0) scale(0.98);
|
||
transition: all 0.1s ease;
|
||
}
|
||
|
||
.control-btn.active {
|
||
background: linear-gradient(45deg, #ff6b6b, #ee5a24);
|
||
transform: scale(1.05);
|
||
box-shadow: 0 8px 25px rgba(255, 107, 107, 0.4);
|
||
}
|
||
|
||
.control-btn.active:hover {
|
||
transform: translateY(-2px) scale(1.08);
|
||
box-shadow: 0 10px 30px rgba(255, 107, 107, 0.5);
|
||
}
|
||
|
||
.weather-container {
|
||
display: flex;
|
||
gap: 20px;
|
||
flex-wrap: wrap;
|
||
justify-content: center;
|
||
max-width: 1200px;
|
||
}
|
||
|
||
.weather-card {
|
||
width: 280px;
|
||
height: 350px;
|
||
border-radius: 20px;
|
||
position: relative;
|
||
overflow: hidden;
|
||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
|
||
transition: all 0.3s ease;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.weather-card:hover {
|
||
transform: translateY(-5px);
|
||
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.4);
|
||
}
|
||
|
||
.card-content {
|
||
position: absolute;
|
||
bottom: 20px;
|
||
left: 20px;
|
||
z-index: 10;
|
||
}
|
||
|
||
.weather-title {
|
||
font-size: 1.8rem;
|
||
font-weight: bold;
|
||
margin-bottom: 5px;
|
||
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
|
||
}
|
||
|
||
.weather-desc {
|
||
font-size: 1rem;
|
||
opacity: 0.9;
|
||
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
|
||
}
|
||
|
||
/* 风天气卡片样式 */
|
||
.wind-card {
|
||
background: linear-gradient(135deg, #74b9ff, #0984e3);
|
||
}
|
||
|
||
/* 风天气动画 */
|
||
.wind-animation {
|
||
position: absolute;
|
||
width: 100%;
|
||
height: 100%;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.wind-cloud {
|
||
position: absolute;
|
||
background: rgba(255, 255, 255, 0.8);
|
||
border-radius: 50px;
|
||
animation: windCloudMove 8s infinite linear;
|
||
}
|
||
|
||
.wind-cloud:before {
|
||
content: '';
|
||
position: absolute;
|
||
background: rgba(255, 255, 255, 0.8);
|
||
border-radius: 50px;
|
||
}
|
||
|
||
.wind-cloud1 {
|
||
width: 60px;
|
||
height: 30px;
|
||
top: 20%;
|
||
left: -80px;
|
||
animation-delay: 0s;
|
||
}
|
||
|
||
.wind-cloud1:before {
|
||
width: 40px;
|
||
height: 25px;
|
||
top: -10px;
|
||
left: 15px;
|
||
}
|
||
|
||
.wind-cloud2 {
|
||
width: 80px;
|
||
height: 40px;
|
||
top: 40%;
|
||
left: -100px;
|
||
animation-delay: -3s;
|
||
}
|
||
|
||
.wind-cloud2:before {
|
||
width: 50px;
|
||
height: 30px;
|
||
top: -15px;
|
||
left: 20px;
|
||
}
|
||
|
||
.wind-cloud3 {
|
||
width: 50px;
|
||
height: 25px;
|
||
top: 60%;
|
||
left: -70px;
|
||
animation-delay: -6s;
|
||
}
|
||
|
||
.wind-cloud3:before {
|
||
width: 35px;
|
||
height: 20px;
|
||
top: -8px;
|
||
left: 12px;
|
||
}
|
||
|
||
@keyframes windCloudMove {
|
||
0% {
|
||
transform: translateX(0);
|
||
}
|
||
100% {
|
||
transform: translateX(380px);
|
||
}
|
||
}
|
||
|
||
.wind-lines {
|
||
position: absolute;
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
|
||
.wind-line {
|
||
position: absolute;
|
||
background: rgba(255, 255, 255, 0.6);
|
||
height: 2px;
|
||
border-radius: 1px;
|
||
animation: windLineMove 3s infinite ease-in-out;
|
||
}
|
||
|
||
.wind-line1 {
|
||
width: 40px;
|
||
top: 25%;
|
||
left: 20px;
|
||
animation-delay: 0s;
|
||
}
|
||
|
||
.wind-line2 {
|
||
width: 60px;
|
||
top: 35%;
|
||
left: 30px;
|
||
animation-delay: -0.5s;
|
||
}
|
||
|
||
.wind-line3 {
|
||
width: 35px;
|
||
top: 45%;
|
||
left: 25px;
|
||
animation-delay: -1s;
|
||
}
|
||
|
||
.wind-line4 {
|
||
width: 50px;
|
||
top: 55%;
|
||
left: 40px;
|
||
animation-delay: -1.5s;
|
||
}
|
||
|
||
.wind-line5 {
|
||
width: 45px;
|
||
top: 65%;
|
||
left: 15px;
|
||
animation-delay: -2s;
|
||
}
|
||
|
||
@keyframes windLineMove {
|
||
0%, 100% {
|
||
transform: translateX(0) scaleX(1);
|
||
opacity: 0.6;
|
||
}
|
||
50% {
|
||
transform: translateX(20px) scaleX(1.2);
|
||
opacity: 0.3;
|
||
}
|
||
}
|
||
|
||
.wind-tree {
|
||
position: absolute;
|
||
bottom: 20px;
|
||
right: 30px;
|
||
width: 8px;
|
||
height: 60px;
|
||
background: #8B4513;
|
||
border-radius: 4px;
|
||
animation: windTreeSway 2s infinite ease-in-out;
|
||
}
|
||
|
||
.wind-tree:before {
|
||
content: '';
|
||
position: absolute;
|
||
top: -20px;
|
||
left: -15px;
|
||
width: 38px;
|
||
height: 35px;
|
||
background: #228B22;
|
||
border-radius: 50%;
|
||
animation: windLeavesSway 2s infinite ease-in-out;
|
||
}
|
||
|
||
@keyframes windTreeSway {
|
||
0%, 100% {
|
||
transform: rotate(0deg);
|
||
}
|
||
25% {
|
||
transform: rotate(3deg);
|
||
}
|
||
75% {
|
||
transform: rotate(-3deg);
|
||
}
|
||
}
|
||
|
||
@keyframes windLeavesSway {
|
||
0%, 100% {
|
||
transform: rotate(0deg) scale(1);
|
||
}
|
||
25% {
|
||
transform: rotate(2deg) scale(1.05);
|
||
}
|
||
75% {
|
||
transform: rotate(-2deg) scale(0.95);
|
||
}
|
||
}
|
||
|
||
/* 雨天气卡片样式 */
|
||
.rain-card {
|
||
background: linear-gradient(135deg, #636e72, #2d3436);
|
||
}
|
||
|
||
/* 雨天气动画 */
|
||
.rain-animation {
|
||
position: absolute;
|
||
width: 100%;
|
||
height: 100%;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.rain-cloud {
|
||
position: absolute;
|
||
top: 10px;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
width: 120px;
|
||
height: 60px;
|
||
background: rgba(100, 100, 100, 0.8);
|
||
border-radius: 60px;
|
||
animation: rainCloudFloat 4s infinite ease-in-out;
|
||
}
|
||
|
||
.rain-cloud:before {
|
||
content: '';
|
||
position: absolute;
|
||
top: -25px;
|
||
left: 20px;
|
||
width: 80px;
|
||
height: 50px;
|
||
background: rgba(100, 100, 100, 0.8);
|
||
border-radius: 50px;
|
||
}
|
||
|
||
.rain-cloud:after {
|
||
content: '';
|
||
position: absolute;
|
||
top: -15px;
|
||
right: 15px;
|
||
width: 60px;
|
||
height: 40px;
|
||
background: rgba(100, 100, 100, 0.8);
|
||
border-radius: 40px;
|
||
}
|
||
|
||
@keyframes rainCloudFloat {
|
||
0%, 100% {
|
||
transform: translateX(-50%) translateY(0);
|
||
}
|
||
50% {
|
||
transform: translateX(-50%) translateY(-5px);
|
||
}
|
||
}
|
||
|
||
.rain-drops {
|
||
position: absolute;
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
|
||
.rain-drop {
|
||
position: absolute;
|
||
width: 2px;
|
||
background: linear-gradient(to bottom, rgba(173, 216, 230, 0.8), rgba(135, 206, 235, 0.6));
|
||
border-radius: 0 0 2px 2px;
|
||
animation: rainFall linear infinite;
|
||
}
|
||
|
||
.rain-drop:nth-child(1) {
|
||
left: 10%;
|
||
height: 20px;
|
||
animation-duration: 1s;
|
||
animation-delay: 0s;
|
||
}
|
||
|
||
.rain-drop:nth-child(2) {
|
||
left: 20%;
|
||
height: 25px;
|
||
animation-duration: 1.2s;
|
||
animation-delay: -0.2s;
|
||
}
|
||
|
||
.rain-drop:nth-child(3) {
|
||
left: 30%;
|
||
height: 18px;
|
||
animation-duration: 0.9s;
|
||
animation-delay: -0.4s;
|
||
}
|
||
|
||
.rain-drop:nth-child(4) {
|
||
left: 40%;
|
||
height: 22px;
|
||
animation-duration: 1.1s;
|
||
animation-delay: -0.6s;
|
||
}
|
||
|
||
.rain-drop:nth-child(5) {
|
||
left: 50%;
|
||
height: 24px;
|
||
animation-duration: 1.3s;
|
||
animation-delay: -0.8s;
|
||
}
|
||
|
||
.rain-drop:nth-child(6) {
|
||
left: 60%;
|
||
height: 19px;
|
||
animation-duration: 1s;
|
||
animation-delay: -1s;
|
||
}
|
||
|
||
.rain-drop:nth-child(7) {
|
||
left: 70%;
|
||
height: 26px;
|
||
animation-duration: 1.4s;
|
||
animation-delay: -1.2s;
|
||
}
|
||
|
||
.rain-drop:nth-child(8) {
|
||
left: 80%;
|
||
height: 21px;
|
||
animation-duration: 1.1s;
|
||
animation-delay: -1.4s;
|
||
}
|
||
|
||
.rain-drop:nth-child(9) {
|
||
left: 90%;
|
||
height: 23px;
|
||
animation-duration: 1.2s;
|
||
animation-delay: -1.6s;
|
||
}
|
||
|
||
@keyframes rainFall {
|
||
0% {
|
||
top: -30px;
|
||
opacity: 1;
|
||
}
|
||
100% {
|
||
top: 100%;
|
||
opacity: 0.3;
|
||
}
|
||
}
|
||
|
||
.rain-puddle {
|
||
position: absolute;
|
||
bottom: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 20px;
|
||
background: linear-gradient(to top, rgba(135, 206, 235, 0.3), transparent);
|
||
animation: rainPuddleRipple 2s infinite ease-in-out;
|
||
}
|
||
|
||
@keyframes rainPuddleRipple {
|
||
0%, 100% {
|
||
transform: scaleY(1);
|
||
opacity: 0.3;
|
||
}
|
||
50% {
|
||
transform: scaleY(1.2);
|
||
opacity: 0.5;
|
||
}
|
||
}
|
||
|
||
/* 太阳天气卡片样式 */
|
||
.sun-card {
|
||
background: linear-gradient(135deg, #fdcb6e, #e17055);
|
||
animation: sunCardGlow 3s infinite ease-in-out;
|
||
}
|
||
|
||
@keyframes sunCardGlow {
|
||
0%, 100% {
|
||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
|
||
}
|
||
50% {
|
||
box-shadow: 0 10px 30px rgba(253, 203, 110, 0.4), 0 0 20px rgba(225, 112, 85, 0.3);
|
||
}
|
||
}
|
||
|
||
/* 太阳天气动画 */
|
||
.sun-animation {
|
||
position: absolute;
|
||
width: 100%;
|
||
height: 100%;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.sun {
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
width: 80px;
|
||
height: 80px;
|
||
background: radial-gradient(circle, #ffeb3b, #ff9800);
|
||
border-radius: 50%;
|
||
animation: sunPulse 2s infinite ease-in-out;
|
||
box-shadow: 0 0 20px rgba(255, 235, 59, 0.6);
|
||
}
|
||
|
||
@keyframes sunPulse {
|
||
0%, 100% {
|
||
transform: translate(-50%, -50%) scale(1);
|
||
box-shadow: 0 0 20px rgba(255, 235, 59, 0.6);
|
||
}
|
||
50% {
|
||
transform: translate(-50%, -50%) scale(1.1);
|
||
box-shadow: 0 0 30px rgba(255, 235, 59, 0.8);
|
||
}
|
||
}
|
||
|
||
.sun-rays {
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
width: 160px;
|
||
height: 160px;
|
||
animation: sunRaysRotate 8s infinite linear;
|
||
}
|
||
|
||
.sun-ray {
|
||
position: absolute;
|
||
background: linear-gradient(to bottom, rgba(255, 235, 59, 0.8), transparent);
|
||
border-radius: 2px;
|
||
transform-origin: center bottom;
|
||
}
|
||
|
||
.sun-ray:nth-child(1) {
|
||
width: 4px;
|
||
height: 40px;
|
||
top: 0;
|
||
left: 50%;
|
||
transform: translateX(-50%) rotate(0deg);
|
||
}
|
||
|
||
.sun-ray:nth-child(2) {
|
||
width: 4px;
|
||
height: 35px;
|
||
top: 5px;
|
||
left: 50%;
|
||
transform: translateX(-50%) rotate(45deg);
|
||
}
|
||
|
||
.sun-ray:nth-child(3) {
|
||
width: 4px;
|
||
height: 40px;
|
||
top: 0;
|
||
left: 50%;
|
||
transform: translateX(-50%) rotate(90deg);
|
||
}
|
||
|
||
.sun-ray:nth-child(4) {
|
||
width: 4px;
|
||
height: 35px;
|
||
top: 5px;
|
||
left: 50%;
|
||
transform: translateX(-50%) rotate(135deg);
|
||
}
|
||
|
||
.sun-ray:nth-child(5) {
|
||
width: 4px;
|
||
height: 40px;
|
||
top: 0;
|
||
left: 50%;
|
||
transform: translateX(-50%) rotate(180deg);
|
||
}
|
||
|
||
.sun-ray:nth-child(6) {
|
||
width: 4px;
|
||
height: 35px;
|
||
top: 5px;
|
||
left: 50%;
|
||
transform: translateX(-50%) rotate(225deg);
|
||
}
|
||
|
||
.sun-ray:nth-child(7) {
|
||
width: 4px;
|
||
height: 40px;
|
||
top: 0;
|
||
left: 50%;
|
||
transform: translateX(-50%) rotate(270deg);
|
||
}
|
||
|
||
.sun-ray:nth-child(8) {
|
||
width: 4px;
|
||
height: 35px;
|
||
top: 5px;
|
||
left: 50%;
|
||
transform: translateX(-50%) rotate(315deg);
|
||
}
|
||
|
||
@keyframes sunRaysRotate {
|
||
0% {
|
||
transform: translate(-50%, -50%) rotate(0deg);
|
||
}
|
||
100% {
|
||
transform: translate(-50%, -50%) rotate(360deg);
|
||
}
|
||
}
|
||
|
||
.sun-sparkles {
|
||
position: absolute;
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
|
||
.sun-sparkle {
|
||
position: absolute;
|
||
width: 6px;
|
||
height: 6px;
|
||
background: #ffeb3b;
|
||
border-radius: 50%;
|
||
animation: sunSparkle 3s infinite ease-in-out;
|
||
}
|
||
|
||
.sun-sparkle:nth-child(1) {
|
||
top: 20%;
|
||
left: 20%;
|
||
animation-delay: 0s;
|
||
}
|
||
|
||
.sun-sparkle:nth-child(2) {
|
||
top: 30%;
|
||
right: 25%;
|
||
animation-delay: -0.5s;
|
||
}
|
||
|
||
.sun-sparkle:nth-child(3) {
|
||
bottom: 30%;
|
||
left: 25%;
|
||
animation-delay: -1s;
|
||
}
|
||
|
||
.sun-sparkle:nth-child(4) {
|
||
bottom: 25%;
|
||
right: 20%;
|
||
animation-delay: -1.5s;
|
||
}
|
||
|
||
@keyframes sunSparkle {
|
||
0%, 100% {
|
||
opacity: 0;
|
||
transform: scale(0);
|
||
}
|
||
50% {
|
||
opacity: 1;
|
||
transform: scale(1);
|
||
}
|
||
}
|
||
|
||
/* 雪天气卡片样式 */
|
||
.snow-card {
|
||
background: linear-gradient(135deg, #a8e6cf, #74b9ff);
|
||
}
|
||
|
||
/* 雪天气动画 */
|
||
.snow-animation {
|
||
position: absolute;
|
||
width: 100%;
|
||
height: 100%;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.snowflakes {
|
||
position: absolute;
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
|
||
.snowflake {
|
||
position: absolute;
|
||
color: white;
|
||
font-size: 1em;
|
||
animation: snowFall linear infinite;
|
||
text-shadow: 0 0 5px rgba(255, 255, 255, 0.8);
|
||
}
|
||
|
||
.snowflake:nth-child(1) {
|
||
left: 10%;
|
||
font-size: 0.8em;
|
||
animation-duration: 3s;
|
||
animation-delay: 0s;
|
||
}
|
||
|
||
.snowflake:nth-child(2) {
|
||
left: 20%;
|
||
font-size: 1.2em;
|
||
animation-duration: 4s;
|
||
animation-delay: -0.5s;
|
||
}
|
||
|
||
.snowflake:nth-child(3) {
|
||
left: 30%;
|
||
font-size: 0.9em;
|
||
animation-duration: 3.5s;
|
||
animation-delay: -1s;
|
||
}
|
||
|
||
.snowflake:nth-child(4) {
|
||
left: 40%;
|
||
font-size: 1.1em;
|
||
animation-duration: 4.5s;
|
||
animation-delay: -1.5s;
|
||
}
|
||
|
||
.snowflake:nth-child(5) {
|
||
left: 50%;
|
||
font-size: 0.7em;
|
||
animation-duration: 3.2s;
|
||
animation-delay: -2s;
|
||
}
|
||
|
||
.snowflake:nth-child(6) {
|
||
left: 60%;
|
||
font-size: 1.3em;
|
||
animation-duration: 4.2s;
|
||
animation-delay: -2.5s;
|
||
}
|
||
|
||
.snowflake:nth-child(7) {
|
||
left: 70%;
|
||
font-size: 0.9em;
|
||
animation-duration: 3.8s;
|
||
animation-delay: -3s;
|
||
}
|
||
|
||
.snowflake:nth-child(8) {
|
||
left: 80%;
|
||
font-size: 1em;
|
||
animation-duration: 4.1s;
|
||
animation-delay: -3.5s;
|
||
}
|
||
|
||
.snowflake:nth-child(9) {
|
||
left: 90%;
|
||
font-size: 0.8em;
|
||
animation-duration: 3.6s;
|
||
animation-delay: -4s;
|
||
}
|
||
|
||
.snowflake:nth-child(10) {
|
||
left: 15%;
|
||
font-size: 1.1em;
|
||
animation-duration: 4.3s;
|
||
animation-delay: -4.5s;
|
||
}
|
||
|
||
@keyframes snowFall {
|
||
0% {
|
||
top: -10%;
|
||
transform: translateX(0) rotate(0deg);
|
||
opacity: 1;
|
||
}
|
||
100% {
|
||
top: 110%;
|
||
transform: translateX(20px) rotate(360deg);
|
||
opacity: 0.3;
|
||
}
|
||
}
|
||
|
||
.snow-ground {
|
||
position: absolute;
|
||
bottom: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 30px;
|
||
background: linear-gradient(to top, rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0.3));
|
||
border-radius: 50% 50% 0 0;
|
||
animation: snowGroundGrow 5s infinite ease-in-out;
|
||
}
|
||
|
||
@keyframes snowGroundGrow {
|
||
0%, 100% {
|
||
height: 30px;
|
||
opacity: 0.9;
|
||
}
|
||
50% {
|
||
height: 35px;
|
||
opacity: 1;
|
||
}
|
||
}
|
||
|
||
.snow-wind {
|
||
position: absolute;
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
|
||
.snow-wind-line {
|
||
position: absolute;
|
||
background: rgba(255, 255, 255, 0.4);
|
||
height: 1px;
|
||
border-radius: 1px;
|
||
animation: snowWindMove 4s infinite ease-in-out;
|
||
}
|
||
|
||
.snow-wind-line:nth-child(1) {
|
||
width: 30px;
|
||
top: 20%;
|
||
left: 10%;
|
||
animation-delay: 0s;
|
||
}
|
||
|
||
.snow-wind-line:nth-child(2) {
|
||
width: 40px;
|
||
top: 40%;
|
||
left: 20%;
|
||
animation-delay: -1s;
|
||
}
|
||
|
||
.snow-wind-line:nth-child(3) {
|
||
width: 25px;
|
||
top: 60%;
|
||
left: 30%;
|
||
animation-delay: -2s;
|
||
}
|
||
|
||
@keyframes snowWindMove {
|
||
0%, 100% {
|
||
transform: translateX(0) scaleX(1);
|
||
opacity: 0.4;
|
||
}
|
||
50% {
|
||
transform: translateX(15px) scaleX(1.3);
|
||
opacity: 0.2;
|
||
}
|
||
}
|
||
|
||
/* 响应式设计 */
|
||
@media (max-width: 1200px) {
|
||
.weather-container {
|
||
max-width: 900px;
|
||
}
|
||
|
||
.weather-card {
|
||
width: 260px;
|
||
height: 320px;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 992px) {
|
||
.weather-container {
|
||
max-width: 600px;
|
||
}
|
||
|
||
.weather-card {
|
||
width: 280px;
|
||
height: 350px;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 768px) {
|
||
.weather-container {
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: 15px;
|
||
}
|
||
|
||
.weather-card {
|
||
width: 100%;
|
||
max-width: 320px;
|
||
height: 300px;
|
||
}
|
||
|
||
.header h1 {
|
||
font-size: 2rem;
|
||
}
|
||
|
||
.controls {
|
||
gap: 10px;
|
||
}
|
||
|
||
.control-btn {
|
||
padding: 10px 20px;
|
||
font-size: 0.9rem;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 480px) {
|
||
body {
|
||
padding: 15px;
|
||
}
|
||
|
||
.header h1 {
|
||
font-size: 1.8rem;
|
||
}
|
||
|
||
.weather-card {
|
||
max-width: 280px;
|
||
height: 280px;
|
||
}
|
||
|
||
.controls {
|
||
flex-direction: column;
|
||
width: 100%;
|
||
max-width: 280px;
|
||
}
|
||
|
||
.control-btn {
|
||
width: 100%;
|
||
padding: 12px;
|
||
}
|
||
|
||
.weather-title {
|
||
font-size: 1.5rem;
|
||
}
|
||
|
||
.weather-desc {
|
||
font-size: 0.9rem;
|
||
}
|
||
}
|
||
|
||
/* 卡片隐藏/显示动画 */
|
||
.weather-card {
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.weather-card.hidden {
|
||
opacity: 0;
|
||
transform: scale(0.8);
|
||
pointer-events: none;
|
||
}
|
||
|
||
.weather-card.visible {
|
||
opacity: 1;
|
||
transform: scale(1);
|
||
pointer-events: auto;
|
||
}
|
||
|
||
/* 卡片焦点状态 */
|
||
.weather-card.focused {
|
||
transform: translateY(-10px) scale(1.05);
|
||
box-shadow: 0 20px 50px rgba(0, 0, 0, 0.5);
|
||
z-index: 10;
|
||
}
|
||
|
||
/* 加载动画 */
|
||
.weather-card {
|
||
animation: cardFadeIn 0.6s ease-out forwards;
|
||
}
|
||
|
||
.weather-card:nth-child(1) { animation-delay: 0.1s; }
|
||
.weather-card:nth-child(2) { animation-delay: 0.2s; }
|
||
.weather-card:nth-child(3) { animation-delay: 0.3s; }
|
||
.weather-card:nth-child(4) { animation-delay: 0.4s; }
|
||
|
||
@keyframes cardFadeIn {
|
||
0% {
|
||
opacity: 0;
|
||
transform: translateY(30px) scale(0.9);
|
||
}
|
||
100% {
|
||
opacity: 1;
|
||
transform: translateY(0) scale(1);
|
||
}
|
||
}
|
||
|
||
/* 页面加载动画 */
|
||
.header {
|
||
animation: headerSlideDown 0.8s ease-out;
|
||
}
|
||
|
||
.controls {
|
||
animation: controlsFadeIn 1s ease-out 0.3s both;
|
||
}
|
||
|
||
@keyframes headerSlideDown {
|
||
0% {
|
||
opacity: 0;
|
||
transform: translateY(-50px);
|
||
}
|
||
100% {
|
||
opacity: 1;
|
||
transform: translateY(0);
|
||
}
|
||
}
|
||
|
||
@keyframes controlsFadeIn {
|
||
0% {
|
||
opacity: 0;
|
||
transform: translateY(20px);
|
||
}
|
||
100% {
|
||
opacity: 1;
|
||
transform: translateY(0);
|
||
}
|
||
}
|
||
|
||
/* 优化动画性能 */
|
||
@media (prefers-reduced-motion: reduce) {
|
||
*,
|
||
*::before,
|
||
*::after {
|
||
animation-duration: 0.01ms !important;
|
||
animation-iteration-count: 1 !important;
|
||
transition-duration: 0.01ms !important;
|
||
}
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="header">
|
||
<h1>动画天气卡片</h1>
|
||
<p>体验不同天气状况的动画效果</p>
|
||
</div>
|
||
|
||
<div class="controls">
|
||
<button class="control-btn active" data-weather="all">显示全部</button>
|
||
<button class="control-btn" data-weather="wind">风</button>
|
||
<button class="control-btn" data-weather="rain">雨</button>
|
||
<button class="control-btn" data-weather="sun">太阳</button>
|
||
<button class="control-btn" data-weather="snow">雪</button>
|
||
</div>
|
||
|
||
<div class="weather-container">
|
||
<!-- 风天气卡片 -->
|
||
<div class="weather-card wind-card" data-type="wind">
|
||
<div class="wind-animation">
|
||
<div class="wind-cloud wind-cloud1"></div>
|
||
<div class="wind-cloud wind-cloud2"></div>
|
||
<div class="wind-cloud wind-cloud3"></div>
|
||
<div class="wind-lines">
|
||
<div class="wind-line wind-line1"></div>
|
||
<div class="wind-line wind-line2"></div>
|
||
<div class="wind-line wind-line3"></div>
|
||
<div class="wind-line wind-line4"></div>
|
||
<div class="wind-line wind-line5"></div>
|
||
</div>
|
||
<div class="wind-tree"></div>
|
||
</div>
|
||
<div class="card-content">
|
||
<div class="weather-title">风</div>
|
||
<div class="weather-desc">微风轻拂</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 雨天气卡片 -->
|
||
<div class="weather-card rain-card" data-type="rain">
|
||
<div class="rain-animation">
|
||
<div class="rain-cloud"></div>
|
||
<div class="rain-drops">
|
||
<div class="rain-drop"></div>
|
||
<div class="rain-drop"></div>
|
||
<div class="rain-drop"></div>
|
||
<div class="rain-drop"></div>
|
||
<div class="rain-drop"></div>
|
||
<div class="rain-drop"></div>
|
||
<div class="rain-drop"></div>
|
||
<div class="rain-drop"></div>
|
||
<div class="rain-drop"></div>
|
||
</div>
|
||
<div class="rain-puddle"></div>
|
||
</div>
|
||
<div class="card-content">
|
||
<div class="weather-title">雨</div>
|
||
<div class="weather-desc">细雨绵绵</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 太阳天气卡片 -->
|
||
<div class="weather-card sun-card" data-type="sun">
|
||
<div class="sun-animation">
|
||
<div class="sun-rays">
|
||
<div class="sun-ray"></div>
|
||
<div class="sun-ray"></div>
|
||
<div class="sun-ray"></div>
|
||
<div class="sun-ray"></div>
|
||
<div class="sun-ray"></div>
|
||
<div class="sun-ray"></div>
|
||
<div class="sun-ray"></div>
|
||
<div class="sun-ray"></div>
|
||
</div>
|
||
<div class="sun"></div>
|
||
<div class="sun-sparkles">
|
||
<div class="sun-sparkle"></div>
|
||
<div class="sun-sparkle"></div>
|
||
<div class="sun-sparkle"></div>
|
||
<div class="sun-sparkle"></div>
|
||
</div>
|
||
</div>
|
||
<div class="card-content">
|
||
<div class="weather-title">太阳</div>
|
||
<div class="weather-desc">阳光明媚</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 雪天气卡片 -->
|
||
<div class="weather-card snow-card" data-type="snow">
|
||
<div class="snow-animation">
|
||
<div class="snowflakes">
|
||
<div class="snowflake">❄</div>
|
||
<div class="snowflake">❅</div>
|
||
<div class="snowflake">❆</div>
|
||
<div class="snowflake">❄</div>
|
||
<div class="snowflake">❅</div>
|
||
<div class="snowflake">❆</div>
|
||
<div class="snowflake">❄</div>
|
||
<div class="snowflake">❅</div>
|
||
<div class="snowflake">❆</div>
|
||
<div class="snowflake">❄</div>
|
||
</div>
|
||
<div class="snow-wind">
|
||
<div class="snow-wind-line"></div>
|
||
<div class="snow-wind-line"></div>
|
||
<div class="snow-wind-line"></div>
|
||
</div>
|
||
<div class="snow-ground"></div>
|
||
</div>
|
||
<div class="card-content">
|
||
<div class="weather-title">雪</div>
|
||
<div class="weather-desc">雪花飞舞</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
// 原来的复杂控制器已被简化版本替代
|
||
|
||
// 简化的初始化函数
|
||
function initWeatherCards() {
|
||
console.log('开始初始化天气卡片...');
|
||
|
||
// 绑定按钮事件
|
||
const controlBtns = document.querySelectorAll('.control-btn');
|
||
console.log('找到按钮数量:', controlBtns.length);
|
||
|
||
controlBtns.forEach((btn, index) => {
|
||
console.log(`按钮 ${index}:`, btn.textContent, btn.dataset.weather);
|
||
btn.addEventListener('click', function(e) {
|
||
console.log('按钮被点击:', this.textContent, this.dataset.weather);
|
||
|
||
// 更新按钮状态
|
||
controlBtns.forEach(b => b.classList.remove('active'));
|
||
this.classList.add('active');
|
||
|
||
// 切换天气显示
|
||
const weatherType = this.dataset.weather;
|
||
showWeatherCards(weatherType);
|
||
});
|
||
});
|
||
|
||
// 初始显示所有卡片
|
||
showWeatherCards('all');
|
||
console.log('初始化完成');
|
||
}
|
||
|
||
function showWeatherCards(weatherType) {
|
||
console.log('切换到:', weatherType);
|
||
const weatherCards = document.querySelectorAll('.weather-card');
|
||
console.log('卡片数量:', weatherCards.length);
|
||
|
||
// 添加切换动画指示
|
||
showSwitchingIndicator();
|
||
|
||
weatherCards.forEach((card, index) => {
|
||
const cardType = card.dataset.type;
|
||
console.log('处理卡片:', cardType);
|
||
|
||
// 确保卡片有流畅的过渡效果
|
||
card.style.transition = 'all 0.6s cubic-bezier(0.25, 0.46, 0.45, 0.94), transform 0.6s cubic-bezier(0.34, 1.56, 0.64, 1)';
|
||
|
||
if (weatherType === 'all') {
|
||
// 显示所有卡片,带有延迟动画
|
||
card.style.display = 'block';
|
||
card.style.filter = 'blur(0px) brightness(1)';
|
||
setTimeout(() => {
|
||
card.style.opacity = '1';
|
||
card.style.transform = 'scale(1) translateY(0) rotateY(0deg)';
|
||
card.style.boxShadow = '0 10px 30px rgba(0, 0, 0, 0.3)';
|
||
}, index * 120); // 每个卡片延迟120ms
|
||
} else if (cardType === weatherType) {
|
||
// 显示选中的卡片,带有特殊效果
|
||
card.style.display = 'block';
|
||
setTimeout(() => {
|
||
card.style.opacity = '1';
|
||
card.style.transform = 'scale(1.08) translateY(-10px) rotateY(0deg)';
|
||
card.style.boxShadow = '0 20px 50px rgba(0, 0, 0, 0.5), 0 0 30px rgba(255, 255, 255, 0.1)';
|
||
card.style.filter = 'blur(0px) brightness(1.1) saturate(1.2)';
|
||
card.style.zIndex = '10';
|
||
|
||
// 2.5秒后恢复正常大小
|
||
setTimeout(() => {
|
||
card.style.transform = 'scale(1) translateY(0) rotateY(0deg)';
|
||
card.style.boxShadow = '0 10px 30px rgba(0, 0, 0, 0.3)';
|
||
card.style.filter = 'blur(0px) brightness(1) saturate(1)';
|
||
card.style.zIndex = '1';
|
||
}, 2500);
|
||
}, 150);
|
||
} else {
|
||
// 隐藏其他卡片,带有3D效果
|
||
card.style.opacity = '0';
|
||
card.style.transform = 'scale(0.7) translateY(30px) rotateY(-20deg)';
|
||
card.style.filter = 'blur(3px) brightness(0.7)';
|
||
setTimeout(() => {
|
||
if (card.style.opacity === '0') {
|
||
card.style.display = 'none';
|
||
}
|
||
}, 600);
|
||
}
|
||
});
|
||
}
|
||
|
||
// 切换指示器函数
|
||
function showSwitchingIndicator() {
|
||
// 创建或获取指示器
|
||
let indicator = document.getElementById('switching-indicator');
|
||
if (!indicator) {
|
||
indicator = document.createElement('div');
|
||
indicator.id = 'switching-indicator';
|
||
indicator.style.cssText = `
|
||
position: fixed;
|
||
top: 50%;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
background: rgba(0, 0, 0, 0.8);
|
||
color: white;
|
||
padding: 15px 25px;
|
||
border-radius: 25px;
|
||
font-size: 14px;
|
||
z-index: 1000;
|
||
opacity: 0;
|
||
transition: opacity 0.3s ease;
|
||
pointer-events: none;
|
||
`;
|
||
indicator.innerHTML = '切换中...';
|
||
document.body.appendChild(indicator);
|
||
}
|
||
|
||
// 显示指示器
|
||
indicator.style.opacity = '1';
|
||
|
||
// 1秒后隐藏
|
||
setTimeout(() => {
|
||
indicator.style.opacity = '0';
|
||
}, 1000);
|
||
}
|
||
|
||
// 页面加载完成后初始化
|
||
document.addEventListener('DOMContentLoaded', initWeatherCards);
|
||
|
||
// 提示功能暂时移除,专注于核心功能
|
||
</script>
|
||
</body>
|
||
</html>
|