LoadingSpinner.vue 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. <template>
  2. <div v-if="isLoading" class="loading-spinner">
  3. <div class="spinner-container">
  4. <div class="logo-container">
  5. <div class="logo-circle"></div>
  6. <div class="logo-text">VAVA</div>
  7. </div>
  8. <div class="loading-dots">
  9. <span class="dot"></span>
  10. <span class="dot"></span>
  11. <span class="dot"></span>
  12. </div>
  13. </div>
  14. </div>
  15. </template>
  16. <script setup lang="ts">
  17. import { ref } from 'vue'
  18. const isLoading = ref(true)
  19. </script>
  20. <style scoped>
  21. .loading-spinner {
  22. position: fixed;
  23. top: 0;
  24. left: 0;
  25. width: 100%;
  26. height: 100%;
  27. background-color: #000;
  28. display: flex;
  29. justify-content: center;
  30. align-items: center;
  31. z-index: 9999;
  32. -webkit-tap-highlight-color: transparent;
  33. touch-action: none;
  34. }
  35. .spinner-container {
  36. display: flex;
  37. flex-direction: column;
  38. align-items: center;
  39. gap: 24px;
  40. }
  41. .logo-container {
  42. position: relative;
  43. width: 80px;
  44. height: 80px;
  45. display: flex;
  46. justify-content: center;
  47. align-items: center;
  48. }
  49. .logo-circle {
  50. position: absolute;
  51. width: 100%;
  52. height: 100%;
  53. border: 2px solid rgba(255, 255, 255, 0.1);
  54. border-top-color: #fff;
  55. border-radius: 50%;
  56. animation: spin 1s linear infinite;
  57. }
  58. .logo-text {
  59. color: #fff;
  60. font-size: 24px;
  61. font-weight: 600;
  62. letter-spacing: 2px;
  63. animation: pulse 2s ease-in-out infinite;
  64. }
  65. .loading-dots {
  66. display: flex;
  67. gap: 8px;
  68. }
  69. .dot {
  70. width: 8px;
  71. height: 8px;
  72. background-color: #fff;
  73. border-radius: 50%;
  74. opacity: 0.6;
  75. animation: fade 1.4s infinite;
  76. }
  77. .dot:nth-child(2) {
  78. animation-delay: 0.2s;
  79. }
  80. .dot:nth-child(3) {
  81. animation-delay: 0.4s;
  82. }
  83. @keyframes spin {
  84. to {
  85. transform: rotate(360deg);
  86. }
  87. }
  88. @keyframes pulse {
  89. 0%,
  90. 100% {
  91. opacity: 0.6;
  92. transform: scale(0.95);
  93. }
  94. 50% {
  95. opacity: 1;
  96. transform: scale(1.05);
  97. }
  98. }
  99. @keyframes fade {
  100. 0%,
  101. 100% {
  102. opacity: 0.2;
  103. transform: scale(0.8);
  104. }
  105. 50% {
  106. opacity: 1;
  107. transform: scale(1.2);
  108. }
  109. }
  110. /* 移动端适配 */
  111. @media screen and (max-width: 768px) {
  112. .logo-container {
  113. width: 60px;
  114. height: 60px;
  115. }
  116. .logo-text {
  117. font-size: 20px;
  118. }
  119. .dot {
  120. width: 6px;
  121. height: 6px;
  122. }
  123. }
  124. /* 防止iOS橡皮筋效果 */
  125. .loading-spinner {
  126. overscroll-behavior: none;
  127. -webkit-overflow-scrolling: touch;
  128. }
  129. </style>