1
This commit is contained in:
@@ -1,785 +0,0 @@
|
||||
/* 动画效果库 - 为项目添加丰富的动画效果 */
|
||||
|
||||
/* ===== 基础动画关键帧 ===== */
|
||||
@keyframes fadeIn {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
|
||||
@keyframes fadeInUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInDown {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInLeft {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(-30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInRight {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideInUp {
|
||||
from {
|
||||
transform: translateY(100px);
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideInDown {
|
||||
from {
|
||||
transform: translateY(-100px);
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideInLeft {
|
||||
from {
|
||||
transform: translateX(-100px);
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
transform: translateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideInRight {
|
||||
from {
|
||||
transform: translateX(100px);
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
transform: translateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes zoomIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: scale(0.3);
|
||||
}
|
||||
50% {
|
||||
opacity: 1;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes zoomOut {
|
||||
from {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
opacity: 1;
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
transform: scale(0.3);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes bounce {
|
||||
0%, 20%, 53%, 80%, 100% {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
40%, 43% {
|
||||
transform: translate3d(0, -30px, 0);
|
||||
}
|
||||
70% {
|
||||
transform: translate3d(0, -15px, 0);
|
||||
}
|
||||
90% {
|
||||
transform: translate3d(0, -4px, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes shake {
|
||||
0%, 100% {
|
||||
transform: translateX(0);
|
||||
}
|
||||
10%, 30%, 50%, 70%, 90% {
|
||||
transform: translateX(-10px);
|
||||
}
|
||||
20%, 40%, 60%, 80% {
|
||||
transform: translateX(10px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes swing {
|
||||
20% {
|
||||
transform: rotate(15deg);
|
||||
}
|
||||
40% {
|
||||
transform: rotate(-10deg);
|
||||
}
|
||||
60% {
|
||||
transform: rotate(5deg);
|
||||
}
|
||||
80% {
|
||||
transform: rotate(-5deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes rotateIn {
|
||||
from {
|
||||
transform: rotate(-200deg);
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
transform: rotate(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes flipInX {
|
||||
from {
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
|
||||
opacity: 0;
|
||||
}
|
||||
40% {
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
|
||||
}
|
||||
60% {
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
|
||||
}
|
||||
80% {
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
|
||||
}
|
||||
to {
|
||||
transform: perspective(400px);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes flipInY {
|
||||
from {
|
||||
transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
|
||||
opacity: 0;
|
||||
}
|
||||
40% {
|
||||
transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
|
||||
}
|
||||
60% {
|
||||
transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
|
||||
}
|
||||
80% {
|
||||
transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
|
||||
}
|
||||
to {
|
||||
transform: perspective(400px);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes lightSpeedIn {
|
||||
from {
|
||||
transform: translate3d(100%, 0, 0) skewX(-30deg);
|
||||
opacity: 0;
|
||||
}
|
||||
60% {
|
||||
transform: skewX(20deg);
|
||||
opacity: 1;
|
||||
}
|
||||
80% {
|
||||
transform: skewX(-5deg);
|
||||
}
|
||||
to {
|
||||
transform: translate3d(0, 0, 0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes rubberBand {
|
||||
from {
|
||||
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);
|
||||
}
|
||||
to {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes wobble {
|
||||
from {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
15% {
|
||||
transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
|
||||
}
|
||||
30% {
|
||||
transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
|
||||
}
|
||||
45% {
|
||||
transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
|
||||
}
|
||||
60% {
|
||||
transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
|
||||
}
|
||||
75% {
|
||||
transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
|
||||
}
|
||||
to {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes tada {
|
||||
from {
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
10%, 20% {
|
||||
transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg);
|
||||
}
|
||||
30%, 50%, 70%, 90% {
|
||||
transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
|
||||
}
|
||||
40%, 60%, 80% {
|
||||
transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
|
||||
}
|
||||
to {
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes heartBeat {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
14% {
|
||||
transform: scale(1.3);
|
||||
}
|
||||
28% {
|
||||
transform: scale(1);
|
||||
}
|
||||
42% {
|
||||
transform: scale(1.3);
|
||||
}
|
||||
70% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes hinge {
|
||||
0% {
|
||||
transform: rotate(0);
|
||||
transform-origin: top left;
|
||||
animation-timing-function: ease-in-out;
|
||||
}
|
||||
20%, 60% {
|
||||
transform: rotate(80deg);
|
||||
transform-origin: top left;
|
||||
animation-timing-function: ease-in-out;
|
||||
}
|
||||
40% {
|
||||
transform: rotate(60deg);
|
||||
transform-origin: top left;
|
||||
animation-timing-function: ease-in-out;
|
||||
}
|
||||
80% {
|
||||
transform: rotate(60deg) translateY(0);
|
||||
transform-origin: top left;
|
||||
animation-timing-function: ease-in-out;
|
||||
}
|
||||
100% {
|
||||
transform: translateY(700px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes rollIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes rollOut {
|
||||
from {
|
||||
opacity: 1;
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);
|
||||
}
|
||||
}
|
||||
|
||||
/* ===== 动画类 ===== */
|
||||
.animate {
|
||||
animation-duration: 1s;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
|
||||
.animate.infinite {
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
|
||||
.animate.delay-1s {
|
||||
animation-delay: 1s;
|
||||
}
|
||||
|
||||
.animate.delay-2s {
|
||||
animation-delay: 2s;
|
||||
}
|
||||
|
||||
.animate.delay-3s {
|
||||
animation-delay: 3s;
|
||||
}
|
||||
|
||||
.animate.delay-4s {
|
||||
animation-delay: 4s;
|
||||
}
|
||||
|
||||
.animate.delay-5s {
|
||||
animation-delay: 5s;
|
||||
}
|
||||
|
||||
.animate.fast {
|
||||
animation-duration: 0.5s;
|
||||
}
|
||||
|
||||
.animate.slow {
|
||||
animation-duration: 2s;
|
||||
}
|
||||
|
||||
.animate.slower {
|
||||
animation-duration: 3s;
|
||||
}
|
||||
|
||||
/* ===== 淡入动画 ===== */
|
||||
.fade-in {
|
||||
animation-name: fadeIn;
|
||||
}
|
||||
|
||||
.fade-in-up {
|
||||
animation-name: fadeInUp;
|
||||
}
|
||||
|
||||
.fade-in-down {
|
||||
animation-name: fadeInDown;
|
||||
}
|
||||
|
||||
.fade-in-left {
|
||||
animation-name: fadeInLeft;
|
||||
}
|
||||
|
||||
.fade-in-right {
|
||||
animation-name: fadeInRight;
|
||||
}
|
||||
|
||||
/* ===== 滑入动画 ===== */
|
||||
.slide-in-up {
|
||||
animation-name: slideInUp;
|
||||
}
|
||||
|
||||
.slide-in-down {
|
||||
animation-name: slideInDown;
|
||||
}
|
||||
|
||||
.slide-in-left {
|
||||
animation-name: slideInLeft;
|
||||
}
|
||||
|
||||
.slide-in-right {
|
||||
animation-name: slideInRight;
|
||||
}
|
||||
|
||||
/* ===== 缩放动画 ===== */
|
||||
.zoom-in {
|
||||
animation-name: zoomIn;
|
||||
}
|
||||
|
||||
.zoom-out {
|
||||
animation-name: zoomOut;
|
||||
}
|
||||
|
||||
/* ===== 特殊效果动画 ===== */
|
||||
.bounce {
|
||||
animation-name: bounce;
|
||||
}
|
||||
|
||||
.pulse {
|
||||
animation-name: pulse;
|
||||
}
|
||||
|
||||
.shake {
|
||||
animation-name: shake;
|
||||
}
|
||||
|
||||
.swing {
|
||||
animation-name: swing;
|
||||
}
|
||||
|
||||
.rotate-in {
|
||||
animation-name: rotateIn;
|
||||
}
|
||||
|
||||
.flip-in-x {
|
||||
animation-name: flipInX;
|
||||
}
|
||||
|
||||
.flip-in-y {
|
||||
animation-name: flipInY;
|
||||
}
|
||||
|
||||
.light-speed-in {
|
||||
animation-name: lightSpeedIn;
|
||||
}
|
||||
|
||||
.rubber-band {
|
||||
animation-name: rubberBand;
|
||||
}
|
||||
|
||||
.wobble {
|
||||
animation-name: wobble;
|
||||
}
|
||||
|
||||
.tada {
|
||||
animation-name: tada;
|
||||
}
|
||||
|
||||
.heart-beat {
|
||||
animation-name: heartBeat;
|
||||
}
|
||||
|
||||
.hinge {
|
||||
animation-name: hinge;
|
||||
}
|
||||
|
||||
.roll-in {
|
||||
animation-name: rollIn;
|
||||
}
|
||||
|
||||
.roll-out {
|
||||
animation-name: rollOut;
|
||||
}
|
||||
|
||||
/* ===== 悬停动画 ===== */
|
||||
.hover-lift {
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
.hover-lift:hover {
|
||||
transform: translateY(-10px);
|
||||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.hover-scale {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.hover-scale:hover {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.hover-rotate {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.hover-rotate:hover {
|
||||
transform: rotate(5deg);
|
||||
}
|
||||
|
||||
.hover-glow {
|
||||
transition: box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
.hover-glow:hover {
|
||||
box-shadow: 0 0 20px rgba(52, 152, 219, 0.5);
|
||||
}
|
||||
|
||||
.hover-bounce {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.hover-bounce:hover {
|
||||
animation: bounce 0.6s ease;
|
||||
}
|
||||
|
||||
/* ===== 滚动触发动画 ===== */
|
||||
.scroll-animate {
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
transition: all 0.8s ease;
|
||||
}
|
||||
|
||||
.scroll-animate.animate-in {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
/* ===== 加载动画 ===== */
|
||||
.loading-spinner {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: 4px solid #f3f3f3;
|
||||
border-top: 4px solid #3498db;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
.loading-dots {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.loading-dots::after {
|
||||
content: '';
|
||||
animation: dots 1.5s steps(5, end) infinite;
|
||||
}
|
||||
|
||||
@keyframes dots {
|
||||
0%, 20% { content: ''; }
|
||||
40% { content: '.'; }
|
||||
60% { content: '..'; }
|
||||
80%, 100% { content: '...'; }
|
||||
}
|
||||
|
||||
/* ===== 打字机效果 ===== */
|
||||
.typewriter {
|
||||
overflow: hidden;
|
||||
border-right: 2px solid #333;
|
||||
white-space: nowrap;
|
||||
animation: typing 3.5s steps(40, end), blink-caret 0.75s step-end infinite;
|
||||
}
|
||||
|
||||
@keyframes typing {
|
||||
from { width: 0; }
|
||||
to { width: 100%; }
|
||||
}
|
||||
|
||||
@keyframes blink-caret {
|
||||
from, to { border-color: transparent; }
|
||||
50% { border-color: #333; }
|
||||
}
|
||||
|
||||
/* ===== 波浪效果 ===== */
|
||||
.wave {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.wave::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent);
|
||||
animation: wave 2s infinite;
|
||||
}
|
||||
|
||||
@keyframes wave {
|
||||
0% { left: -100%; }
|
||||
100% { left: 100%; }
|
||||
}
|
||||
|
||||
/* ===== 粒子效果 ===== */
|
||||
.particles {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.particle {
|
||||
position: absolute;
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
background: #3498db;
|
||||
border-radius: 50%;
|
||||
animation: particle-float 3s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.particle:nth-child(1) { animation-delay: 0s; }
|
||||
.particle:nth-child(2) { animation-delay: 0.5s; }
|
||||
.particle:nth-child(3) { animation-delay: 1s; }
|
||||
.particle:nth-child(4) { animation-delay: 1.5s; }
|
||||
.particle:nth-child(5) { animation-delay: 2s; }
|
||||
|
||||
@keyframes particle-float {
|
||||
0%, 100% {
|
||||
transform: translateY(0) scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
transform: translateY(-20px) scale(1.2);
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
|
||||
/* ===== 3D翻转效果 ===== */
|
||||
.flip-card {
|
||||
perspective: 1000px;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.flip-card-inner {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
transition: transform 0.8s;
|
||||
transform-style: preserve-3d;
|
||||
}
|
||||
|
||||
.flip-card:hover .flip-card-inner {
|
||||
transform: rotateY(180deg);
|
||||
}
|
||||
|
||||
.flip-card-front, .flip-card-back {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
backface-visibility: hidden;
|
||||
}
|
||||
|
||||
.flip-card-back {
|
||||
transform: rotateY(180deg);
|
||||
}
|
||||
|
||||
/* ===== 渐变背景动画 ===== */
|
||||
.gradient-bg {
|
||||
background: linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab);
|
||||
background-size: 400% 400%;
|
||||
animation: gradient-shift 15s ease infinite;
|
||||
}
|
||||
|
||||
@keyframes gradient-shift {
|
||||
0% { background-position: 0% 50%; }
|
||||
50% { background-position: 100% 50%; }
|
||||
100% { background-position: 0% 50%; }
|
||||
}
|
||||
|
||||
/* ===== 霓虹灯效果 ===== */
|
||||
.neon-text {
|
||||
color: #fff;
|
||||
text-shadow: 0 0 5px #fff, 0 0 10px #fff, 0 0 15px #0073e6, 0 0 20px #0073e6, 0 0 25px #0073e6, 0 0 30px #0073e6, 0 0 35px #0073e6;
|
||||
animation: neon-pulse 1.5s ease-in-out infinite alternate;
|
||||
}
|
||||
|
||||
@keyframes neon-pulse {
|
||||
from { text-shadow: 0 0 5px #fff, 0 0 10px #fff, 0 0 15px #0073e6, 0 0 20px #0073e6, 0 0 25px #0073e6, 0 0 30px #0073e6, 0 0 35px #0073e6; }
|
||||
to { text-shadow: 0 0 2px #fff, 0 0 4px #fff, 0 0 6px #0073e6, 0 0 8px #0073e6, 0 0 10px #0073e6, 0 0 12px #0073e6, 0 0 14px #0073e6; }
|
||||
}
|
||||
|
||||
/* ===== 响应式动画 ===== */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.animate,
|
||||
.hover-lift,
|
||||
.hover-scale,
|
||||
.hover-rotate,
|
||||
.hover-glow,
|
||||
.hover-bounce {
|
||||
animation: none !important;
|
||||
transition: none !important;
|
||||
transform: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* ===== 动画工具类 ===== */
|
||||
.animate-on-scroll {
|
||||
opacity: 0;
|
||||
transform: translateY(50px);
|
||||
transition: all 0.8s ease;
|
||||
}
|
||||
|
||||
.animate-on-scroll.visible {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.animate-stagger > * {
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
transition: all 0.6s ease;
|
||||
}
|
||||
|
||||
.animate-stagger.visible > * {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.animate-stagger.visible > *:nth-child(1) { transition-delay: 0.1s; }
|
||||
.animate-stagger.visible > *:nth-child(2) { transition-delay: 0.2s; }
|
||||
.animate-stagger.visible > *:nth-child(3) { transition-delay: 0.3s; }
|
||||
.animate-stagger.visible > *:nth-child(4) { transition-delay: 0.4s; }
|
||||
.animate-stagger.visible > *:nth-child(5) { transition-delay: 0.5s; }
|
||||
.animate-stagger.visible > *:nth-child(6) { transition-delay: 0.6s; }
|
||||
761
src/assets/css/animations.less
Normal file
761
src/assets/css/animations.less
Normal file
@@ -0,0 +1,761 @@
|
||||
// 动画效果库 - LESS版本
|
||||
@import './variables.less';
|
||||
|
||||
// ===== 动画变量 =====
|
||||
@animation-duration: @animation-duration-base;
|
||||
@animation-timing: @animation-timing-base;
|
||||
@animation-fill-mode: both;
|
||||
|
||||
// ===== 基础动画关键帧 =====
|
||||
@keyframes fadeIn {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
|
||||
@keyframes fadeInUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInDown {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInLeft {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(-30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInRight {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideInUp {
|
||||
from {
|
||||
transform: translateY(100px);
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideInDown {
|
||||
from {
|
||||
transform: translateY(-100px);
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideInLeft {
|
||||
from {
|
||||
transform: translateX(-100px);
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
transform: translateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideInRight {
|
||||
from {
|
||||
transform: translateX(100px);
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
transform: translateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes zoomIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: scale(0.3);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes zoomOut {
|
||||
from {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
transform: scale(0.3);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes bounce {
|
||||
0%, 20%, 53%, 80%, 100% {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
40%, 43% {
|
||||
transform: translate3d(0, -30px, 0);
|
||||
}
|
||||
70% {
|
||||
transform: translate3d(0, -15px, 0);
|
||||
}
|
||||
90% {
|
||||
transform: translate3d(0, -4px, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
from {
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
50% {
|
||||
transform: scale3d(1.05, 1.05, 1.05);
|
||||
}
|
||||
to {
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes shake {
|
||||
0%, 100% {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
10%, 30%, 50%, 70%, 90% {
|
||||
transform: translate3d(-10px, 0, 0);
|
||||
}
|
||||
20%, 40%, 60%, 80% {
|
||||
transform: translate3d(10px, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes swing {
|
||||
20% {
|
||||
transform: rotate(15deg);
|
||||
}
|
||||
40% {
|
||||
transform: rotate(-10deg);
|
||||
}
|
||||
60% {
|
||||
transform: rotate(5deg);
|
||||
}
|
||||
80% {
|
||||
transform: rotate(-5deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes rotate {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes flip {
|
||||
0% {
|
||||
transform: perspective(400px) rotateY(0);
|
||||
}
|
||||
40% {
|
||||
transform: perspective(400px) rotateY(90deg);
|
||||
}
|
||||
60% {
|
||||
transform: perspective(400px) rotateY(180deg);
|
||||
}
|
||||
80% {
|
||||
transform: perspective(400px) rotateY(270deg);
|
||||
}
|
||||
100% {
|
||||
transform: perspective(400px) rotateY(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes lightSpeedIn {
|
||||
from {
|
||||
transform: translate3d(100%, 0, 0) skewX(-30deg);
|
||||
opacity: 0;
|
||||
}
|
||||
60% {
|
||||
transform: skewX(20deg);
|
||||
opacity: 1;
|
||||
}
|
||||
80% {
|
||||
transform: skewX(-5deg);
|
||||
opacity: 1;
|
||||
}
|
||||
to {
|
||||
transform: translate3d(0, 0, 0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes rubberBand {
|
||||
from {
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
30% {
|
||||
transform: scale3d(1.25, 0.75, 1);
|
||||
}
|
||||
40% {
|
||||
transform: scale3d(0.75, 1.25, 1);
|
||||
}
|
||||
50% {
|
||||
transform: scale3d(1.15, 0.85, 1);
|
||||
}
|
||||
65% {
|
||||
transform: scale3d(0.95, 1.05, 1);
|
||||
}
|
||||
75% {
|
||||
transform: scale3d(1.05, 0.95, 1);
|
||||
}
|
||||
to {
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes wobble {
|
||||
0% {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
15% {
|
||||
transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
|
||||
}
|
||||
30% {
|
||||
transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
|
||||
}
|
||||
45% {
|
||||
transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
|
||||
}
|
||||
60% {
|
||||
transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
|
||||
}
|
||||
75% {
|
||||
transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
|
||||
}
|
||||
100% {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes tada {
|
||||
0% {
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
10%, 20% {
|
||||
transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg);
|
||||
}
|
||||
30%, 50%, 70%, 90% {
|
||||
transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
|
||||
}
|
||||
40%, 60%, 80% {
|
||||
transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
|
||||
}
|
||||
100% {
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes heartBeat {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
14% {
|
||||
transform: scale(1.3);
|
||||
}
|
||||
28% {
|
||||
transform: scale(1);
|
||||
}
|
||||
42% {
|
||||
transform: scale(1.3);
|
||||
}
|
||||
70% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes hinge {
|
||||
0% {
|
||||
transform: rotate(0);
|
||||
transform-origin: top left;
|
||||
animation-timing-function: ease-in-out;
|
||||
}
|
||||
20%, 60% {
|
||||
transform: rotate(80deg);
|
||||
transform-origin: top left;
|
||||
animation-timing-function: ease-in-out;
|
||||
}
|
||||
40%, 80% {
|
||||
transform: rotate(60deg);
|
||||
transform-origin: top left;
|
||||
animation-timing-function: ease-in-out;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
transform: translate3d(0, 700px, 0);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes roll {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 基础动画类 =====
|
||||
.animate {
|
||||
animation-duration: @animation-duration;
|
||||
animation-fill-mode: @animation-fill-mode;
|
||||
animation-timing-function: @animation-timing;
|
||||
}
|
||||
|
||||
// 淡入动画
|
||||
.fade-in { animation-name: fadeIn; }
|
||||
.fade-in-up { animation-name: fadeInUp; }
|
||||
.fade-in-down { animation-name: fadeInDown; }
|
||||
.fade-in-left { animation-name: fadeInLeft; }
|
||||
.fade-in-right { animation-name: fadeInRight; }
|
||||
|
||||
// 滑入动画
|
||||
.slide-in-up { animation-name: slideInUp; }
|
||||
.slide-in-down { animation-name: slideInDown; }
|
||||
.slide-in-left { animation-name: slideInLeft; }
|
||||
.slide-in-right { animation-name: slideInRight; }
|
||||
|
||||
// 缩放动画
|
||||
.zoom-in { animation-name: zoomIn; }
|
||||
.zoom-out { animation-name: zoomOut; }
|
||||
|
||||
// 特殊动画
|
||||
.bounce { animation-name: bounce; }
|
||||
.pulse { animation-name: pulse; }
|
||||
.shake { animation-name: shake; }
|
||||
.swing { animation-name: swing; }
|
||||
.rotate { animation-name: rotate; }
|
||||
.flip { animation-name: flip; }
|
||||
.light-speed-in { animation-name: lightSpeedIn; }
|
||||
.rubber-band { animation-name: rubberBand; }
|
||||
.wobble { animation-name: wobble; }
|
||||
.tada { animation-name: tada; }
|
||||
.heart-beat { animation-name: heartBeat; }
|
||||
.hinge { animation-name: hinge; }
|
||||
.roll { animation-name: roll; }
|
||||
|
||||
// ===== 动画时长 =====
|
||||
.duration-0_5s { animation-duration: 0.5s; }
|
||||
.duration-1s { animation-duration: 1s; }
|
||||
.duration-1_5s { animation-duration: 1.5s; }
|
||||
.duration-2s { animation-duration: 2s; }
|
||||
.duration-3s { animation-duration: 3s; }
|
||||
|
||||
// ===== 动画延迟 =====
|
||||
.delay-0_5s { animation-delay: 0.5s; }
|
||||
.delay-1s { animation-delay: 1s; }
|
||||
.delay-1_5s { animation-delay: 1.5s; }
|
||||
.delay-2s { animation-delay: 2s; }
|
||||
.delay-3s { animation-delay: 3s; }
|
||||
|
||||
// ===== 动画重复 =====
|
||||
.infinite { animation-iteration-count: infinite; }
|
||||
.repeat-2 { animation-iteration-count: 2; }
|
||||
.repeat-3 { animation-iteration-count: 3; }
|
||||
|
||||
// ===== 悬停动画效果 =====
|
||||
.hover-lift {
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
}
|
||||
|
||||
.hover-scale {
|
||||
transition: transform 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
}
|
||||
|
||||
.hover-glow {
|
||||
transition: box-shadow 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 0 20px rgba(0, 123, 255, 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
.hover-rotate {
|
||||
transition: transform 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
transform: rotate(5deg);
|
||||
}
|
||||
}
|
||||
|
||||
.hover-bounce {
|
||||
transition: transform 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
animation: bounce 0.6s ease;
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 滚动触发动画 =====
|
||||
.scroll-animate {
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
transition: all 0.8s ease;
|
||||
|
||||
&.animate-in {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 交错动画 =====
|
||||
.animate-stagger {
|
||||
> * {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
transition: all 0.6s ease;
|
||||
|
||||
&:nth-child(1) { transition-delay: 0.1s; }
|
||||
&:nth-child(2) { transition-delay: 0.2s; }
|
||||
&:nth-child(3) { transition-delay: 0.3s; }
|
||||
&:nth-child(4) { transition-delay: 0.4s; }
|
||||
&:nth-child(5) { transition-delay: 0.5s; }
|
||||
&:nth-child(6) { transition-delay: 0.6s; }
|
||||
|
||||
&.animate-in {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 加载指示器 =====
|
||||
.loading-spinner {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: 4px solid #f3f3f3;
|
||||
border-top: 4px solid #3498db;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
// ===== 打字机效果 =====
|
||||
.typewriter {
|
||||
overflow: hidden;
|
||||
border-right: 2px solid #000;
|
||||
white-space: nowrap;
|
||||
animation: typing 3.5s steps(40, end), blink-caret 0.75s step-end infinite;
|
||||
}
|
||||
|
||||
@keyframes typing {
|
||||
from { width: 0; }
|
||||
to { width: 100%; }
|
||||
}
|
||||
|
||||
@keyframes blink-caret {
|
||||
from, to { border-color: transparent; }
|
||||
50% { border-color: #000; }
|
||||
}
|
||||
|
||||
// ===== 波浪效果 =====
|
||||
.wave {
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(45deg, transparent 30%, rgba(255, 255, 255, 0.3) 50%, transparent 70%);
|
||||
animation: wave 2s infinite;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes wave {
|
||||
0% { transform: translateX(-100%); }
|
||||
100% { transform: translateX(100%); }
|
||||
}
|
||||
|
||||
// ===== 粒子效果 =====
|
||||
.particles {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
border-radius: 50%;
|
||||
animation: float 6s infinite;
|
||||
}
|
||||
|
||||
&::before {
|
||||
left: 20%;
|
||||
animation-delay: 0s;
|
||||
}
|
||||
|
||||
&::after {
|
||||
right: 20%;
|
||||
animation-delay: 3s;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes float {
|
||||
0%, 100% { transform: translateY(0px) rotate(0deg); opacity: 1; }
|
||||
50% { transform: translateY(-20px) rotate(180deg); opacity: 0.5; }
|
||||
}
|
||||
|
||||
// ===== 3D翻转卡片 =====
|
||||
.flip-card {
|
||||
perspective: 1000px;
|
||||
|
||||
.flip-card-inner {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
transition: transform 0.6s;
|
||||
transform-style: preserve-3d;
|
||||
|
||||
&:hover {
|
||||
transform: rotateY(180deg);
|
||||
}
|
||||
}
|
||||
|
||||
.flip-card-front,
|
||||
.flip-card-back {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
backface-visibility: hidden;
|
||||
}
|
||||
|
||||
.flip-card-back {
|
||||
transform: rotateY(180deg);
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 渐变背景动画 =====
|
||||
.gradient-bg {
|
||||
background: linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab);
|
||||
background-size: 400% 400%;
|
||||
animation: gradient 15s ease infinite;
|
||||
}
|
||||
|
||||
@keyframes gradient {
|
||||
0% { background-position: 0% 50%; }
|
||||
50% { background-position: 100% 50%; }
|
||||
100% { background-position: 0% 50%; }
|
||||
}
|
||||
|
||||
// ===== 霓虹文字效果 =====
|
||||
.neon-text {
|
||||
color: #fff;
|
||||
text-shadow:
|
||||
0 0 5px #fff,
|
||||
0 0 10px #fff,
|
||||
0 0 15px #0073e6,
|
||||
0 0 20px #0073e6,
|
||||
0 0 25px #0073e6,
|
||||
0 0 30px #0073e6,
|
||||
0 0 35px #0073e6;
|
||||
animation: neon-pulse 1.5s ease-in-out infinite alternate;
|
||||
}
|
||||
|
||||
@keyframes neon-pulse {
|
||||
from { text-shadow: 0 0 5px #fff, 0 0 10px #fff, 0 0 15px #0073e6, 0 0 20px #0073e6, 0 0 25px #0073e6, 0 0 30px #0073e6, 0 0 35px #0073e6; }
|
||||
to { text-shadow: 0 0 2px #fff, 0 0 4px #fff, 0 0 6px #0073e6, 0 0 8px #0073e6, 0 0 10px #0073e6, 0 0 12px #0073e6, 0 0 14px #0073e6; }
|
||||
}
|
||||
|
||||
// ===== 滚动进度条 =====
|
||||
.scroll-progress-bar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 0%;
|
||||
height: 3px;
|
||||
background: linear-gradient(90deg, #0073e6, #00d4ff);
|
||||
z-index: 9999;
|
||||
transition: width 0.1s ease;
|
||||
}
|
||||
|
||||
// ===== 视差滚动元素 =====
|
||||
.parallax {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
.parallax-bg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 120%;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
transform: translateZ(0);
|
||||
will-change: transform;
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 浮动粒子 =====
|
||||
.floating-particles {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
pointer-events: none;
|
||||
z-index: 1;
|
||||
|
||||
.floating-particle {
|
||||
position: absolute;
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
background: rgba(255, 255, 255, 0.6);
|
||||
border-radius: 50%;
|
||||
animation: float-particle 8s infinite linear;
|
||||
|
||||
&:nth-child(1) { left: 10%; animation-delay: 0s; animation-duration: 8s; }
|
||||
&:nth-child(2) { left: 20%; animation-delay: 1s; animation-duration: 10s; }
|
||||
&:nth-child(3) { left: 30%; animation-delay: 2s; animation-duration: 12s; }
|
||||
&:nth-child(4) { left: 40%; animation-delay: 3s; animation-duration: 9s; }
|
||||
&:nth-child(5) { left: 50%; animation-delay: 4s; animation-duration: 11s; }
|
||||
&:nth-child(6) { left: 60%; animation-delay: 5s; animation-duration: 7s; }
|
||||
&:nth-child(7) { left: 70%; animation-delay: 6s; animation-duration: 13s; }
|
||||
&:nth-child(8) { left: 80%; animation-delay: 7s; animation-duration: 8s; }
|
||||
&:nth-child(9) { left: 90%; animation-delay: 8s; animation-duration: 10s; }
|
||||
&:nth-child(10) { left: 95%; animation-delay: 9s; animation-duration: 12s; }
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes float-particle {
|
||||
0% {
|
||||
transform: translateY(100vh) scale(0);
|
||||
opacity: 0;
|
||||
}
|
||||
10% {
|
||||
opacity: 1;
|
||||
}
|
||||
90% {
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
transform: translateY(-100px) scale(1);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 文字发光效果 =====
|
||||
.text-glow {
|
||||
text-shadow:
|
||||
0 0 5px currentColor,
|
||||
0 0 10px currentColor,
|
||||
0 0 15px currentColor,
|
||||
0 0 20px currentColor;
|
||||
animation: text-glow-pulse 2s ease-in-out infinite alternate;
|
||||
}
|
||||
|
||||
@keyframes text-glow-pulse {
|
||||
from { text-shadow: 0 0 5px currentColor, 0 0 10px currentColor, 0 0 15px currentColor, 0 0 20px currentColor; }
|
||||
to { text-shadow: 0 0 10px currentColor, 0 0 20px currentColor, 0 0 30px currentColor, 0 0 40px currentColor; }
|
||||
}
|
||||
|
||||
// ===== 响应式动画考虑 =====
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 移动端动画优化 =====
|
||||
@media (max-width: 768px) {
|
||||
.floating-particles {
|
||||
display: none; // 移动端隐藏浮动粒子以提升性能
|
||||
}
|
||||
|
||||
.animate {
|
||||
animation-duration: 0.8s; // 移动端减少动画时长
|
||||
}
|
||||
|
||||
.scroll-animate {
|
||||
transform: translateY(20px); // 移动端减少移动距离
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 性能优化 =====
|
||||
.animate,
|
||||
.hover-lift,
|
||||
.hover-scale,
|
||||
.hover-glow,
|
||||
.hover-rotate,
|
||||
.hover-bounce {
|
||||
will-change: transform, opacity;
|
||||
transform: translate3d(0, 0, 0); // 启用硬件加速
|
||||
}
|
||||
|
||||
// ===== 动画工具类 =====
|
||||
.animation-paused { animation-play-state: paused; }
|
||||
.animation-running { animation-play-state: running; }
|
||||
.animation-reverse { animation-direction: reverse; }
|
||||
.animation-alternate { animation-direction: alternate; }
|
||||
.animation-alternate-reverse { animation-direction: alternate-reverse; }
|
||||
@@ -1,39 +0,0 @@
|
||||
|
||||
|
||||
.scrollToContentWrapper {
|
||||
height: 6em;
|
||||
text-align: center;
|
||||
z-index: 5000;
|
||||
}
|
||||
|
||||
.scrollToContentWrapper>a.scrollToContent {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
margin-top: -3em;
|
||||
background: lightyellow;
|
||||
width: 4.8em;
|
||||
height: 4.8em;
|
||||
line-height: 5.6em;
|
||||
border: 1px solid #eee;
|
||||
border-radius: 50%;
|
||||
background-color: #fff;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.scrollToContentWrapper>a.scrollToContent:hover {
|
||||
background-color: #000 !important;
|
||||
border-color: #111;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.scrollToContentWrapper>a.scrollToContent:hover img {
|
||||
-webkit-filter: invert(100%);
|
||||
filter: invert(100%);
|
||||
}
|
||||
|
||||
.scrollToContentWrapper>a.scrollToContent>img {
|
||||
height: 1.0em;
|
||||
}
|
||||
40
src/assets/css/common.less
Normal file
40
src/assets/css/common.less
Normal file
@@ -0,0 +1,40 @@
|
||||
// 通用样式 - LESS版本
|
||||
@import './variables.less';
|
||||
|
||||
.scrollToContentWrapper {
|
||||
height: 6em;
|
||||
text-align: center;
|
||||
z-index: 5000;
|
||||
|
||||
> a.scrollToContent {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
margin-top: -3em;
|
||||
background: lightyellow;
|
||||
width: 4.8em;
|
||||
height: 4.8em;
|
||||
line-height: 5.6em;
|
||||
border: 1px solid #eee;
|
||||
border-radius: 50%;
|
||||
background-color: #fff;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
color: #000;
|
||||
|
||||
&:hover {
|
||||
background-color: #000 !important;
|
||||
border-color: #111;
|
||||
text-decoration: none;
|
||||
|
||||
img {
|
||||
-webkit-filter: invert(100%);
|
||||
filter: invert(100%);
|
||||
}
|
||||
}
|
||||
|
||||
> img {
|
||||
height: 1.0em;
|
||||
}
|
||||
}
|
||||
}
|
||||
933
src/assets/css/common_mobile.less
Normal file
933
src/assets/css/common_mobile.less
Normal file
@@ -0,0 +1,933 @@
|
||||
// 通用移动端适配样式 - 适用于所有页面 - LESS版本
|
||||
@import './variables.less';
|
||||
|
||||
// ===== 移动端断点变量 =====
|
||||
// 使用全局变量文件中的断点
|
||||
|
||||
// ===== 移动端基础适配 =====
|
||||
@media (max-width: @mobile-breakpoint) {
|
||||
// 页面横幅移动端适配
|
||||
.page-banner {
|
||||
padding: 60px 0 40px !important;
|
||||
}
|
||||
|
||||
.banner-title {
|
||||
font-size: 2.5rem !important;
|
||||
line-height: 1.2 !important;
|
||||
}
|
||||
|
||||
.banner-subtitle {
|
||||
font-size: 1.2rem !important;
|
||||
line-height: 1.4 !important;
|
||||
}
|
||||
|
||||
// 容器移动端适配
|
||||
.container {
|
||||
padding: 0 15px !important;
|
||||
}
|
||||
|
||||
// 标题移动端适配
|
||||
.section-title {
|
||||
font-size: 2rem !important;
|
||||
line-height: 1.3 !important;
|
||||
}
|
||||
|
||||
.section-subtitle {
|
||||
font-size: 1.1rem !important;
|
||||
line-height: 1.5 !important;
|
||||
}
|
||||
|
||||
// 网格布局移动端适配
|
||||
.grid,
|
||||
.advantages-grid,
|
||||
.areas-grid,
|
||||
.services-grid,
|
||||
.team-grid,
|
||||
.contact-grid,
|
||||
.tech-grid {
|
||||
grid-template-columns: 1fr !important;
|
||||
gap: 20px !important;
|
||||
}
|
||||
|
||||
// 卡片移动端适配
|
||||
.card,
|
||||
.advantage-card,
|
||||
.area-card,
|
||||
.service-item,
|
||||
.team-member,
|
||||
.contact-card,
|
||||
.tech-layer {
|
||||
padding: 25px 20px !important;
|
||||
margin-bottom: 20px !important;
|
||||
}
|
||||
|
||||
// 内容区域移动端适配
|
||||
.content-section {
|
||||
margin-bottom: 40px !important;
|
||||
}
|
||||
|
||||
.section-text {
|
||||
font-size: 1rem !important;
|
||||
line-height: 1.6 !important;
|
||||
}
|
||||
|
||||
// 图标移动端适配
|
||||
.icon,
|
||||
.service-icon,
|
||||
.advantage-icon,
|
||||
.area-icon,
|
||||
.contact-icon {
|
||||
font-size: 2.5rem !important;
|
||||
margin-bottom: 15px !important;
|
||||
}
|
||||
|
||||
// 列表移动端适配
|
||||
.feature-list,
|
||||
.advantage-features,
|
||||
.area-features {
|
||||
padding-left: 20px !important;
|
||||
|
||||
li {
|
||||
margin-bottom: 8px !important;
|
||||
font-size: 0.95rem !important;
|
||||
}
|
||||
}
|
||||
|
||||
// 时间线移动端适配
|
||||
.timeline {
|
||||
padding-left: 20px !important;
|
||||
|
||||
.timeline-item {
|
||||
margin-bottom: 30px !important;
|
||||
padding-left: 20px !important;
|
||||
|
||||
.timeline-date {
|
||||
font-size: 0.9rem !important;
|
||||
margin-bottom: 8px !important;
|
||||
}
|
||||
|
||||
.timeline-title {
|
||||
font-size: 1.1rem !important;
|
||||
margin-bottom: 10px !important;
|
||||
}
|
||||
|
||||
.timeline-content {
|
||||
font-size: 0.95rem !important;
|
||||
line-height: 1.5 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 统计数字移动端适配
|
||||
.stats-section {
|
||||
padding: 40px 0 !important;
|
||||
|
||||
.stats-grid {
|
||||
grid-template-columns: repeat(2, 1fr) !important;
|
||||
gap: 20px !important;
|
||||
}
|
||||
|
||||
.stat-item {
|
||||
text-align: center !important;
|
||||
padding: 20px 15px !important;
|
||||
|
||||
.stat-number {
|
||||
font-size: 2rem !important;
|
||||
margin-bottom: 10px !important;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 0.9rem !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 团队介绍移动端适配
|
||||
.team-section {
|
||||
.team-grid {
|
||||
grid-template-columns: 1fr !important;
|
||||
gap: 25px !important;
|
||||
}
|
||||
|
||||
.team-member {
|
||||
text-align: center !important;
|
||||
|
||||
.member-photo {
|
||||
width: 120px !important;
|
||||
height: 120px !important;
|
||||
margin: 0 auto 15px !important;
|
||||
}
|
||||
|
||||
.member-name {
|
||||
font-size: 1.2rem !important;
|
||||
margin-bottom: 8px !important;
|
||||
}
|
||||
|
||||
.member-position {
|
||||
font-size: 0.9rem !important;
|
||||
margin-bottom: 10px !important;
|
||||
}
|
||||
|
||||
.member-description {
|
||||
font-size: 0.9rem !important;
|
||||
line-height: 1.5 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 联系信息移动端适配
|
||||
.contact-section {
|
||||
.contact-grid {
|
||||
grid-template-columns: 1fr !important;
|
||||
gap: 25px !important;
|
||||
}
|
||||
|
||||
.contact-info {
|
||||
text-align: center !important;
|
||||
|
||||
.contact-icon {
|
||||
font-size: 2rem !important;
|
||||
margin-bottom: 15px !important;
|
||||
}
|
||||
|
||||
.contact-title {
|
||||
font-size: 1.1rem !important;
|
||||
margin-bottom: 8px !important;
|
||||
}
|
||||
|
||||
.contact-detail {
|
||||
font-size: 0.95rem !important;
|
||||
line-height: 1.5 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 技术栈移动端适配
|
||||
.tech-section {
|
||||
.tech-grid {
|
||||
grid-template-columns: repeat(2, 1fr) !important;
|
||||
gap: 15px !important;
|
||||
}
|
||||
|
||||
.tech-layer {
|
||||
padding: 20px 15px !important;
|
||||
text-align: center !important;
|
||||
|
||||
.tech-icon {
|
||||
font-size: 2rem !important;
|
||||
margin-bottom: 10px !important;
|
||||
}
|
||||
|
||||
.tech-name {
|
||||
font-size: 0.9rem !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 解决方案移动端适配
|
||||
.solutions-section {
|
||||
.solution-item {
|
||||
margin-bottom: 30px !important;
|
||||
padding: 20px !important;
|
||||
|
||||
.solution-icon {
|
||||
font-size: 2.5rem !important;
|
||||
margin-bottom: 15px !important;
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
.solution-title {
|
||||
font-size: 1.3rem !important;
|
||||
margin-bottom: 12px !important;
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
.solution-description {
|
||||
font-size: 0.95rem !important;
|
||||
line-height: 1.6 !important;
|
||||
text-align: center !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 优势特点移动端适配
|
||||
.advantages-section {
|
||||
.advantage-item {
|
||||
margin-bottom: 25px !important;
|
||||
padding: 20px !important;
|
||||
text-align: center !important;
|
||||
|
||||
.advantage-icon {
|
||||
font-size: 2.5rem !important;
|
||||
margin-bottom: 15px !important;
|
||||
}
|
||||
|
||||
.advantage-title {
|
||||
font-size: 1.2rem !important;
|
||||
margin-bottom: 10px !important;
|
||||
}
|
||||
|
||||
.advantage-description {
|
||||
font-size: 0.9rem !important;
|
||||
line-height: 1.5 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 服务领域移动端适配
|
||||
.areas-section {
|
||||
.area-item {
|
||||
margin-bottom: 25px !important;
|
||||
padding: 20px !important;
|
||||
text-align: center !important;
|
||||
|
||||
.area-icon {
|
||||
font-size: 2.5rem !important;
|
||||
margin-bottom: 15px !important;
|
||||
}
|
||||
|
||||
.area-title {
|
||||
font-size: 1.2rem !important;
|
||||
margin-bottom: 10px !important;
|
||||
}
|
||||
|
||||
.area-description {
|
||||
font-size: 0.9rem !important;
|
||||
line-height: 1.5 !important;
|
||||
}
|
||||
|
||||
.area-features {
|
||||
margin-top: 15px !important;
|
||||
text-align: left !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 按钮移动端适配
|
||||
.btn,
|
||||
.button {
|
||||
padding: 12px 24px !important;
|
||||
font-size: 16px !important;
|
||||
min-height: 44px !important; // 触摸友好尺寸
|
||||
width: 100% !important; // 移动端全宽按钮
|
||||
|
||||
&.btn-large {
|
||||
padding: 15px 30px !important;
|
||||
font-size: 18px !important;
|
||||
}
|
||||
|
||||
&.btn-small {
|
||||
padding: 8px 16px !important;
|
||||
font-size: 14px !important;
|
||||
}
|
||||
|
||||
&.btn-block {
|
||||
display: block !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
// 表单移动端适配
|
||||
.form-section {
|
||||
.form-group {
|
||||
margin-bottom: 20px !important;
|
||||
|
||||
label {
|
||||
display: block !important;
|
||||
margin-bottom: 8px !important;
|
||||
font-weight: 500 !important;
|
||||
font-size: 0.95rem !important;
|
||||
}
|
||||
|
||||
input,
|
||||
textarea,
|
||||
select {
|
||||
width: 100% !important;
|
||||
padding: 12px !important;
|
||||
font-size: 16px !important; // 防止iOS缩放
|
||||
border: 1px solid #ddd !important;
|
||||
border-radius: 4px !important;
|
||||
min-height: 44px !important; // 触摸友好尺寸
|
||||
|
||||
&:focus {
|
||||
outline: none !important;
|
||||
border-color: #3498db !important;
|
||||
box-shadow: 0 0 0 2px rgba(52, 152, 219, 0.2) !important;
|
||||
}
|
||||
}
|
||||
|
||||
textarea {
|
||||
min-height: 100px !important;
|
||||
resize: vertical !important;
|
||||
}
|
||||
|
||||
.form-help {
|
||||
font-size: 0.85rem !important;
|
||||
color: #666 !important;
|
||||
margin-top: 5px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.form-actions {
|
||||
text-align: center !important;
|
||||
margin-top: 30px !important;
|
||||
|
||||
.btn {
|
||||
margin: 0 5px 10px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 图片移动端适配
|
||||
.image-section {
|
||||
img {
|
||||
max-width: 100% !important;
|
||||
height: auto !important;
|
||||
border-radius: 8px !important;
|
||||
}
|
||||
|
||||
.image-caption {
|
||||
font-size: 0.9rem !important;
|
||||
color: #666 !important;
|
||||
text-align: center !important;
|
||||
margin-top: 10px !important;
|
||||
}
|
||||
}
|
||||
|
||||
// 视频移动端适配
|
||||
.video-section {
|
||||
.video-container {
|
||||
position: relative !important;
|
||||
width: 100% !important;
|
||||
height: 0 !important;
|
||||
padding-bottom: 56.25% !important; // 16:9 比例
|
||||
|
||||
iframe,
|
||||
video {
|
||||
position: absolute !important;
|
||||
top: 0 !important;
|
||||
left: 0 !important;
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
border-radius: 8px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 表格移动端适配
|
||||
.table-section {
|
||||
.table-responsive {
|
||||
overflow-x: auto !important;
|
||||
-webkit-overflow-scrolling: touch !important;
|
||||
|
||||
table {
|
||||
min-width: 600px !important;
|
||||
font-size: 0.9rem !important;
|
||||
|
||||
th,
|
||||
td {
|
||||
padding: 8px 12px !important;
|
||||
white-space: nowrap !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 分页移动端适配
|
||||
.pagination {
|
||||
display: flex !important;
|
||||
justify-content: center !important;
|
||||
flex-wrap: wrap !important;
|
||||
gap: 5px !important;
|
||||
margin: 30px 0 !important;
|
||||
|
||||
.page-item {
|
||||
.page-link {
|
||||
padding: 8px 12px !important;
|
||||
font-size: 14px !important;
|
||||
min-width: 40px !important;
|
||||
text-align: center !important;
|
||||
border-radius: 4px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 面包屑移动端适配
|
||||
.breadcrumb {
|
||||
padding: 10px 0 !important;
|
||||
font-size: 0.9rem !important;
|
||||
|
||||
.breadcrumb-item {
|
||||
margin-right: 8px !important;
|
||||
|
||||
&:not(:last-child)::after {
|
||||
content: '>' !important;
|
||||
margin-left: 8px !important;
|
||||
color: #999 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 标签移动端适配
|
||||
.tags {
|
||||
display: flex !important;
|
||||
flex-wrap: wrap !important;
|
||||
gap: 8px !important;
|
||||
margin: 15px 0 !important;
|
||||
|
||||
.tag {
|
||||
padding: 4px 8px !important;
|
||||
font-size: 0.8rem !important;
|
||||
border-radius: 12px !important;
|
||||
background: #f0f0f0 !important;
|
||||
color: #333 !important;
|
||||
}
|
||||
}
|
||||
|
||||
// 警告框移动端适配
|
||||
.alert {
|
||||
padding: 15px !important;
|
||||
margin: 20px 0 !important;
|
||||
border-radius: 4px !important;
|
||||
font-size: 0.95rem !important;
|
||||
|
||||
&.alert-success {
|
||||
background: #d4edda !important;
|
||||
border: 1px solid #c3e6cb !important;
|
||||
color: #155724 !important;
|
||||
}
|
||||
|
||||
&.alert-warning {
|
||||
background: #fff3cd !important;
|
||||
border: 1px solid #ffeaa7 !important;
|
||||
color: #856404 !important;
|
||||
}
|
||||
|
||||
&.alert-danger {
|
||||
background: #f8d7da !important;
|
||||
border: 1px solid #f5c6cb !important;
|
||||
color: #721c24 !important;
|
||||
}
|
||||
|
||||
&.alert-info {
|
||||
background: #d1ecf1 !important;
|
||||
border: 1px solid #bee5eb !important;
|
||||
color: #0c5460 !important;
|
||||
}
|
||||
}
|
||||
|
||||
// 进度条移动端适配
|
||||
.progress {
|
||||
height: 20px !important;
|
||||
margin: 15px 0 !important;
|
||||
border-radius: 10px !important;
|
||||
overflow: hidden !important;
|
||||
|
||||
.progress-bar {
|
||||
height: 100% !important;
|
||||
border-radius: 10px !important;
|
||||
font-size: 0.8rem !important;
|
||||
line-height: 20px !important;
|
||||
}
|
||||
}
|
||||
|
||||
// 模态框移动端适配
|
||||
.modal {
|
||||
.modal-dialog {
|
||||
margin: 10px !important;
|
||||
max-width: calc(100% - 20px) !important;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
border-radius: 8px !important;
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
padding: 15px 20px !important;
|
||||
|
||||
.modal-title {
|
||||
font-size: 1.2rem !important;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding: 20px !important;
|
||||
font-size: 0.95rem !important;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
padding: 15px 20px !important;
|
||||
|
||||
.btn {
|
||||
margin: 0 5px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 工具提示移动端适配
|
||||
.tooltip {
|
||||
font-size: 0.85rem !important;
|
||||
max-width: 200px !important;
|
||||
}
|
||||
|
||||
// 弹出框移动端适配
|
||||
.popover {
|
||||
max-width: 250px !important;
|
||||
font-size: 0.9rem !important;
|
||||
|
||||
.popover-header {
|
||||
font-size: 1rem !important;
|
||||
padding: 10px 15px !important;
|
||||
}
|
||||
|
||||
.popover-body {
|
||||
padding: 10px 15px !important;
|
||||
}
|
||||
}
|
||||
|
||||
// 手风琴移动端适配
|
||||
.accordion {
|
||||
.accordion-item {
|
||||
margin-bottom: 10px !important;
|
||||
border-radius: 8px !important;
|
||||
overflow: hidden !important;
|
||||
|
||||
.accordion-header {
|
||||
.accordion-button {
|
||||
padding: 15px 20px !important;
|
||||
font-size: 1rem !important;
|
||||
|
||||
&:not(.collapsed) {
|
||||
background-color: #f8f9fa !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.accordion-body {
|
||||
padding: 15px 20px !important;
|
||||
font-size: 0.95rem !important;
|
||||
line-height: 1.6 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 标签页移动端适配
|
||||
.nav-tabs {
|
||||
flex-wrap: wrap !important;
|
||||
|
||||
.nav-item {
|
||||
margin-bottom: 5px !important;
|
||||
|
||||
.nav-link {
|
||||
padding: 8px 12px !important;
|
||||
font-size: 0.9rem !important;
|
||||
border-radius: 4px !important;
|
||||
|
||||
&.active {
|
||||
background-color: #007bff !important;
|
||||
border-color: #007bff !important;
|
||||
color: white !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 导航栏移动端适配
|
||||
.navbar {
|
||||
.navbar-brand {
|
||||
font-size: 1.2rem !important;
|
||||
}
|
||||
|
||||
.navbar-nav {
|
||||
.nav-link {
|
||||
padding: 10px 15px !important;
|
||||
font-size: 0.95rem !important;
|
||||
border-bottom: 1px solid #eee !important;
|
||||
|
||||
&:hover {
|
||||
background-color: #f8f9fa !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 侧边栏移动端适配
|
||||
.sidebar {
|
||||
position: fixed !important;
|
||||
top: 0 !important;
|
||||
left: -100% !important;
|
||||
width: 80% !important;
|
||||
height: 100vh !important;
|
||||
background: white !important;
|
||||
z-index: 1000 !important;
|
||||
transition: left 0.3s ease !important;
|
||||
overflow-y: auto !important;
|
||||
|
||||
&.active {
|
||||
left: 0 !important;
|
||||
}
|
||||
|
||||
.sidebar-header {
|
||||
padding: 20px !important;
|
||||
border-bottom: 1px solid #eee !important;
|
||||
|
||||
.close-sidebar {
|
||||
float: right !important;
|
||||
background: none !important;
|
||||
border: none !important;
|
||||
font-size: 1.5rem !important;
|
||||
cursor: pointer !important;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-body {
|
||||
padding: 20px !important;
|
||||
}
|
||||
}
|
||||
|
||||
// 页脚移动端适配
|
||||
.footer {
|
||||
padding: 40px 0 20px !important;
|
||||
text-align: center !important;
|
||||
|
||||
.footer-content {
|
||||
margin-bottom: 30px !important;
|
||||
|
||||
.footer-section {
|
||||
margin-bottom: 25px !important;
|
||||
|
||||
.footer-title {
|
||||
font-size: 1.1rem !important;
|
||||
margin-bottom: 15px !important;
|
||||
}
|
||||
|
||||
.footer-links {
|
||||
list-style: none !important;
|
||||
padding: 0 !important;
|
||||
|
||||
li {
|
||||
margin-bottom: 8px !important;
|
||||
|
||||
a {
|
||||
color: #666 !important;
|
||||
text-decoration: none !important;
|
||||
font-size: 0.9rem !important;
|
||||
|
||||
&:hover {
|
||||
color: #333 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer-bottom {
|
||||
border-top: 1px solid #eee !important;
|
||||
padding-top: 20px !important;
|
||||
font-size: 0.85rem !important;
|
||||
color: #999 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 平板端适配 =====
|
||||
@media (min-width: @mobile-breakpoint + 1) and (max-width: @tablet-breakpoint) {
|
||||
.container {
|
||||
padding: 0 30px !important;
|
||||
}
|
||||
|
||||
.grid,
|
||||
.advantages-grid,
|
||||
.areas-grid,
|
||||
.services-grid,
|
||||
.team-grid,
|
||||
.contact-grid,
|
||||
.tech-grid {
|
||||
grid-template-columns: repeat(2, 1fr) !important;
|
||||
gap: 25px !important;
|
||||
}
|
||||
|
||||
.stats-grid {
|
||||
grid-template-columns: repeat(4, 1fr) !important;
|
||||
}
|
||||
|
||||
.tech-grid {
|
||||
grid-template-columns: repeat(3, 1fr) !important;
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 小屏幕移动端适配 =====
|
||||
@media (max-width: @small-mobile) {
|
||||
.container {
|
||||
padding: 0 10px !important;
|
||||
}
|
||||
|
||||
.banner-title {
|
||||
font-size: 2rem !important;
|
||||
}
|
||||
|
||||
.banner-subtitle {
|
||||
font-size: 1rem !important;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 1.8rem !important;
|
||||
}
|
||||
|
||||
.section-subtitle {
|
||||
font-size: 1rem !important;
|
||||
}
|
||||
|
||||
.stats-grid {
|
||||
grid-template-columns: 1fr !important;
|
||||
}
|
||||
|
||||
.card,
|
||||
.advantage-card,
|
||||
.area-card,
|
||||
.service-item,
|
||||
.team-member,
|
||||
.contact-card,
|
||||
.tech-layer {
|
||||
padding: 20px 15px !important;
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 超小屏幕移动端适配 =====
|
||||
@media (max-width: @xs-mobile) {
|
||||
.container {
|
||||
padding: 0 8px !important;
|
||||
}
|
||||
|
||||
.banner-title {
|
||||
font-size: 1.8rem !important;
|
||||
}
|
||||
|
||||
.banner-subtitle {
|
||||
font-size: 0.9rem !important;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 1.6rem !important;
|
||||
}
|
||||
|
||||
.section-subtitle {
|
||||
font-size: 0.9rem !important;
|
||||
}
|
||||
|
||||
.card,
|
||||
.advantage-card,
|
||||
.area-card,
|
||||
.service-item,
|
||||
.team-member,
|
||||
.contact-card,
|
||||
.tech-layer {
|
||||
padding: 15px 12px !important;
|
||||
}
|
||||
|
||||
.btn,
|
||||
.button {
|
||||
padding: 8px 16px !important;
|
||||
font-size: 14px !important;
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 触摸设备优化 =====
|
||||
@media (hover: none) and (pointer: coarse) {
|
||||
// 触摸设备禁用悬停效果
|
||||
.btn:hover,
|
||||
.button:hover,
|
||||
.card:hover,
|
||||
.advantage-card:hover,
|
||||
.area-card:hover,
|
||||
.service-item:hover,
|
||||
.team-member:hover,
|
||||
.contact-card:hover,
|
||||
.tech-layer:hover {
|
||||
transform: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
// 触摸设备增加触摸反馈
|
||||
.btn,
|
||||
.button,
|
||||
.card,
|
||||
.advantage-card,
|
||||
.area-card,
|
||||
.service-item,
|
||||
.team-member,
|
||||
.contact-card,
|
||||
.tech-layer {
|
||||
-webkit-tap-highlight-color: rgba(52, 152, 219, 0.3) !important;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.98) !important;
|
||||
transition: transform 0.1s ease !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 高分辨率屏幕适配 =====
|
||||
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
|
||||
.icon,
|
||||
.service-icon,
|
||||
.advantage-icon,
|
||||
.area-icon,
|
||||
.contact-icon {
|
||||
image-rendering: -webkit-optimize-contrast !important;
|
||||
image-rendering: crisp-edges !important;
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 横屏模式适配 =====
|
||||
@media (orientation: landscape) and (max-height: 500px) {
|
||||
.page-banner {
|
||||
padding: 30px 0 20px !important;
|
||||
}
|
||||
|
||||
.banner-title {
|
||||
font-size: 2rem !important;
|
||||
margin-bottom: 15px !important;
|
||||
}
|
||||
|
||||
.banner-subtitle {
|
||||
font-size: 1rem !important;
|
||||
margin-bottom: 20px !important;
|
||||
}
|
||||
|
||||
.section {
|
||||
padding: 30px 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 打印样式 =====
|
||||
@media print {
|
||||
.mobile-nav,
|
||||
.sidebar,
|
||||
.modal,
|
||||
.tooltip,
|
||||
.popover {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.container {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.section {
|
||||
padding: 20px 0 !important;
|
||||
page-break-inside: avoid !important;
|
||||
}
|
||||
|
||||
.card,
|
||||
.advantage-card,
|
||||
.area-card,
|
||||
.service-item,
|
||||
.team-member,
|
||||
.contact-card,
|
||||
.tech-layer {
|
||||
page-break-inside: avoid !important;
|
||||
margin-bottom: 15px !important;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
251
src/assets/css/content_pages.less
Normal file
251
src/assets/css/content_pages.less
Normal file
@@ -0,0 +1,251 @@
|
||||
/*PAGE*/
|
||||
|
||||
/* 导入全局变量 */
|
||||
@import './variables.less';
|
||||
|
||||
/* 使用 LESS 变量定义响应式断点 */
|
||||
@breakpoint-xs: 380px;
|
||||
@breakpoint-sm: 480px;
|
||||
@breakpoint-md: 620px;
|
||||
@breakpoint-lg: 768px;
|
||||
@breakpoint-xl: 992px;
|
||||
@breakpoint-xxl: 1200px;
|
||||
@breakpoint-xxxl: 1500px;
|
||||
@breakpoint-xxxxl: 1600px;
|
||||
|
||||
/* 间距变量 */
|
||||
@spacing-xs: 0.5em;
|
||||
@spacing-sm: 1em;
|
||||
@spacing-md: 1.5em;
|
||||
@spacing-lg: 2em;
|
||||
@spacing-xl: 3em;
|
||||
@spacing-xxl: 4em;
|
||||
@spacing-xxxl: 5em;
|
||||
@spacing-xxxxl: 7em;
|
||||
|
||||
/* 字体大小变量 */
|
||||
@font-size-xs: 0.9em;
|
||||
@font-size-sm: 1.2em;
|
||||
@font-size-md: 1.5em;
|
||||
@font-size-lg: 2.5em;
|
||||
@font-size-xl: 3em;
|
||||
|
||||
/* 布局变量 */
|
||||
@sidebar-width: 25%;
|
||||
@content-width: 75%;
|
||||
@content-padding: 4em;
|
||||
@sidebar-padding: 5em;
|
||||
|
||||
.contentPage {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
vertical-align: top;
|
||||
margin: 0 auto;
|
||||
padding-top: @spacing-xxxxl;
|
||||
min-height: 100vh;
|
||||
|
||||
/* 容器查询支持 */
|
||||
container-type: inline-size;
|
||||
container-name: content-page;
|
||||
}
|
||||
|
||||
/* CONTENT TABLES */
|
||||
|
||||
.contentTableLeft {
|
||||
width: @sidebar-width;
|
||||
padding-left: @sidebar-padding;
|
||||
padding-top: @spacing-xl;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.contentTableRight {
|
||||
width: @content-width;
|
||||
padding-top: 3.5em;
|
||||
padding-left: @content-padding;
|
||||
padding-right: @content-padding;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
/* 使用容器查询替代媒体查询 */
|
||||
@container content-page (max-width: @breakpoint-xxxxl) {
|
||||
.contentTableRight {
|
||||
padding-right: 8em;
|
||||
}
|
||||
}
|
||||
|
||||
@container content-page (max-width: @breakpoint-xxxl) {
|
||||
.contentTableRight {
|
||||
padding-right: 6em;
|
||||
}
|
||||
|
||||
.contentPage .contentPageBanner .bannerBox .bannerBoxTitle {
|
||||
font-size: @font-size-xl;
|
||||
}
|
||||
}
|
||||
|
||||
@container content-page (max-width: @breakpoint-xxl) {
|
||||
.contentPage .contentPageBanner .bannerBox .bannerBoxTitle {
|
||||
font-size: @font-size-lg;
|
||||
}
|
||||
|
||||
.contentPage .contentPageBanner .bannerBox .bread {
|
||||
width: 75%;
|
||||
}
|
||||
|
||||
.contentTableLeft {
|
||||
padding-left: @spacing-xl;
|
||||
padding-top: @spacing-xl;
|
||||
}
|
||||
|
||||
.contentTableRight {
|
||||
padding-left: @spacing-xl;
|
||||
padding-right: @spacing-xl;
|
||||
}
|
||||
}
|
||||
|
||||
@container content-page (max-width: @breakpoint-xl) {
|
||||
.contentPage .contentPageBanner .bannerBox .bannerBoxTitle {
|
||||
font-size: @font-size-md;
|
||||
}
|
||||
|
||||
.contentPage .contentPageBanner .bannerBox .bread {
|
||||
width: 85%;
|
||||
}
|
||||
|
||||
.contentTableLeft {
|
||||
padding-left: @spacing-lg;
|
||||
padding-top: @spacing-lg;
|
||||
}
|
||||
|
||||
.contentTableRight {
|
||||
padding-left: @spacing-lg;
|
||||
padding-right: @spacing-lg;
|
||||
}
|
||||
}
|
||||
|
||||
@container content-page (max-width: @breakpoint-lg) {
|
||||
.contentPage .contentPageBanner .bannerBox .bannerBoxTitle {
|
||||
font-size: @font-size-sm;
|
||||
}
|
||||
|
||||
.contentPage .contentPageBanner .bannerBox .bread {
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
.contentTableLeft {
|
||||
padding-left: @spacing-md;
|
||||
padding-top: @spacing-md;
|
||||
}
|
||||
|
||||
.contentTableRight {
|
||||
padding-left: @spacing-md;
|
||||
padding-right: @spacing-md;
|
||||
}
|
||||
}
|
||||
|
||||
@container content-page (max-width: @breakpoint-md) {
|
||||
.contentPage .contentPageBanner .bannerBox .bannerBoxTitle {
|
||||
font-size: @font-size-xs;
|
||||
}
|
||||
|
||||
.contentPage .contentPageBanner .bannerBox .bread {
|
||||
width: 95%;
|
||||
}
|
||||
|
||||
.contentTableLeft {
|
||||
padding-left: @spacing-sm;
|
||||
padding-top: @spacing-sm;
|
||||
}
|
||||
|
||||
.contentTableRight {
|
||||
padding-left: @spacing-sm;
|
||||
padding-right: @spacing-sm;
|
||||
}
|
||||
}
|
||||
|
||||
@container content-page (max-width: @breakpoint-sm) {
|
||||
.contentPage .contentPageBanner .bannerBox .bannerBoxTitle {
|
||||
font-size: @font-size-xs;
|
||||
}
|
||||
|
||||
.contentPage .contentPageBanner .bannerBox .bread {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.contentTableLeft {
|
||||
padding-left: @spacing-xs;
|
||||
padding-top: @spacing-xs;
|
||||
}
|
||||
|
||||
.contentTableRight {
|
||||
padding-left: @spacing-xs;
|
||||
padding-right: @spacing-xs;
|
||||
}
|
||||
}
|
||||
|
||||
@container content-page (max-width: @breakpoint-xs) {
|
||||
.contentPage .contentPageBanner .bannerBox .bannerBoxTitle {
|
||||
font-size: @font-size-xs;
|
||||
}
|
||||
|
||||
.contentPage .contentPageBanner .bannerBox .bread {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.contentTableLeft {
|
||||
padding-left: @spacing-xs;
|
||||
padding-top: @spacing-xs;
|
||||
}
|
||||
|
||||
.contentTableRight {
|
||||
padding-left: @spacing-xs;
|
||||
padding-right: @spacing-xs;
|
||||
}
|
||||
}
|
||||
|
||||
/* 响应式布局调整 */
|
||||
@media (max-width: @breakpoint-lg) {
|
||||
.contentPage {
|
||||
padding-top: @spacing-xxl;
|
||||
}
|
||||
|
||||
.contentTableLeft,
|
||||
.contentTableRight {
|
||||
width: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.contentTableLeft {
|
||||
padding-bottom: @spacing-lg;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: @breakpoint-md) {
|
||||
.contentPage {
|
||||
padding-top: @spacing-xl;
|
||||
}
|
||||
|
||||
.contentTableLeft {
|
||||
padding-bottom: @spacing-md;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: @breakpoint-sm) {
|
||||
.contentPage {
|
||||
padding-top: @spacing-lg;
|
||||
}
|
||||
|
||||
.contentTableLeft {
|
||||
padding-bottom: @spacing-sm;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: @breakpoint-xs) {
|
||||
.contentPage {
|
||||
padding-top: @spacing-md;
|
||||
}
|
||||
|
||||
.contentTableLeft {
|
||||
padding-bottom: @spacing-xs;
|
||||
}
|
||||
}
|
||||
602
src/assets/css/mobile_responsive.less
Normal file
602
src/assets/css/mobile_responsive.less
Normal file
@@ -0,0 +1,602 @@
|
||||
// 移动端响应式适配样式 - LESS版本
|
||||
@import './variables.less';
|
||||
|
||||
// ===== 移动端断点变量 =====
|
||||
// 使用全局变量文件中的断点
|
||||
|
||||
// ===== 移动端断点 =====
|
||||
@media (max-width: @mobile-breakpoint) {
|
||||
// 头部导航移动端适配
|
||||
.header {
|
||||
padding: 10px 0;
|
||||
|
||||
.content {
|
||||
padding: 0 15px;
|
||||
}
|
||||
}
|
||||
|
||||
// 桌面端导航隐藏
|
||||
.desktop {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
// 移动端导航显示
|
||||
.mobile {
|
||||
display: flex !important;
|
||||
}
|
||||
|
||||
// 移动端导航样式
|
||||
.mobile-nav {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.logoCell {
|
||||
.logo {
|
||||
height: 40px;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.mobileIconsCell {
|
||||
cursor: pointer;
|
||||
|
||||
img {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
// 移动端菜单样式
|
||||
.headerMobileMenu {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background: rgba(0, 0, 0, 0.9);
|
||||
z-index: 1000;
|
||||
display: none;
|
||||
overflow-y: auto;
|
||||
|
||||
&.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.menuContent {
|
||||
padding: 80px 20px 20px;
|
||||
color: white;
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
margin: 15px 0;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.2);
|
||||
padding-bottom: 15px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
font-size: 18px;
|
||||
display: block;
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.hasSubmenu {
|
||||
color: #3498db;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.subMenu {
|
||||
margin-left: 20px;
|
||||
margin-top: 10px;
|
||||
|
||||
li {
|
||||
border-bottom: none;
|
||||
margin: 10px 0;
|
||||
padding-bottom: 5px;
|
||||
|
||||
a {
|
||||
font-size: 16px;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.closeMenu {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
background: none;
|
||||
border: none;
|
||||
color: white;
|
||||
font-size: 24px;
|
||||
cursor: pointer;
|
||||
padding: 10px;
|
||||
|
||||
&:hover {
|
||||
color: #3498db;
|
||||
}
|
||||
}
|
||||
|
||||
.goBack {
|
||||
margin-top: 30px;
|
||||
padding-top: 20px;
|
||||
border-top: 2px solid rgba(255, 255, 255, 0.3);
|
||||
text-align: center;
|
||||
|
||||
a {
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
font-size: 16px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
|
||||
&:hover {
|
||||
color: #3498db;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
filter: invert(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 移动端横幅适配
|
||||
.banner {
|
||||
height: 60vh;
|
||||
min-height: 400px;
|
||||
|
||||
.banner-content {
|
||||
padding: 40px 20px;
|
||||
text-align: center;
|
||||
|
||||
.banner-title {
|
||||
font-size: 2.5rem;
|
||||
line-height: 1.2;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.banner-subtitle {
|
||||
font-size: 1.2rem;
|
||||
line-height: 1.4;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.banner-button {
|
||||
padding: 12px 24px;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 移动端内容区域适配
|
||||
.pageWidth {
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
.section {
|
||||
padding: 40px 0;
|
||||
|
||||
.section-title {
|
||||
font-size: 2rem;
|
||||
line-height: 1.3;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.section-subtitle {
|
||||
font-size: 1.1rem;
|
||||
line-height: 1.5;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
// 移动端网格布局适配
|
||||
.grid,
|
||||
.advantages-grid,
|
||||
.areas-grid,
|
||||
.services-grid,
|
||||
.team-grid,
|
||||
.contact-grid {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
// 移动端卡片适配
|
||||
.card,
|
||||
.advantage-card,
|
||||
.area-card,
|
||||
.service-card,
|
||||
.team-card,
|
||||
.contact-card {
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.card-title {
|
||||
font-size: 1.3rem;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.card-content {
|
||||
font-size: 1rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
}
|
||||
|
||||
// 移动端按钮适配
|
||||
.btn,
|
||||
.button {
|
||||
padding: 12px 24px;
|
||||
font-size: 16px;
|
||||
min-height: 44px; // 触摸友好尺寸
|
||||
|
||||
&.btn-large {
|
||||
padding: 15px 30px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
&.btn-small {
|
||||
padding: 8px 16px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
// 移动端表单适配
|
||||
.form-group {
|
||||
margin-bottom: 20px;
|
||||
|
||||
label {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
input,
|
||||
textarea,
|
||||
select {
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
font-size: 16px; // 防止iOS缩放
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
min-height: 44px; // 触摸友好尺寸
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
border-color: #3498db;
|
||||
box-shadow: 0 0 0 2px rgba(52, 152, 219, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
textarea {
|
||||
min-height: 100px;
|
||||
resize: vertical;
|
||||
}
|
||||
}
|
||||
|
||||
// 移动端图片适配
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
// 移动端图标适配
|
||||
.icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
|
||||
&.icon-large {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
&.icon-small {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
// 移动端间距适配
|
||||
.mt-mobile { margin-top: 20px !important; }
|
||||
.mb-mobile { margin-bottom: 20px !important; }
|
||||
.ml-mobile { margin-left: 15px !important; }
|
||||
.mr-mobile { margin-right: 15px !important; }
|
||||
|
||||
.pt-mobile { padding-top: 20px !important; }
|
||||
.pb-mobile { padding-bottom: 20px !important; }
|
||||
.pl-mobile { padding-left: 15px !important; }
|
||||
.pr-mobile { padding-right: 15px !important; }
|
||||
|
||||
// 移动端隐藏元素
|
||||
.hide-mobile {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
// 移动端显示元素
|
||||
.show-mobile {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
// 移动端文本对齐
|
||||
.text-center-mobile {
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
.text-left-mobile {
|
||||
text-align: left !important;
|
||||
}
|
||||
|
||||
.text-right-mobile {
|
||||
text-align: right !important;
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 平板端适配 =====
|
||||
@media (min-width: @mobile-breakpoint + 1) and (max-width: @tablet-breakpoint) {
|
||||
.pageWidth {
|
||||
padding: 0 30px;
|
||||
}
|
||||
|
||||
.grid,
|
||||
.advantages-grid,
|
||||
.areas-grid,
|
||||
.services-grid,
|
||||
.team-grid,
|
||||
.contact-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 25px;
|
||||
}
|
||||
|
||||
.section {
|
||||
padding: 50px 0;
|
||||
}
|
||||
|
||||
.banner {
|
||||
height: 70vh;
|
||||
|
||||
.banner-content {
|
||||
padding: 60px 40px;
|
||||
|
||||
.banner-title {
|
||||
font-size: 3rem;
|
||||
}
|
||||
|
||||
.banner-subtitle {
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 小屏幕移动端适配 =====
|
||||
@media (max-width: @small-mobile) {
|
||||
.pageWidth {
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.banner {
|
||||
.banner-content {
|
||||
padding: 30px 15px;
|
||||
|
||||
.banner-title {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.banner-subtitle {
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.section {
|
||||
padding: 30px 0;
|
||||
|
||||
.section-title {
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
|
||||
.section-subtitle {
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.card,
|
||||
.advantage-card,
|
||||
.area-card,
|
||||
.service-card,
|
||||
.team-card,
|
||||
.contact-card {
|
||||
padding: 15px;
|
||||
|
||||
.card-title {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.btn,
|
||||
.button {
|
||||
padding: 10px 20px;
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 超小屏幕移动端适配 =====
|
||||
@media (max-width: @xs-mobile) {
|
||||
.pageWidth {
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
.banner {
|
||||
.banner-content {
|
||||
padding: 25px 10px;
|
||||
|
||||
.banner-title {
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
|
||||
.banner-subtitle {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.section {
|
||||
padding: 25px 0;
|
||||
|
||||
.section-title {
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
|
||||
.section-subtitle {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
}
|
||||
|
||||
.card,
|
||||
.advantage-card,
|
||||
.area-card,
|
||||
.service-card,
|
||||
.team-card,
|
||||
.contact-card {
|
||||
padding: 12px;
|
||||
|
||||
.card-title {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.btn,
|
||||
.button {
|
||||
padding: 8px 16px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 触摸设备优化 =====
|
||||
@media (hover: none) and (pointer: coarse) {
|
||||
// 触摸设备禁用悬停效果
|
||||
.hover-lift:hover,
|
||||
.hover-scale:hover,
|
||||
.hover-glow:hover,
|
||||
.hover-rotate:hover,
|
||||
.hover-bounce:hover {
|
||||
transform: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
// 触摸设备增加触摸反馈
|
||||
.btn,
|
||||
.button,
|
||||
.card,
|
||||
.advantage-card,
|
||||
.area-card,
|
||||
.service-card,
|
||||
.team-card,
|
||||
.contact-card {
|
||||
-webkit-tap-highlight-color: rgba(52, 152, 219, 0.3);
|
||||
|
||||
&:active {
|
||||
transform: scale(0.98);
|
||||
transition: transform 0.1s ease;
|
||||
}
|
||||
}
|
||||
|
||||
// 触摸设备优化菜单项
|
||||
.menuContent {
|
||||
li {
|
||||
a {
|
||||
padding: 15px 0; // 增加触摸区域
|
||||
min-height: 44px; // 触摸友好尺寸
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 高分辨率屏幕适配 =====
|
||||
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
|
||||
.logo {
|
||||
image-rendering: -webkit-optimize-contrast;
|
||||
image-rendering: crisp-edges;
|
||||
}
|
||||
|
||||
.icon {
|
||||
image-rendering: -webkit-optimize-contrast;
|
||||
image-rendering: crisp-edges;
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 横屏模式适配 =====
|
||||
@media (orientation: landscape) and (max-height: 500px) {
|
||||
.headerMobileMenu {
|
||||
.menuContent {
|
||||
padding: 60px 20px 20px;
|
||||
}
|
||||
|
||||
.closeMenu {
|
||||
top: 15px;
|
||||
right: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.banner {
|
||||
height: 100vh;
|
||||
|
||||
.banner-content {
|
||||
padding: 30px 20px;
|
||||
|
||||
.banner-title {
|
||||
font-size: 2rem;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.banner-subtitle {
|
||||
font-size: 1rem;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 打印样式 =====
|
||||
@media print {
|
||||
.headerMobileMenu,
|
||||
.mobile-nav,
|
||||
.floating-particles,
|
||||
.scroll-progress-bar {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.pageWidth {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.section {
|
||||
padding: 20px 0 !important;
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
|
||||
.card,
|
||||
.advantage-card,
|
||||
.area-card,
|
||||
.service-card,
|
||||
.team-card,
|
||||
.contact-card {
|
||||
page-break-inside: avoid;
|
||||
margin-bottom: 15px !important;
|
||||
}
|
||||
}
|
||||
279
src/assets/css/variables.less
Normal file
279
src/assets/css/variables.less
Normal file
@@ -0,0 +1,279 @@
|
||||
// ===== LESS 变量定义文件 =====
|
||||
|
||||
// ===== 颜色变量 =====
|
||||
@primary-color: #3498db;
|
||||
@primary-light: #5dade2;
|
||||
@primary-dark: #2980b9;
|
||||
@primary-lighter: #ebf3fd;
|
||||
|
||||
@success-color: #52c41a;
|
||||
@success-light: #73d13d;
|
||||
@success-dark: #389e0d;
|
||||
@success-lighter: #f6ffed;
|
||||
|
||||
@warning-color: #faad14;
|
||||
@warning-light: #ffc53d;
|
||||
@warning-dark: #d48806;
|
||||
@warning-lighter: #fffbe6;
|
||||
|
||||
@error-color: #f5222d;
|
||||
@error-light: #ff4d4f;
|
||||
@error-dark: #cf1322;
|
||||
@error-lighter: #fff2f0;
|
||||
|
||||
@info-color: #1890ff;
|
||||
@info-light: #40a9ff;
|
||||
@info-dark: #096dd9;
|
||||
@info-lighter: #e6f7ff;
|
||||
|
||||
// 中性色
|
||||
@white: #ffffff;
|
||||
@black: #000000;
|
||||
@gray-1: #fafafa;
|
||||
@gray-2: #f5f5f5;
|
||||
@gray-3: #f0f0f0;
|
||||
@gray-4: #d9d9d9;
|
||||
@gray-5: #bfbfbf;
|
||||
@gray-6: #8c8c8c;
|
||||
@gray-7: #595959;
|
||||
@gray-8: #434343;
|
||||
@gray-9: #262626;
|
||||
@gray-10: #1f1f1f;
|
||||
|
||||
// 文字颜色
|
||||
@text-color: @gray-8;
|
||||
@text-color-secondary: @gray-6;
|
||||
@text-color-disabled: @gray-5;
|
||||
@heading-color: @gray-9;
|
||||
@link-color: @primary-color;
|
||||
@link-hover-color: @primary-light;
|
||||
|
||||
// 背景颜色
|
||||
@bg-color: @white;
|
||||
@bg-color-light: @gray-1;
|
||||
@bg-color-dark: @gray-2;
|
||||
|
||||
// 边框颜色
|
||||
@border-color: @gray-4;
|
||||
@border-color-light: @gray-3;
|
||||
@border-color-dark: @gray-5;
|
||||
|
||||
// ===== 字体变量 =====
|
||||
@font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
||||
@font-family-code: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace;
|
||||
|
||||
@font-size-base: 14px;
|
||||
@font-size-lg: 16px;
|
||||
@font-size-sm: 12px;
|
||||
@font-size-xs: 10px;
|
||||
|
||||
@font-size-h1: 38px;
|
||||
@font-size-h2: 30px;
|
||||
@font-size-h3: 24px;
|
||||
@font-size-h4: 20px;
|
||||
@font-size-h5: 16px;
|
||||
@font-size-h6: 14px;
|
||||
|
||||
@line-height-base: 1.5715;
|
||||
@line-height-lg: 1.5;
|
||||
@line-height-sm: 1.4;
|
||||
@line-height-xs: 1.3;
|
||||
|
||||
@font-weight-light: 300;
|
||||
@font-weight-normal: 400;
|
||||
@font-weight-medium: 500;
|
||||
@font-weight-semibold: 600;
|
||||
@font-weight-bold: 700;
|
||||
@font-weight-extrabold: 800;
|
||||
|
||||
// ===== 间距变量 =====
|
||||
@spacing-xs: 4px;
|
||||
@spacing-sm: 8px;
|
||||
@spacing-md: 16px;
|
||||
@spacing-lg: 24px;
|
||||
@spacing-xl: 32px;
|
||||
@spacing-xxl: 48px;
|
||||
@spacing-xxxl: 64px;
|
||||
|
||||
@padding-xs: @spacing-xs;
|
||||
@padding-sm: @spacing-sm;
|
||||
@padding-md: @spacing-md;
|
||||
@padding-lg: @spacing-lg;
|
||||
@padding-xl: @spacing-xl;
|
||||
|
||||
@margin-xs: @spacing-xs;
|
||||
@margin-sm: @spacing-sm;
|
||||
@margin-md: @spacing-md;
|
||||
@margin-lg: @spacing-lg;
|
||||
@margin-xl: @spacing-xl;
|
||||
|
||||
// ===== 尺寸变量 =====
|
||||
@border-radius-base: 4px;
|
||||
@border-radius-sm: 2px;
|
||||
@border-radius-lg: 8px;
|
||||
@border-radius-xl: 12px;
|
||||
@border-radius-circle: 50%;
|
||||
|
||||
@border-width-base: 1px;
|
||||
@border-width-thick: 2px;
|
||||
@border-width-thin: 0.5px;
|
||||
|
||||
// ===== 阴影变量 =====
|
||||
@box-shadow-base: 0 2px 8px rgba(0, 0, 0, 0.15);
|
||||
@box-shadow-sm: 0 1px 4px rgba(0, 0, 0, 0.1);
|
||||
@box-shadow-lg: 0 4px 16px rgba(0, 0, 0, 0.2);
|
||||
@box-shadow-xl: 0 8px 24px rgba(0, 0, 0, 0.25);
|
||||
|
||||
@text-shadow-base: 0 1px 2px rgba(0, 0, 0, 0.1);
|
||||
@text-shadow-lg: 0 2px 4px rgba(0, 0, 0, 0.2);
|
||||
|
||||
// ===== 断点变量 =====
|
||||
@screen-xs: 480px;
|
||||
@screen-sm: 576px;
|
||||
@screen-md: 768px;
|
||||
@screen-lg: 992px;
|
||||
@screen-xl: 1200px;
|
||||
@screen-xxl: 1600px;
|
||||
|
||||
@mobile-breakpoint: @screen-md;
|
||||
@tablet-breakpoint: @screen-lg;
|
||||
@desktop-breakpoint: @screen-xl;
|
||||
|
||||
// 移动端断点变量
|
||||
@small-mobile: 480px;
|
||||
@xs-mobile: 360px;
|
||||
|
||||
// ===== 动画变量 =====
|
||||
@animation-duration-base: 0.2s;
|
||||
@animation-duration-fast: 0.1s;
|
||||
@animation-duration-slow: 0.3s;
|
||||
@animation-duration-slower: 0.5s;
|
||||
|
||||
@animation-timing-base: ease;
|
||||
@animation-timing-ease-in: ease-in;
|
||||
@animation-timing-ease-out: ease-out;
|
||||
@animation-timing-ease-in-out: ease-in-out;
|
||||
@animation-timing-linear: linear;
|
||||
|
||||
@animation-delay-base: 0s;
|
||||
@animation-delay-fast: 0.1s;
|
||||
@animation-delay-slow: 0.3s;
|
||||
|
||||
// ===== Z-index 变量 =====
|
||||
@zindex-dropdown: 1000;
|
||||
@zindex-sticky: 1020;
|
||||
@zindex-fixed: 1030;
|
||||
@zindex-modal-backdrop: 1040;
|
||||
@zindex-modal: 1050;
|
||||
@zindex-popover: 1060;
|
||||
@zindex-tooltip: 1070;
|
||||
@zindex-toast: 1080;
|
||||
|
||||
// ===== 组件特定变量 =====
|
||||
|
||||
// 按钮
|
||||
@btn-height-base: 32px;
|
||||
@btn-height-lg: 40px;
|
||||
@btn-height-sm: 24px;
|
||||
@btn-padding-horizontal-base: @padding-md;
|
||||
@btn-padding-horizontal-lg: @padding-lg;
|
||||
@btn-padding-horizontal-sm: @padding-sm;
|
||||
|
||||
// 输入框
|
||||
@input-height-base: 32px;
|
||||
@input-height-lg: 40px;
|
||||
@input-height-sm: 24px;
|
||||
@input-padding-horizontal: @padding-sm;
|
||||
|
||||
// 卡片
|
||||
@card-padding-base: @padding-lg;
|
||||
@card-padding-sm: @padding-md;
|
||||
@card-padding-lg: @padding-xl;
|
||||
|
||||
// 表格
|
||||
@table-padding-vertical: @padding-sm;
|
||||
@table-padding-horizontal: @padding-md;
|
||||
|
||||
// 分页
|
||||
@pagination-item-size: 32px;
|
||||
@pagination-item-size-sm: 24px;
|
||||
|
||||
// 标签
|
||||
@tag-height: 20px;
|
||||
@tag-height-lg: 28px;
|
||||
@tag-height-sm: 16px;
|
||||
|
||||
// 徽章
|
||||
@badge-height: 20px;
|
||||
@badge-height-sm: 14px;
|
||||
@badge-height-lg: 24px;
|
||||
|
||||
// ===== 工具函数 =====
|
||||
|
||||
// 颜色混合函数
|
||||
.lighten(@color, @amount) {
|
||||
color: lighten(@color, @amount);
|
||||
}
|
||||
|
||||
.darken(@color, @amount) {
|
||||
color: darken(@color, @amount);
|
||||
}
|
||||
|
||||
// 透明度函数
|
||||
.alpha(@color, @opacity) {
|
||||
color: fade(@color, @opacity);
|
||||
}
|
||||
|
||||
// 响应式混合
|
||||
.mobile(@rules) {
|
||||
@media (max-width: @mobile-breakpoint) {
|
||||
@rules();
|
||||
}
|
||||
}
|
||||
|
||||
.tablet(@rules) {
|
||||
@media (min-width: @mobile-breakpoint + 1) and (max-width: @tablet-breakpoint) {
|
||||
@rules();
|
||||
}
|
||||
}
|
||||
|
||||
.desktop(@rules) {
|
||||
@media (min-width: @tablet-breakpoint + 1) {
|
||||
@rules();
|
||||
}
|
||||
}
|
||||
|
||||
// 触摸设备检测
|
||||
.touch-device(@rules) {
|
||||
@media (hover: none) and (pointer: coarse) {
|
||||
@rules();
|
||||
}
|
||||
}
|
||||
|
||||
// 高分辨率屏幕
|
||||
.high-dpi(@rules) {
|
||||
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
|
||||
@rules();
|
||||
}
|
||||
}
|
||||
|
||||
// 打印样式
|
||||
.print(@rules) {
|
||||
@media print {
|
||||
@rules();
|
||||
}
|
||||
}
|
||||
|
||||
// 横屏模式
|
||||
.landscape(@rules) {
|
||||
@media (orientation: landscape) and (max-height: 500px) {
|
||||
@rules();
|
||||
}
|
||||
}
|
||||
|
||||
// 减少动画偏好
|
||||
.reduced-motion(@rules) {
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
@rules();
|
||||
}
|
||||
}
|
||||
@@ -116,6 +116,7 @@ export default {
|
||||
mounted() {
|
||||
this.initHeader()
|
||||
this.initScrollListener()
|
||||
this.initMobileMenu()
|
||||
},
|
||||
methods: {
|
||||
// 封装事件监听器创建,提高代码复用性
|
||||
@@ -197,6 +198,52 @@ export default {
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// 初始化移动端菜单
|
||||
initMobileMenu() {
|
||||
// 汉堡菜单点击事件
|
||||
this.add_event_listener("hamburger", "click", () => {
|
||||
this.toggle_class("mobileMenu", "active", true);
|
||||
}, true);
|
||||
|
||||
// 返回按钮点击事件
|
||||
this.add_event_listener(".linkGoBack", "click", () => {
|
||||
this.remove_class("mobileMenu", "active", true);
|
||||
// 关闭移动端菜单后滚动到顶部
|
||||
window.scrollTo({
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
});
|
||||
|
||||
// 点击菜单项后自动关闭菜单
|
||||
const menuLinks = document.querySelectorAll('.headerMobileMenu a');
|
||||
menuLinks.forEach(link => {
|
||||
link.addEventListener('click', () => {
|
||||
this.remove_class("mobileMenu", "active", true);
|
||||
});
|
||||
});
|
||||
|
||||
// 点击菜单外部区域关闭菜单
|
||||
document.addEventListener('click', (e) => {
|
||||
const mobileMenu = document.getElementById('mobileMenu');
|
||||
const hamburger = document.getElementById('hamburger');
|
||||
|
||||
if (mobileMenu && mobileMenu.classList.contains('active') &&
|
||||
!mobileMenu.contains(e.target) &&
|
||||
!hamburger.contains(e.target)) {
|
||||
this.remove_class("mobileMenu", "active", true);
|
||||
}
|
||||
});
|
||||
|
||||
// ESC键关闭菜单
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape') {
|
||||
this.remove_class("mobileMenu", "active", true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
import './assets/css/cookieconsent.min.css'
|
||||
import './assets/css/common.css'
|
||||
import './assets/css/animations.css'
|
||||
import './assets/css/common.less'
|
||||
import './assets/css/content_pages.less'
|
||||
import './assets/css/animations.less'
|
||||
import './assets/css/mobile_responsive.less'
|
||||
import './assets/css/common_mobile.less'
|
||||
import 'swiper/css/swiper.min.css'
|
||||
import 'es6-promise/auto'
|
||||
import './static/animation_helper'
|
||||
import './static/scroll_helper'
|
||||
import Vue from 'vue'
|
||||
import App from './App.vue'
|
||||
import Vuex from 'vuex'
|
||||
|
||||
250
src/static/scroll_helper.js
Normal file
250
src/static/scroll_helper.js
Normal file
@@ -0,0 +1,250 @@
|
||||
/**
|
||||
* 滚动控制助手 - 处理页面刷新和路由切换时的滚动行为
|
||||
*/
|
||||
class ScrollHelper {
|
||||
constructor() {
|
||||
this.isInitialized = false;
|
||||
this.init();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化滚动助手
|
||||
*/
|
||||
init() {
|
||||
if (this.isInitialized) return;
|
||||
|
||||
// 监听页面加载完成事件
|
||||
this.handlePageLoad();
|
||||
|
||||
// 监听路由变化事件
|
||||
this.handleRouteChange();
|
||||
|
||||
// 监听页面刷新事件
|
||||
this.handlePageRefresh();
|
||||
|
||||
// 监听浏览器前进后退事件
|
||||
this.handleBrowserNavigation();
|
||||
|
||||
this.isInitialized = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理页面加载完成
|
||||
*/
|
||||
handlePageLoad() {
|
||||
// 页面完全加载后滚动到顶部
|
||||
if (document.readyState === 'complete') {
|
||||
this.scrollToTop();
|
||||
} else {
|
||||
window.addEventListener('load', () => {
|
||||
this.scrollToTop();
|
||||
});
|
||||
}
|
||||
|
||||
// DOM内容加载完成后也滚动到顶部
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
this.scrollToTop();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理路由变化
|
||||
*/
|
||||
handleRouteChange() {
|
||||
// 监听 Vue Router 的全局前置守卫
|
||||
if (window.Vue && window.Vue.prototype.$router) {
|
||||
window.Vue.prototype.$router.beforeEach((to, from, next) => {
|
||||
// 路由切换时滚动到顶部
|
||||
this.scrollToTop();
|
||||
next();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理页面刷新
|
||||
*/
|
||||
handlePageRefresh() {
|
||||
// 监听页面即将刷新事件
|
||||
window.addEventListener('beforeunload', () => {
|
||||
// 保存当前滚动位置到 sessionStorage
|
||||
sessionStorage.setItem('scrollPosition', window.pageYOffset);
|
||||
});
|
||||
|
||||
// 页面加载完成后检查是否需要滚动到顶部
|
||||
window.addEventListener('load', () => {
|
||||
const savedPosition = sessionStorage.getItem('scrollPosition');
|
||||
if (savedPosition) {
|
||||
// 清除保存的位置
|
||||
sessionStorage.removeItem('scrollPosition');
|
||||
// 滚动到顶部
|
||||
this.scrollToTop();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理浏览器前进后退
|
||||
*/
|
||||
handleBrowserNavigation() {
|
||||
// 监听 popstate 事件(浏览器前进后退)
|
||||
window.addEventListener('popstate', () => {
|
||||
// 延迟执行,确保路由更新完成
|
||||
setTimeout(() => {
|
||||
this.scrollToTop();
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 滚动到页面顶部
|
||||
*/
|
||||
scrollToTop(options = {}) {
|
||||
const defaultOptions = {
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: 'smooth'
|
||||
};
|
||||
|
||||
const config = { ...defaultOptions, ...options };
|
||||
|
||||
// 检查浏览器是否支持平滑滚动
|
||||
if (!this.supportsSmoothScrolling()) {
|
||||
config.behavior = 'auto';
|
||||
}
|
||||
|
||||
// 执行滚动
|
||||
window.scrollTo(config);
|
||||
|
||||
// 同时滚动 body 和 html 元素(兼容性处理)
|
||||
if (document.body) {
|
||||
document.body.scrollTop = 0;
|
||||
document.body.scrollLeft = 0;
|
||||
}
|
||||
if (document.documentElement) {
|
||||
document.documentElement.scrollTop = 0;
|
||||
document.documentElement.scrollLeft = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 滚动到指定元素
|
||||
*/
|
||||
scrollToElement(selector, options = {}) {
|
||||
const element = document.querySelector(selector);
|
||||
if (!element) return;
|
||||
|
||||
const defaultOptions = {
|
||||
behavior: 'smooth',
|
||||
block: 'start',
|
||||
inline: 'nearest'
|
||||
};
|
||||
|
||||
const config = { ...defaultOptions, ...options };
|
||||
|
||||
// 检查浏览器是否支持 scrollIntoView
|
||||
if (element.scrollIntoView) {
|
||||
element.scrollIntoView(config);
|
||||
} else {
|
||||
// 降级处理:计算元素位置并滚动
|
||||
const rect = element.getBoundingClientRect();
|
||||
const scrollTop = window.pageYOffset + rect.top;
|
||||
this.scrollToTop({ top: scrollTop, behavior: config.behavior });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查浏览器是否支持平滑滚动
|
||||
*/
|
||||
supportsSmoothScrolling() {
|
||||
return 'scrollBehavior' in document.documentElement.style;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前滚动位置
|
||||
*/
|
||||
getScrollPosition() {
|
||||
return {
|
||||
x: window.pageXOffset || document.documentElement.scrollLeft,
|
||||
y: window.pageYOffset || document.documentElement.scrollTop
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置滚动位置
|
||||
*/
|
||||
setScrollPosition(x, y, behavior = 'smooth') {
|
||||
const options = {
|
||||
top: y,
|
||||
left: x,
|
||||
behavior: this.supportsSmoothScrolling() ? behavior : 'auto'
|
||||
};
|
||||
|
||||
window.scrollTo(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* 滚动到底部
|
||||
*/
|
||||
scrollToBottom(behavior = 'smooth') {
|
||||
const scrollHeight = Math.max(
|
||||
document.body.scrollHeight,
|
||||
document.documentElement.scrollHeight,
|
||||
document.body.offsetHeight,
|
||||
document.documentElement.offsetHeight,
|
||||
document.body.clientHeight,
|
||||
document.documentElement.clientHeight
|
||||
);
|
||||
|
||||
this.scrollToTop({
|
||||
top: scrollHeight,
|
||||
behavior: behavior
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 滚动到指定百分比位置
|
||||
*/
|
||||
scrollToPercentage(percentage, behavior = 'smooth') {
|
||||
const scrollHeight = Math.max(
|
||||
document.body.scrollHeight,
|
||||
document.documentElement.scrollHeight
|
||||
);
|
||||
const targetPosition = (scrollHeight - window.innerHeight) * (percentage / 100);
|
||||
|
||||
this.scrollToTop({
|
||||
top: targetPosition,
|
||||
behavior: behavior
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 监听滚动事件
|
||||
*/
|
||||
onScroll(callback) {
|
||||
window.addEventListener('scroll', callback, { passive: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除滚动监听器
|
||||
*/
|
||||
offScroll(callback) {
|
||||
window.removeEventListener('scroll', callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 销毁滚动助手
|
||||
*/
|
||||
destroy() {
|
||||
// 清理事件监听器
|
||||
this.isInitialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 创建全局实例
|
||||
window.scrollHelper = new ScrollHelper();
|
||||
|
||||
// 导出类(如果使用模块系统)
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports = ScrollHelper;
|
||||
}
|
||||
@@ -7,13 +7,27 @@
|
||||
|
||||
<!-- 现代化横幅区域 -->
|
||||
<div class="banner" data-parallax="0.3">
|
||||
<!-- 浮动粒子背景 -->
|
||||
<div class="floating-particles">
|
||||
<div class="floating-particle"></div>
|
||||
<div class="floating-particle"></div>
|
||||
<div class="floating-particle"></div>
|
||||
<div class="floating-particle"></div>
|
||||
<div class="floating-particle"></div>
|
||||
<div class="floating-particle"></div>
|
||||
<div class="floating-particle"></div>
|
||||
<div class="floating-particle"></div>
|
||||
<div class="floating-particle"></div>
|
||||
<div class="floating-particle"></div>
|
||||
</div>
|
||||
|
||||
<swiper ref="swiper" :options="swiperOption">
|
||||
<swiper-slide v-for="banner in banners" :key="banner.img">
|
||||
<div class="banner-content">
|
||||
<img :src="banner.img" width="100%" />
|
||||
<div class="banner-overlay">
|
||||
<div class="banner-text">
|
||||
<h1 class="banner-title animate fade-in-down">{{banner.title}}</h1>
|
||||
<h1 class="banner-title animate fade-in-down text-glow">{{banner.title}}</h1>
|
||||
<p class="banner-subtitle animate fade-in-up delay-1s">{{banner.subtitle}}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user