su-progress.vue 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. <template>
  2. <view>
  3. <view class="flex a-center content" v-if="lineData">
  4. <view>
  5. <slot name="content"></slot>
  6. </view>
  7. </view>
  8. <view class="flex a-center" style="padding-right: 10rpx">
  9. <view
  10. class="progress-container"
  11. id="container"
  12. ref="progressContainer"
  13. :style="{ background: inBgColor }"
  14. >
  15. <view
  16. class="progress-content flex j-end"
  17. id="content"
  18. ref="progressContent"
  19. :style="{
  20. height: strokeWidth + 'px',
  21. background: bgColor,
  22. width: contentWidth,
  23. transition: `width ${duration / 1000}s ease`,
  24. }"
  25. v-if="isAnimate"
  26. >
  27. <view class="textInside flex a-center j-center" v-if="textInside && !noData">
  28. <view class="text">{{ percentage }}%</view>
  29. </view>
  30. </view>
  31. <view
  32. v-if="!isAnimate"
  33. class="progress-content flex j-end"
  34. :style="{ width: percentage + '%', height: strokeWidth + 'px', background: bgColor }"
  35. >
  36. <view class="textInside flex a-center j-center" v-if="textInside && !noData">
  37. <view class="text">{{ percentage }}%</view>
  38. </view>
  39. </view>
  40. </view>
  41. <view>
  42. <view class="percentage" v-if="!textInside && !lineData && !noData && !isAnimate"
  43. >{{ percentage }}%
  44. </view>
  45. </view>
  46. </view>
  47. </view>
  48. </template>
  49. <script>
  50. export default {
  51. name: 'AiProgress',
  52. components: {},
  53. props: {
  54. // 进度条的值
  55. percentage: {
  56. type: [Number, String],
  57. required: true,
  58. },
  59. // 是否内联显示数据
  60. textInside: {
  61. type: Boolean,
  62. default: false,
  63. },
  64. // 进度条高度
  65. strokeWidth: {
  66. type: [Number, String],
  67. default: 6,
  68. },
  69. // 默认动画时长
  70. duration: {
  71. type: [Number, String],
  72. default: 2000,
  73. },
  74. // 是否有动画
  75. isAnimate: {
  76. type: Boolean,
  77. default: false,
  78. },
  79. // 背景颜色
  80. bgColor: {
  81. type: String,
  82. default: 'linear-gradient(90deg, var(--ui-BG-Main) 0%, var(--ui-BG-Main-gradient) 100%)',
  83. },
  84. // 是否不显示数据
  85. noData: {
  86. type: Boolean,
  87. default: false,
  88. },
  89. // 是否自定义显示内容
  90. lineData: {
  91. type: Boolean,
  92. default: false,
  93. },
  94. // 自定义底色
  95. inBgColor: {
  96. type: String,
  97. default: '#ebeef5',
  98. },
  99. },
  100. data() {
  101. return {
  102. width: 0,
  103. timer: null,
  104. containerWidth: 0,
  105. contentWidth: 0,
  106. };
  107. },
  108. methods: {
  109. start() {
  110. if (this.isAnimate) {
  111. // #ifdef H5
  112. this.$nextTick(() => {
  113. let progressContainer = this.$refs.progressContainer.$el;
  114. let progressContent = this.$refs.progressContent.$el;
  115. let style = window.getComputedStyle(progressContainer, null);
  116. let width = style.width.replace('px', '') * ((this.percentage * 1) / 100);
  117. progressContent.style.width = width.toFixed(2) + 'px';
  118. progressContent.style.transition = `width ${this.duration / 1000}s ease`;
  119. });
  120. // #endif
  121. const container = uni.createSelectorQuery().in(this).selectAll('#container');
  122. const content = uni.createSelectorQuery().in(this).selectAll('#content');
  123. container.boundingClientRect().exec((res1) => {
  124. this.contentWidth =
  125. res1[0][0].width * 1 * ((this.percentage * 1) / 100).toFixed(2) + 'px';
  126. });
  127. }
  128. },
  129. },
  130. mounted() {
  131. this.$nextTick(() => {
  132. this.start();
  133. });
  134. },
  135. created() {},
  136. filters: {},
  137. computed: {},
  138. watch: {},
  139. directives: {},
  140. };
  141. </script>
  142. <style scoped lang="scss">
  143. .content {
  144. margin-bottom: 10px;
  145. .c-per {
  146. font-size: 26px;
  147. }
  148. }
  149. .progress-container {
  150. width: 100%;
  151. border-radius: 100px;
  152. .progress-content {
  153. border-radius: 100px;
  154. width: 0;
  155. }
  156. .textInside {
  157. color: #fff;
  158. margin-right: 10rpx;
  159. position: relative;
  160. }
  161. }
  162. .text {
  163. margin-left: 10rpx;
  164. font-size: 16rpx;
  165. width: 100rpx;
  166. color: #FFB9B9;
  167. }
  168. .percentage {
  169. margin-left: 6px;
  170. font-size: 12px;
  171. width: 30px;
  172. }
  173. .flex {
  174. display: flex;
  175. }
  176. .a-center {
  177. align-items: center;
  178. }
  179. .j-center {
  180. justify-content: center;
  181. }
  182. .j-between {
  183. justify-content: space-between;
  184. }
  185. .content {
  186. margin-bottom: 10px;
  187. color: #666;
  188. font-size: 32rpx;
  189. }
  190. </style>