204 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Vue
		
	
	
			
		
		
	
	
			204 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Vue
		
	
	
| <template>
 | |
|   <view>
 | |
|     <view class="flex a-center content" v-if="lineData">
 | |
|       <view>
 | |
|         <slot name="content"></slot>
 | |
|       </view>
 | |
|     </view>
 | |
|     <view class="flex a-center" style="padding-right: 10rpx">
 | |
|       <view
 | |
|         class="progress-container"
 | |
|         id="container"
 | |
|         ref="progressContainer"
 | |
|         :style="{ background: inBgColor }"
 | |
|       >
 | |
|         <view
 | |
|           class="progress-content flex j-end"
 | |
|           id="content"
 | |
|           ref="progressContent"
 | |
|           :style="{
 | |
|             height: strokeWidth + 'px',
 | |
|             background: bgColor,
 | |
|             width: contentWidth,
 | |
|             transition: `width ${duration / 1000}s ease`,
 | |
|           }"
 | |
|           v-if="isAnimate"
 | |
|         >
 | |
|           <view class="textInside flex a-center j-center" v-if="textInside && !noData">
 | |
|             <view class="text">{{ percentage }}%</view>
 | |
|           </view>
 | |
|         </view>
 | |
|         <view
 | |
|           v-if="!isAnimate"
 | |
|           class="progress-content flex j-end"
 | |
|           :style="{ width: percentage + '%', height: strokeWidth + 'px', background: bgColor }"
 | |
|         >
 | |
|           <view class="textInside flex a-center j-center" v-if="textInside && !noData">
 | |
|             <view class="text">{{ percentage }}%</view>
 | |
|           </view>
 | |
|         </view>
 | |
|       </view>
 | |
|       <view>
 | |
|         <view class="percentage" v-if="!textInside && !lineData && !noData && !isAnimate"
 | |
|           >{{ percentage }}%
 | |
|         </view>
 | |
|       </view>
 | |
|     </view>
 | |
|   </view>
 | |
| </template>
 | |
| 
 | |
| <script>
 | |
|   export default {
 | |
|     name: 'AiProgress',
 | |
|     components: {},
 | |
|     props: {
 | |
|       // 进度条的值
 | |
|       percentage: {
 | |
|         type: [Number, String],
 | |
|         required: true,
 | |
|       },
 | |
|       // 是否内联显示数据
 | |
|       textInside: {
 | |
|         type: Boolean,
 | |
|         default: false,
 | |
|       },
 | |
|       // 进度条高度
 | |
|       strokeWidth: {
 | |
|         type: [Number, String],
 | |
|         default: 6,
 | |
|       },
 | |
|       // 默认动画时长
 | |
|       duration: {
 | |
|         type: [Number, String],
 | |
|         default: 2000,
 | |
|       },
 | |
|       // 是否有动画
 | |
|       isAnimate: {
 | |
|         type: Boolean,
 | |
|         default: false,
 | |
|       },
 | |
|       // 背景颜色
 | |
|       bgColor: {
 | |
|         type: String,
 | |
|         default: 'linear-gradient(90deg, var(--ui-BG-Main) 0%, var(--ui-BG-Main-gradient) 100%)',
 | |
|       },
 | |
|       // 是否不显示数据
 | |
|       noData: {
 | |
|         type: Boolean,
 | |
|         default: false,
 | |
|       },
 | |
|       // 是否自定义显示内容
 | |
|       lineData: {
 | |
|         type: Boolean,
 | |
|         default: false,
 | |
|       },
 | |
|       // 自定义底色
 | |
|       inBgColor: {
 | |
|         type: String,
 | |
|         default: '#ebeef5',
 | |
|       },
 | |
|     },
 | |
|     data() {
 | |
|       return {
 | |
|         width: 0,
 | |
|         timer: null,
 | |
|         containerWidth: 0,
 | |
|         contentWidth: 0,
 | |
|       };
 | |
|     },
 | |
|     methods: {
 | |
|       start() {
 | |
|         if (this.isAnimate) {
 | |
|           // #ifdef H5
 | |
|           this.$nextTick(() => {
 | |
|             let progressContainer = this.$refs.progressContainer.$el;
 | |
|             let progressContent = this.$refs.progressContent.$el;
 | |
|             let style = window.getComputedStyle(progressContainer, null);
 | |
|             let width = style.width.replace('px', '') * ((this.percentage * 1) / 100);
 | |
|             progressContent.style.width = width.toFixed(2) + 'px';
 | |
|             progressContent.style.transition = `width ${this.duration / 1000}s ease`;
 | |
|           });
 | |
|           // #endif
 | |
|           const container = uni.createSelectorQuery().in(this).selectAll('#container');
 | |
|           const content = uni.createSelectorQuery().in(this).selectAll('#content');
 | |
|           container.boundingClientRect().exec((res1) => {
 | |
|             this.contentWidth =
 | |
|               res1[0][0].width * 1 * ((this.percentage * 1) / 100).toFixed(2) + 'px';
 | |
|           });
 | |
|         }
 | |
|       },
 | |
|     },
 | |
|     mounted() {
 | |
|       this.$nextTick(() => {
 | |
|         this.start();
 | |
|       });
 | |
|     },
 | |
|     created() {},
 | |
|     filters: {},
 | |
|     computed: {},
 | |
|     watch: {},
 | |
|     directives: {},
 | |
|   };
 | |
| </script>
 | |
| 
 | |
| <style scoped lang="scss">
 | |
|   .content {
 | |
|     margin-bottom: 10px;
 | |
| 
 | |
|     .c-per {
 | |
|       font-size: 26px;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   .progress-container {
 | |
|     width: 100%;
 | |
|     border-radius: 100px;
 | |
| 
 | |
|     .progress-content {
 | |
|       border-radius: 100px;
 | |
|       width: 0;
 | |
|     }
 | |
| 
 | |
|     .textInside {
 | |
|       color: #fff;
 | |
|       margin-right: 10rpx;
 | |
|       position: relative;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   .text {
 | |
|     margin-left: 10rpx;
 | |
|     font-size: 16rpx;
 | |
|     width: 100rpx;
 | |
|     color: #FFB9B9;
 | |
|   }
 | |
| 
 | |
|   .percentage {
 | |
|     margin-left: 6px;
 | |
|     font-size: 12px;
 | |
|     width: 30px;
 | |
|   }
 | |
| 
 | |
|   .flex {
 | |
|     display: flex;
 | |
|   }
 | |
| 
 | |
|   .a-center {
 | |
|     align-items: center;
 | |
|   }
 | |
| 
 | |
|   .j-center {
 | |
|     justify-content: center;
 | |
|   }
 | |
| 
 | |
|   .j-between {
 | |
|     justify-content: space-between;
 | |
|   }
 | |
| 
 | |
|   .content {
 | |
|     margin-bottom: 10px;
 | |
|     color: #666;
 | |
|     font-size: 32rpx;
 | |
|   }
 | |
| </style>
 |