ActivityIndicator.vue 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. <template>
  2. <view
  3. class="nana-activity-indicator"
  4. :style="style"
  5. >
  6. <!-- #ifndef APP-NVUE || MP -->
  7. <svg class="chrome-spinner" viewBox="0 0 50 50">
  8. <circle cx="25" cy="25" r="20" class="single-ring" :stroke-width="props.strokeWidth" />
  9. </svg>
  10. <!-- #endif -->
  11. <!-- #ifdef APP-NVUE || MP -->
  12. <!-- #endif -->
  13. </view>
  14. </template>
  15. <script setup lang="ts">
  16. import { computed } from 'vue';
  17. import { propGetThemeVar, useTheme, type ViewStyle } from '../theme/ThemeDefine';
  18. export interface ActivityIndicatorProps {
  19. /**
  20. * 加载中圆圈颜色
  21. */
  22. color?: string,
  23. /**
  24. * 加载中圆圈颜色
  25. */
  26. size?: string|number,
  27. /**
  28. * 加载中圆圈宽度
  29. */
  30. strokeWidth?: number,
  31. /**
  32. * 自定义样式
  33. */
  34. innerStyle?: ViewStyle,
  35. }
  36. const themeContext = useTheme();
  37. const props = withDefaults(defineProps<ActivityIndicatorProps>(), {
  38. color: () => propGetThemeVar('ActivityIndicatorColor', 'primary'),
  39. size: () => propGetThemeVar('ActivityIndicatorSize', 60),
  40. })
  41. const style = computed(() => {
  42. return {
  43. borderTopColor: themeContext.resolveThemeColor(props.color),
  44. color: themeContext.resolveThemeColor(props.color),
  45. width: themeContext.resolveThemeSize(props.size),
  46. height: themeContext.resolveThemeSize(props.size),
  47. ...props.innerStyle,
  48. }
  49. });
  50. </script>
  51. <style lang="scss">
  52. /* #ifndef APP-NVUE || MP */
  53. /* 旋转动画 */
  54. @keyframes spin {
  55. 0% {
  56. transform: rotate(0deg);
  57. }
  58. 100% {
  59. transform: rotate(360deg);
  60. }
  61. }
  62. /* 线段长度变化动画 */
  63. @keyframes dash {
  64. 0% {
  65. stroke-dasharray: 10 190; /* 最短状态 */
  66. stroke-dashoffset: 0;
  67. }
  68. 50% {
  69. stroke-dasharray: 100 100; /* 最长状态 */
  70. stroke-dashoffset: -40;
  71. }
  72. 100% {
  73. stroke-dasharray: 10 190; /* 回到最短 */
  74. stroke-dashoffset: -200;
  75. }
  76. }
  77. .nana-activity-indicator {
  78. .chrome-spinner {
  79. width: 100%;
  80. height: 100%;
  81. animation: spin 1.5s linear infinite;
  82. .single-ring {
  83. fill: none;
  84. stroke-width: 5;
  85. stroke-linecap: round;
  86. stroke: currentColor; /* 单色灰色 */
  87. stroke-dasharray: 20 160; /* 控制线段长度 */
  88. animation: dash 1.5s ease-in-out infinite;
  89. }
  90. }
  91. }
  92. /* #endif */
  93. /* #ifdef APP-NVUE || MP */
  94. @keyframes spin {
  95. from {
  96. transform: rotate(0deg);
  97. }
  98. to {
  99. transform: rotate(360deg);
  100. }
  101. }
  102. .nana-activity-indicator {
  103. width: 50px;
  104. height: 50px;
  105. border: 5px solid transparent;
  106. border-top: 5px solid #3498db;
  107. border-radius: 50%;
  108. animation: spin 1s linear infinite;
  109. box-sizing: border-box;
  110. }
  111. /* #endif */
  112. </style>