/** * ============================================ * ⚡ 企业级动画系统 * ============================================ * 参考:iOS、Material Design、Framer Motion */ @import './design-tokens.wxss'; /* ==================== 🎭 入场动画 ==================== */ /* 淡入 */ .animate-fade-in { animation: fade-in var(--duration-moderate) var(--ease-out) forwards; } @keyframes fade-in { from { opacity: 0; } to { opacity: 1; } } /* 从上滑入 */ .animate-slide-in-up { animation: slide-in-up var(--duration-moderate) var(--ease-out) forwards; } @keyframes slide-in-up { from { opacity: 0; transform: translateY(60rpx); } to { opacity: 1; transform: translateY(0); } } /* 从下滑入 */ .animate-slide-in-down { animation: slide-in-down var(--duration-moderate) var(--ease-out) forwards; } @keyframes slide-in-down { from { opacity: 0; transform: translateY(-60rpx); } to { opacity: 1; transform: translateY(0); } } /* 从左滑入 */ .animate-slide-in-left { animation: slide-in-left var(--duration-moderate) var(--ease-out) forwards; } @keyframes slide-in-left { from { opacity: 0; transform: translateX(-60rpx); } to { opacity: 1; transform: translateX(0); } } /* 从右滑入 */ .animate-slide-in-right { animation: slide-in-right var(--duration-moderate) var(--ease-out) forwards; } @keyframes slide-in-right { from { opacity: 0; transform: translateX(60rpx); } to { opacity: 1; transform: translateX(0); } } /* 缩放入场 */ .animate-scale-in { animation: scale-in var(--duration-moderate) var(--ease-out) forwards; } @keyframes scale-in { from { opacity: 0; transform: scale(0.85); } to { opacity: 1; transform: scale(1); } } /* 弹跳入场 */ .animate-bounce-in { animation: bounce-in var(--duration-slow) var(--ease-bounce) forwards; } @keyframes bounce-in { 0% { opacity: 0; transform: scale(0.3); } 50% { opacity: 1; transform: scale(1.05); } 70% { transform: scale(0.95); } 100% { transform: scale(1); } } /* 旋转入场 */ .animate-rotate-in { animation: rotate-in var(--duration-moderate) var(--ease-out) forwards; } @keyframes rotate-in { from { opacity: 0; transform: rotate(-180deg) scale(0.5); } to { opacity: 1; transform: rotate(0) scale(1); } } /* 翻转入场 */ .animate-flip-in { animation: flip-in var(--duration-slow) var(--ease-out) forwards; } @keyframes flip-in { from { opacity: 0; transform: perspective(2000rpx) rotateX(-90deg); } to { opacity: 1; transform: perspective(2000rpx) rotateX(0); } } /* ==================== 🎯 退场动画 ==================== */ /* 淡出 */ .animate-fade-out { animation: fade-out var(--duration-moderate) var(--ease-in) forwards; } @keyframes fade-out { from { opacity: 1; } to { opacity: 0; } } /* 向上滑出 */ .animate-slide-out-up { animation: slide-out-up var(--duration-moderate) var(--ease-in) forwards; } @keyframes slide-out-up { from { opacity: 1; transform: translateY(0); } to { opacity: 0; transform: translateY(-60rpx); } } /* 向下滑出 */ .animate-slide-out-down { animation: slide-out-down var(--duration-moderate) var(--ease-in) forwards; } @keyframes slide-out-down { from { opacity: 1; transform: translateY(0); } to { opacity: 0; transform: translateY(60rpx); } } /* 缩放退出 */ .animate-scale-out { animation: scale-out var(--duration-moderate) var(--ease-in) forwards; } @keyframes scale-out { from { opacity: 1; transform: scale(1); } to { opacity: 0; transform: scale(0.85); } } /* ==================== 💫 循环动画 ==================== */ /* 脉冲 */ .animate-pulse { animation: pulse 2s var(--ease-in-out) infinite; } @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } } /* 心跳 */ .animate-heartbeat { animation: heartbeat 1.5s var(--ease-in-out) infinite; } @keyframes heartbeat { 0%, 100% { transform: scale(1); } 14% { transform: scale(1.15); } 28% { transform: scale(1); } 42% { transform: scale(1.15); } 70% { transform: scale(1); } } /* 弹跳 */ .animate-bounce { animation: bounce 1s var(--ease-bounce) infinite; } @keyframes bounce { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-20rpx); } } /* 摇晃 */ .animate-shake { animation: shake 0.5s var(--ease-in-out); } @keyframes shake { 0%, 100% { transform: translateX(0); } 10%, 30%, 50%, 70%, 90% { transform: translateX(-10rpx); } 20%, 40%, 60%, 80% { transform: translateX(10rpx); } } /* 摆动 */ .animate-swing { animation: swing 1s var(--ease-in-out); } @keyframes swing { 20% { transform: rotate(15deg); } 40% { transform: rotate(-10deg); } 60% { transform: rotate(5deg); } 80% { transform: rotate(-5deg); } 100% { transform: rotate(0deg); } } /* 旋转 */ .animate-spin { animation: spin 1s linear infinite; } @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } /* 慢速旋转 */ .animate-spin-slow { animation: spin 3s linear infinite; } /* 反向旋转 */ .animate-spin-reverse { animation: spin-reverse 1s linear infinite; } @keyframes spin-reverse { from { transform: rotate(360deg); } to { transform: rotate(0deg); } } /* 漂浮 */ .animate-float { animation: float 3s var(--ease-in-out) infinite; } @keyframes float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-20rpx); } } /* 呼吸灯 */ .animate-breathing { animation: breathing 3s var(--ease-in-out) infinite; } @keyframes breathing { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.05); opacity: 0.8; } } /* 闪烁 */ .animate-blink { animation: blink 1s steps(2) infinite; } @keyframes blink { 0%, 100% { opacity: 1; } 50% { opacity: 0; } } /* ==================== 🌊 高级特效 ==================== */ /* 波纹扩散 */ .animate-ripple { position: relative; overflow: hidden; } .animate-ripple::after { content: ''; position: absolute; top: 50%; left: 50%; width: 0; height: 0; border-radius: 50%; background: rgba(255, 255, 255, 0.5); transform: translate(-50%, -50%); animation: ripple 0.6s ease-out; } @keyframes ripple { to { width: 300%; height: 300%; opacity: 0; } } /* 渐变动画 */ .animate-gradient { background-size: 200% 200%; animation: gradient-shift 3s ease infinite; } @keyframes gradient-shift { 0%, 100% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } } /* 光晕效果 */ .animate-glow { animation: glow 2s ease-in-out infinite; } @keyframes glow { 0%, 100% { box-shadow: 0 0 10rpx rgba(102, 126, 234, 0.5); } 50% { box-shadow: 0 0 30rpx rgba(102, 126, 234, 0.8); } } /* 彩虹边框 */ .animate-rainbow-border { position: relative; border: 3rpx solid transparent; background-clip: padding-box; } .animate-rainbow-border::before { content: ''; position: absolute; top: -3rpx; left: -3rpx; right: -3rpx; bottom: -3rpx; background: linear-gradient(45deg, #FF6B6B, #FFD93D, #6BCF7F, #4ECDC4, #667EEA, #C77DFF); background-size: 400% 400%; border-radius: inherit; z-index: -1; animation: rainbow 3s ease infinite; } @keyframes rainbow { 0%, 100% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } } /* 打字效果 */ .animate-typing { overflow: hidden; border-right: 3rpx solid; white-space: nowrap; animation: typing 3.5s steps(40) 1s forwards, blink-caret 0.75s step-end infinite; width: 0; } @keyframes typing { to { width: 100%; } } @keyframes blink-caret { from, to { border-color: transparent; } 50% { border-color: currentColor; } } /* ==================== 🎨 悬停效果 ==================== */ /* 悬停上浮 */ .hover-lift { transition: transform var(--duration-fast) var(--ease-out), box-shadow var(--duration-fast) var(--ease-out); } .hover-lift:active { transform: translateY(-8rpx); box-shadow: var(--shadow-lg); } /* 悬停放大 */ .hover-scale { transition: transform var(--duration-fast) var(--ease-out); } .hover-scale:active { transform: scale(1.05); } /* 悬停缩小 */ .hover-shrink { transition: transform var(--duration-fast) var(--ease-out); } .hover-shrink:active { transform: scale(0.95); } /* 悬停倾斜 */ .hover-tilt { transition: transform var(--duration-fast) var(--ease-out); } .hover-tilt:active { transform: perspective(1000rpx) rotateX(5deg) rotateY(5deg); } /* 悬停发光 */ .hover-glow { transition: box-shadow var(--duration-fast) var(--ease-out); } .hover-glow:active { box-shadow: 0 0 30rpx rgba(102, 126, 234, 0.6); } /* 悬停彩色阴影 */ .hover-shadow-color { transition: box-shadow var(--duration-fast) var(--ease-out); } .hover-shadow-color:active { box-shadow: 0 10rpx 40rpx rgba(102, 126, 234, 0.4); } /* ==================== ⚙️ 延迟类 ==================== */ .delay-0 { animation-delay: 0ms !important; } .delay-50 { animation-delay: 50ms !important; } .delay-100 { animation-delay: 100ms !important; } .delay-150 { animation-delay: 150ms !important; } .delay-200 { animation-delay: 200ms !important; } .delay-300 { animation-delay: 300ms !important; } .delay-400 { animation-delay: 400ms !important; } .delay-500 { animation-delay: 500ms !important; } .delay-600 { animation-delay: 600ms !important; } .delay-700 { animation-delay: 700ms !important; } .delay-800 { animation-delay: 800ms !important; } .delay-900 { animation-delay: 900ms !important; } .delay-1000 { animation-delay: 1000ms !important; } /* ==================== 🏃 速度类 ==================== */ .duration-fast { animation-duration: var(--duration-fast) !important; } .duration-normal { animation-duration: var(--duration-normal) !important; } .duration-moderate { animation-duration: var(--duration-moderate) !important; } .duration-slow { animation-duration: var(--duration-slow) !important; } .duration-slower { animation-duration: var(--duration-slower) !important; } /* ==================== 🔄 列表过渡动画 ==================== */ /* 列表项淡入 - 阶梯延迟 */ .list-item-fade { animation: fade-in var(--duration-moderate) var(--ease-out) backwards; } .list-item-fade:nth-child(1) { animation-delay: 0ms; } .list-item-fade:nth-child(2) { animation-delay: 50ms; } .list-item-fade:nth-child(3) { animation-delay: 100ms; } .list-item-fade:nth-child(4) { animation-delay: 150ms; } .list-item-fade:nth-child(5) { animation-delay: 200ms; } .list-item-fade:nth-child(6) { animation-delay: 250ms; } .list-item-fade:nth-child(7) { animation-delay: 300ms; } .list-item-fade:nth-child(8) { animation-delay: 350ms; } .list-item-fade:nth-child(9) { animation-delay: 400ms; } .list-item-fade:nth-child(10) { animation-delay: 450ms; } /* 列表项滑入 - 阶梯延迟 */ .list-item-slide { animation: slide-in-up var(--duration-moderate) var(--ease-out) backwards; } .list-item-slide:nth-child(1) { animation-delay: 0ms; } .list-item-slide:nth-child(2) { animation-delay: 50ms; } .list-item-slide:nth-child(3) { animation-delay: 100ms; } .list-item-slide:nth-child(4) { animation-delay: 150ms; } .list-item-slide:nth-child(5) { animation-delay: 200ms; } .list-item-slide:nth-child(6) { animation-delay: 250ms; } .list-item-slide:nth-child(7) { animation-delay: 300ms; } .list-item-slide:nth-child(8) { animation-delay: 350ms; } .list-item-slide:nth-child(9) { animation-delay: 400ms; } .list-item-slide:nth-child(10) { animation-delay: 450ms; } /* ==================== 📱 页面转场动画 ==================== */ /* 页面淡入 */ .page-enter { animation: page-fade-in var(--duration-moderate) var(--ease-out); } @keyframes page-fade-in { from { opacity: 0; } to { opacity: 1; } } /* 页面从右滑入 */ .page-slide-in { animation: page-slide-in var(--duration-moderate) var(--ease-out); } @keyframes page-slide-in { from { opacity: 0; transform: translateX(100rpx); } to { opacity: 1; transform: translateX(0); } } /* 页面缩放进入 */ .page-zoom-in { animation: page-zoom-in var(--duration-moderate) var(--ease-out); } @keyframes page-zoom-in { from { opacity: 0; transform: scale(0.95); } to { opacity: 1; transform: scale(1); } } /* ==================== 🎯 骨架屏动画 ==================== */ .skeleton-shimmer { background: linear-gradient( 90deg, rgba(0, 0, 0, 0.06) 25%, rgba(0, 0, 0, 0.15) 37%, rgba(0, 0, 0, 0.06) 63% ); background-size: 400% 100%; animation: skeleton-loading 1.4s ease infinite; } @keyframes skeleton-loading { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } } /* ==================== 🌟 特殊效果 ==================== */ /* 故障效果 */ .glitch { position: relative; animation: glitch 2s infinite; } @keyframes glitch { 0%, 100% { transform: translate(0); } 20% { transform: translate(-2rpx, 2rpx); } 40% { transform: translate(-2rpx, -2rpx); } 60% { transform: translate(2rpx, 2rpx); } 80% { transform: translate(2rpx, -2rpx); } } /* 霓虹灯效果 */ .neon { animation: neon 1.5s ease-in-out infinite alternate; } @keyframes neon { from { text-shadow: 0 0 10rpx #fff, 0 0 20rpx #fff, 0 0 30rpx #fff, 0 0 40rpx #667EEA, 0 0 70rpx #667EEA, 0 0 80rpx #667EEA, 0 0 100rpx #667EEA, 0 0 150rpx #667EEA; } to { text-shadow: 0 0 5rpx #fff, 0 0 10rpx #fff, 0 0 15rpx #fff, 0 0 20rpx #667EEA, 0 0 35rpx #667EEA, 0 0 40rpx #667EEA, 0 0 50rpx #667EEA, 0 0 75rpx #667EEA; } } /* 粒子飘散 */ .particle-float { animation: particle-float 3s ease-in-out infinite; } @keyframes particle-float { 0%, 100% { transform: translateY(0) translateX(0); } 33% { transform: translateY(-20rpx) translateX(10rpx); } 66% { transform: translateY(-10rpx) translateX(-10rpx); } }