/** * Jio Animations — animate.css 等价(独立重写) * ------------------------------------------------------------ * 关键帧 + 工具类 + IntersectionObserver 触发配合 * 触发 JS 已在 enhancements2.js([data-jio-animate] 属性) * 本文件仅定义 @keyframes 和 .jio-anim-* 工具类 */ /* ============================================================ * Keyframes * ============================================================ */ /* Fade 系列 */ @keyframes jioFadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes jioFadeInUp { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: none; } } @keyframes jioFadeInDown { from { opacity: 0; transform: translateY(-20px); } to { opacity: 1; transform: none; } } @keyframes jioFadeInLeft { from { opacity: 0; transform: translateX(-20px); } to { opacity: 1; transform: none; } } @keyframes jioFadeInRight { from { opacity: 0; transform: translateX(20px); } to { opacity: 1; transform: none; } } /* Zoom 系列 */ @keyframes jioZoomIn { from { opacity: 0; transform: scale(.85); } to { opacity: 1; transform: none; } } @keyframes jioZoomInUp { from { opacity: 0; transform: scale(.85) translateY(20px); } to { opacity: 1; transform: none; } } /* Bounce 系列 */ @keyframes jioBounceIn { 0% { opacity: 0; transform: scale(.3); } 50% { opacity: 1; transform: scale(1.08); } 70% { transform: scale(.95); } 100% { opacity: 1; transform: none; } } @keyframes jioBounce { 0%, 20%, 50%, 80%, 100% { transform: translateY(0); } 40% { transform: translateY(-12px); } 60% { transform: translateY(-6px); } } /* Pulse */ @keyframes jioPulse { 0% { transform: scale(1); } 50% { transform: scale(1.06); } 100% { transform: scale(1); } } /* Flash */ @keyframes jioFlash { 0%, 50%, 100% { opacity: 1; } 25%, 75% { opacity: 0; } } /* RubberBand */ @keyframes jioRubberBand { 0% { transform: scale(1); } 30% { transform: scaleX(1.25) scaleY(0.75); } 40% { transform: scaleX(0.75) scaleY(1.25); } 50% { transform: scaleX(1.15) scaleY(0.85); } 65% { transform: scaleX(0.95) scaleY(1.05); } 75% { transform: scaleX(1.05) scaleY(0.95); } 100% { transform: scale(1); } } /* Shake */ @keyframes jioShake { 0%, 100% { transform: translateX(0); } 10%, 30%, 50%, 70%, 90% { transform: translateX(-4px); } 20%, 40%, 60%, 80% { transform: translateX(4px); } } /* Swing */ @keyframes jioSwing { 20% { transform: rotate(15deg); } 40% { transform: rotate(-10deg); } 60% { transform: rotate(5deg); } 80% { transform: rotate(-5deg); } 100% { transform: none; } } /* Tada */ @keyframes jioTada { 0% { transform: scale(1); } 10%, 20% { transform: scale(0.9) rotate(-3deg); } 30%, 50%, 70%, 90% { transform: scale(1.1) rotate(3deg); } 40%, 60%, 80% { transform: scale(1.1) rotate(-3deg); } 100% { transform: scale(1) rotate(0); } } /* Wobble */ @keyframes jioWobble { 0% { transform: none; } 15% { transform: translateX(-25%) rotate(-5deg); } 30% { transform: translateX(20%) rotate(3deg); } 45% { transform: translateX(-15%) rotate(-3deg); } 60% { transform: translateX(10%) rotate(2deg); } 75% { transform: translateX(-5%) rotate(-1deg); } 100% { transform: none; } } /* Slide 系列 */ @keyframes jioSlideInUp { from { opacity: 0; transform: translateY(100%); } to { opacity: 1; transform: none; } } @keyframes jioSlideInDown { from { opacity: 0; transform: translateY(-100%); } to { opacity: 1; transform: none; } } @keyframes jioSlideInLeft { from { opacity: 0; transform: translateX(-100%); } to { opacity: 1; transform: none; } } @keyframes jioSlideInRight { from { opacity: 0; transform: translateX(100%); } to { opacity: 1; transform: none; } } /* HeartBeat */ @keyframes jioHeartBeat { 0% { transform: scale(1); } 14% { transform: scale(1.3); } 28% { transform: scale(1); } 42% { transform: scale(1.3); } 70% { transform: scale(1); } 100% { transform: scale(1); } } /* Jello */ @keyframes jioJello { 0%, 100% { transform: none; } 11% { transform: skewX(-12.5deg) skewY(-12.5deg); } 22% { transform: skewX(6.25deg) skewY(6.25deg); } 33% { transform: skewX(-6.25deg) skewY(-6.25deg); } 44% { transform: skewX(3.125deg) skewY(3.125deg); } 55% { transform: skewX(-3.125deg) skewY(-3.125deg); } 66% { transform: skewX(1.5625deg) skewY(1.5625deg); } 77% { transform: skewX(-1.5625deg) skewY(-1.5625deg); } 88% { transform: skewX(0.78125deg) skewY(0.78125deg); } } /* HeadShake */ @keyframes jioHeadShake { 0% { transform: translateX(0); } 6.5% { transform: translateX(-6px) rotateY(-9deg); } 18.5% { transform: translateX(5px) rotateY(7deg); } 31.5% { transform: translateX(-3px) rotateY(-5deg); } 43.5% { transform: translateX(2px) rotateY(3deg); } 50% { transform: translateX(0); } 100% { transform: translateX(0); } } /* BounceOut — 退出动画 */ @keyframes jioBounceOut { 0% { transform: scale(1); } 25% { transform: scale(0.95); } 50% { transform: scale(1.1); } 75% { transform: scale(0.97); } 100% { transform: scale(1); opacity: 0; } } /* ZoomOut — 退出动画 */ @keyframes jioZoomOut { 0% { opacity: 1; transform: none; } 100% { opacity: 0; transform: scale(0.85); } } /* BackIn/BackOut */ @keyframes jioBackInUp { 0% { opacity: 0; transform: translateY(30px) scale(0.7); } 80% { opacity: 0.8; transform: translateY(-5px) scale(1.02); } 100% { opacity: 1; transform: none; } } @keyframes jioBackInDown { 0% { opacity: 0; transform: translateY(-30px) scale(0.7); } 80% { opacity: 0.8; transform: translateY(5px) scale(1.02); } 100% { opacity: 1; transform: none; } } /* Flip */ @keyframes jioFlip { 0% { transform: perspective(400px) rotateY(90deg); opacity: 0; } 40% { transform: perspective(400px) rotateY(-10deg); } 70% { transform: perspective(400px) rotateY(10deg); } 100% { transform: perspective(400px) rotateY(0deg); opacity: 1; } } @keyframes jioFlipInX { 0% { transform: perspective(400px) rotateX(90deg); opacity: 0; } 40% { transform: perspective(400px) rotateX(-10deg); } 70% { transform: perspective(400px) rotateX(10deg); } 100% { transform: perspective(400px) rotateX(0deg); opacity: 1; } } /* ============================================================ * Animation utility classes * ============================================================ */ .jio-anim-fade-in { animation: jioFadeIn var(--dur-base, .4s) var(--ease-out, ease) both; } .jio-anim-fade-up { animation: jioFadeInUp var(--dur-base, .4s) var(--ease-out, ease) both; } .jio-anim-fade-down { animation: jioFadeInDown var(--dur-base, .4s) var(--ease-out, ease) both; } .jio-anim-fade-left { animation: jioFadeInLeft var(--dur-base, .4s) var(--ease-out, ease) both; } .jio-anim-fade-right { animation: jioFadeInRight var(--dur-base, .4s) var(--ease-out, ease) both; } .jio-anim-zoom-in { animation: jioZoomIn var(--dur-base, .4s) var(--ease-out, ease) both; } .jio-anim-zoom-in-up { animation: jioZoomInUp var(--dur-base, .4s) var(--ease-out, ease) both; } .jio-anim-bounce-in { animation: jioBounceIn .6s var(--ease-out, ease) both; } .jio-anim-bounce { animation: jioBounce 1s ease both; } .jio-anim-pulse { animation: jioPulse 1s ease infinite; } .jio-anim-flash { animation: jioFlash 1s ease both; } .jio-anim-rubber-band { animation: jioRubberBand .8s ease both; } .jio-anim-shake { animation: jioShake .5s ease both; } .jio-anim-swing { animation: jioSwing .6s var(--ease-out, ease) both; } .jio-anim-tada { animation: jioTada 1s ease both; } .jio-anim-wobble { animation: jioWobble .8s ease both; } .jio-anim-heart-beat { animation: jioHeartBeat 1.3s ease both; } .jio-anim-jello { animation: jioJello .8s ease both; } .jio-anim-head-shake { animation: jioHeadShake .8s ease both; } /* 退出动画 */ .jio-anim-bounce-out { animation: jioBounceOut .5s ease both; } .jio-anim-zoom-out { animation: jioZoomOut .3s ease both; } /* BackIn 动画 */ .jio-anim-back-in-up { animation: jioBackInUp .5s var(--ease-out, ease) both; } .jio-anim-back-in-down { animation: jioBackInDown .5s var(--ease-out, ease) both; } .jio-anim-slide-up { animation: jioSlideInUp .5s var(--ease-out, ease) both; } .jio-anim-slide-down { animation: jioSlideInDown .5s var(--ease-out, ease) both; } .jio-anim-slide-left { animation: jioSlideInLeft .5s var(--ease-out, ease) both; } .jio-anim-slide-right { animation: jioSlideInRight .5s var(--ease-out, ease) both; } .jio-anim-flip { animation: jioFlip .6s var(--ease-out, ease) both; } .jio-anim-flip-x { animation: jioFlipInX .6s var(--ease-out, ease) both; } /* ============================================================ * Duration modifiers * ============================================================ */ .jio-anim-fast { --dur-base: .2s; } .jio-anim-slow { --dur-base: .6s; } /* ============================================================ * Delay modifiers (配合 data-jio-delay 使用时为 inline, * 也可用 class 方式独立设置) * ============================================================ */ .jio-anim-delay-1 { animation-delay: .1s; } .jio-anim-delay-2 { animation-delay: .2s; } .jio-anim-delay-3 { animation-delay: .3s; } .jio-anim-delay-4 { animation-delay: .4s; } .jio-anim-delay-5 { animation-delay: .5s; } .jio-anim-delay-6 { animation-delay: .6s; } .jio-anim-delay-7 { animation-delay: .7s; } .jio-anim-delay-8 { animation-delay: .8s; } /* ============================================================ * Infinite modifier * ============================================================ */ .jio-anim-infinite { animation-iteration-count: infinite; } /* ============================================================ * Reduced-motion — 尊重用户偏好 * ============================================================ */ @media (prefers-reduced-motion: reduce) { .jio-anim-fade-in, .jio-anim-fade-up, .jio-anim-fade-down, .jio-anim-fade-left, .jio-anim-fade-right, .jio-anim-zoom-in, .jio-anim-zoom-in-up, .jio-anim-bounce-in, .jio-anim-bounce, .jio-anim-pulse, .jio-anim-flash, .jio-anim-rubber-band, .jio-anim-shake, .jio-anim-swing, .jio-anim-tada, .jio-anim-wobble, .jio-anim-heart-beat, .jio-anim-jello, .jio-anim-head-shake, .jio-anim-bounce-out, .jio-anim-zoom-out, .jio-anim-back-in-up, .jio-anim-back-in-down, .jio-anim-slide-up, .jio-anim-slide-down, .jio-anim-slide-left, .jio-anim-slide-right, .jio-anim-flip, .jio-anim-flip-x { animation: none !important; } }