cl-loading.uvue 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. <template>
  2. <view
  3. class="cl-loading"
  4. :class="[
  5. {
  6. 'is-dark': isDark && color == '',
  7. 'cl-loading--spin': loading,
  8. '!border-primary-500': color == 'primary',
  9. '!border-green-500': color == 'success',
  10. '!border-yellow-500': color == 'warn',
  11. '!border-red-500': color == 'error',
  12. '!border-surface-500': color == 'info',
  13. '!border-surface-700': color == 'dark',
  14. '!border-white': color == 'light',
  15. '!border-surface-300': color == 'disabled',
  16. '!border-r-transparent': true
  17. },
  18. pt.className
  19. ]"
  20. :style="{
  21. // #ifdef APP
  22. transform: `rotate(${rotate}deg)`,
  23. // #endif
  24. height: parseRpx(size!),
  25. width: parseRpx(size!),
  26. borderColor: color
  27. }"
  28. v-if="loading"
  29. >
  30. </view>
  31. </template>
  32. <script setup lang="ts">
  33. import { computed, onMounted, ref, watch } from "vue";
  34. import { isDark, parsePt, parseRpx } from "@/cool";
  35. import type { ClIconProps } from "../cl-icon/props";
  36. defineOptions({
  37. name: "cl-loading"
  38. });
  39. // 定义组件属性
  40. const props = defineProps({
  41. // 透传样式
  42. pt: {
  43. type: Object,
  44. default: () => ({})
  45. },
  46. // 是否加载中
  47. loading: {
  48. type: Boolean,
  49. default: true
  50. },
  51. // 图标大小
  52. size: {
  53. type: [Number, String],
  54. default: 24
  55. },
  56. // 图标颜色
  57. color: {
  58. type: String,
  59. default: ""
  60. }
  61. });
  62. // 透传样式类型定义
  63. type PassThrough = {
  64. className?: string;
  65. icon?: ClIconProps;
  66. };
  67. // 解析透传样式
  68. const pt = computed(() => parsePt<PassThrough>(props.pt));
  69. // 旋转角度
  70. const rotate = ref(0);
  71. // 开始旋转动画
  72. function start() {
  73. requestAnimationFrame(() => {
  74. // 增加旋转角度
  75. rotate.value += 1;
  76. // 如果仍在加载中则继续旋转
  77. if (props.loading) {
  78. start();
  79. }
  80. });
  81. }
  82. // 组件挂载后监听loading状态
  83. onMounted(() => {
  84. // #ifdef APP-UVUE
  85. watch(
  86. computed(() => props.loading),
  87. (val: boolean) => {
  88. // 当loading为true时开始旋转
  89. if (val) {
  90. start();
  91. }
  92. },
  93. {
  94. immediate: true
  95. }
  96. );
  97. // #endif
  98. });
  99. </script>
  100. <style lang="scss" scoped>
  101. .cl-loading {
  102. @apply flex flex-row items-center justify-center rounded-full;
  103. @apply border-surface-700 border-solid;
  104. border-width: 2rpx;
  105. &.is-dark {
  106. @apply border-white;
  107. }
  108. // #ifdef H5 || MP
  109. &--spin {
  110. animation: spin 2.5s linear infinite;
  111. }
  112. @keyframes spin {
  113. from {
  114. transform: rotate(0deg);
  115. }
  116. to {
  117. transform: rotate(360deg);
  118. }
  119. }
  120. // #endif
  121. }
  122. </style>