766 lines
14 KiB
Plaintext
766 lines
14 KiB
Plaintext
/**
|
||
* ============================================
|
||
* ⚡ 企业级动画系统
|
||
* ============================================
|
||
* 参考: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);
|
||
}
|
||
}
|