index.taro.vue 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. <template>
  2. <div class="nut-progress">
  3. <div
  4. class="nut-progress-outer"
  5. ref="progressOuter"
  6. :class="[
  7. showText && !textInside ? 'nut-progress-outer-part' : '',
  8. size ? 'nut-progress-' + size : ''
  9. ]"
  10. :style="{ height: height }"
  11. >
  12. <div
  13. :class="['nut-progress-inner', status == 'active' ? 'nut-active' : '']"
  14. :style="bgStyle"
  15. >
  16. <div
  17. class="nut-progress-text nut-progress-insidetext"
  18. :style="{ lineHeight: height, left: left }"
  19. v-if="showText && textInside"
  20. >
  21. <span :style="textStyle">{{ percentage }}%</span>
  22. </div>
  23. </div>
  24. </div>
  25. <div
  26. class="nut-progress-text"
  27. :style="{ lineHeight: height }"
  28. v-if="showText && !textInside"
  29. >
  30. <template v-if="status == 'text' || status == 'active'">
  31. <span :style="textStyle">{{ percentage }}%</span>
  32. </template>
  33. <template v-else-if="status == 'icon'">
  34. <nut-icon size="16px" :name="iconName" :color="iconColor"></nut-icon>
  35. </template>
  36. </div>
  37. </div>
  38. </template>
  39. <script lang="ts">
  40. import {
  41. computed,
  42. onMounted,
  43. provide,
  44. reactive,
  45. nextTick,
  46. ref,
  47. getCurrentInstance,
  48. watch
  49. } from 'vue';
  50. import { createComponent } from '../../utils/create';
  51. import Taro, { eventCenter } from '@tarojs/taro';
  52. const { create } = createComponent('progress');
  53. export default create({
  54. props: {
  55. percentage: {
  56. type: [Number, String],
  57. default: 0,
  58. required: true
  59. },
  60. size: {
  61. type: String,
  62. default: 'base'
  63. },
  64. status: {
  65. type: String,
  66. default: 'text'
  67. },
  68. strokeWidth: {
  69. type: [Number, String],
  70. default: ''
  71. },
  72. textInside: {
  73. type: Boolean,
  74. default: false
  75. },
  76. showText: {
  77. type: Boolean,
  78. default: true
  79. },
  80. strokeColor: {
  81. type: String,
  82. default: ''
  83. },
  84. textColor: {
  85. tyep: String,
  86. default: ''
  87. },
  88. iconName: {
  89. type: String,
  90. default: 'checked'
  91. },
  92. iconColor: {
  93. type: String,
  94. default: '#439422'
  95. }
  96. },
  97. setup(props, { emit }) {
  98. const height = ref(props.strokeWidth + 'px');
  99. const progressOuter = ref<any>();
  100. const left = ref();
  101. const bgStyle = computed(() => {
  102. return {
  103. width: props.percentage + '%',
  104. background: props.strokeColor || ''
  105. };
  106. });
  107. const textStyle = computed(() => {
  108. return {
  109. color: props.textColor || ''
  110. };
  111. });
  112. const slideLeft = async (values: String | Number) => {
  113. if (Taro.getEnv() === 'WEB') {
  114. setTimeout(() => {
  115. left.value =
  116. progressOuter.value.offsetWidth * Number(values) * 0.01 - 4 + 'px';
  117. }, 200);
  118. } else {
  119. setTimeout(() => {
  120. const query = Taro.createSelectorQuery() as any;
  121. query
  122. .select('.nut-progress-outer')
  123. .boundingClientRect((rec: any) => {
  124. left.value = rec.width * Number(values) * 0.01 - 4 + 'px';
  125. })
  126. .exec();
  127. }, 200);
  128. }
  129. };
  130. watch(
  131. () => props.percentage,
  132. (values) => {
  133. slideLeft(values);
  134. },
  135. { immediate: true }
  136. );
  137. onMounted(() => {});
  138. return {
  139. height,
  140. bgStyle,
  141. textStyle,
  142. progressOuter,
  143. left
  144. };
  145. }
  146. });
  147. </script>
  148. <style lang="scss">
  149. @import 'index.scss';
  150. </style>