progress.vue 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. <template>
  2. <view class="wrapper">
  3. <view class="progress_box" :style="{margin: '0 auto',width:progress_width+'rpx',height:progress_height+'rpx'}">
  4. <view class="bg" :style="{width:progress_width+'rpx',height:progress_height+'rpx'}"></view>
  5. <canvas class="progress_bg" canvas-id="cpbg" id="cpbg" :style="{width:progress_width+'rpx',height:progress_height+'rpx',left:0}"></canvas>
  6. <canvas class="progress_bar" canvas-id="cpbar" id="cpbar" :style="{width:progress_width+'rpx',height:progress_height+'rpx',left:0}"></canvas>
  7. </view>
  8. </view>
  9. </template>
  10. <script>
  11. /**
  12. * circleProgress 自己写的环形进度条
  13. * @property {String Number} value 圆环进度百分比值,为数值类型,0-100(默认必传).
  14. * @property {String Number} progress_time 圆环进度总时间
  15. * @property {String Number} border_width 圆环边框宽度
  16. * @property {String Number} progress_width 圆环宽度(建议宽高一致)
  17. * @property {String Number} progress_height 圆环高度(建议宽高一致)
  18. * @property {String} bg_color 圆环的背景色
  19. * @property {String} start_color 圆环开始渐变色
  20. * @property {String} bg_color 圆环结束渐变色
  21. */
  22. export default {
  23. props: {
  24. value: {
  25. type: Number,
  26. default: 10,
  27. required: true
  28. },
  29. progress_time: {
  30. type: Number,
  31. default: 1500
  32. },
  33. progress_width: {
  34. type: Number,
  35. default: 670
  36. },
  37. progress_height: {
  38. type: Number,
  39. default: 340
  40. },
  41. border_width: {
  42. type: Number,
  43. default: 10
  44. },
  45. bg_color: {
  46. type: String,
  47. default: 'rgba(255,255,255,0.2)'
  48. },
  49. start_color: {
  50. type: String,
  51. default: '#01D8D0'
  52. },
  53. end_color: {
  54. type: String,
  55. default: '#14E7A0'
  56. },
  57. show: {
  58. type: Boolean,
  59. default: true,
  60. },
  61. },
  62. watch: {
  63. value(val) {
  64. // 监听value进度变化,如果进度大于现有进度,则开始绘制
  65. if (this.value > this.percent) {
  66. this.percent++
  67. this.drawCircle(this.percent)
  68. }
  69. },
  70. },
  71. computed: {
  72. wRpx() {
  73. return this.rpxToPx(this.progress_width)
  74. },
  75. hRpx() {
  76. return this.rpxToPx(this.progress_height)
  77. },
  78. },
  79. data() {
  80. return {
  81. percent: 0, // 保存进度值的变化前后值,用于比较用
  82. }
  83. },
  84. mounted() {
  85. this.drawProgressbg();
  86. this.drawCircle(this.value);
  87. },
  88. beforeDestroy: function () {
  89. // 在组件实例被从页面节点树移除时执行
  90. console.log('visitor detached');
  91. this.clear()
  92. },
  93. methods: {
  94. // rpx转px
  95. rpxToPx(rpx) {
  96. const screenWidth = uni.getSystemInfoSync().windowWidth
  97. return (screenWidth * Number.parseInt(rpx)) / 750
  98. },
  99. // 背景
  100. drawProgressbg: function () {
  101. // 自定义组件实例 this ,表示在这个自定义组件下查找拥有 canvas-id 的 <canvas/>
  102. let ctx = uni.createCanvasContext('cpbg', this);
  103. ctx.setLineWidth(this.border_width);
  104. ctx.setStrokeStyle(this.bg_color);
  105. ctx.setLineCap('round');
  106. ctx.beginPath();
  107. ctx.arc(this.wRpx / 2, this.hRpx - this.border_width, this.wRpx / 2 - this.border_width - 15, 0.99 * Math.PI, 0.01 * Math.PI, false);
  108. ctx.stroke();
  109. ctx.draw();
  110. },
  111. // 画圆(递归调用)
  112. drawCircle: function (step) {
  113. if (step === 0) return;
  114. let time = Math.floor(this.progress_time / 100)
  115. let ctx = uni.createCanvasContext('cpbar', this);
  116. let gradient = ctx.createLinearGradient(28, 55, 192, 55);
  117. gradient.addColorStop('0', this.start_color);
  118. gradient.addColorStop('1.0', this.end_color);
  119. ctx.setLineWidth(this.border_width);
  120. ctx.setStrokeStyle(gradient);
  121. ctx.setLineCap('round');
  122. ctx.beginPath();
  123. step = 0.01 * step + 0.99;
  124. if (step === 1) {
  125. step = 0.99
  126. }
  127. if (step >= 2) {
  128. step = step % 2;
  129. }
  130. if (step === 1.99) {
  131. step = 0.01
  132. }
  133. ctx.arc(this.wRpx / 2, this.hRpx - this.border_width, this.wRpx / 2 - this.border_width - 15, 0.99 * Math.PI, step * Math.PI, false);
  134. ctx.stroke();
  135. ctx.draw();
  136. if (this.value > this.percent) {
  137. this.percent++
  138. setTimeout(() => {
  139. this.drawCircle(this.percent)
  140. }, time)
  141. }
  142. },
  143. clear: function () {
  144. let ctx = uni.createCanvasContext('cpbar', this);
  145. ctx.draw();
  146. let ctxBg = uni.createCanvasContext('cpbg', this);
  147. ctxBg.draw();
  148. }
  149. }
  150. };
  151. </script>
  152. <style>
  153. .wrapper {
  154. width: 100%;
  155. height: 100%;
  156. text-align: center;
  157. }
  158. .progress_box {
  159. position: relative;
  160. /* width: 100%;
  161. height: 100%; */
  162. /* display: flex;
  163. align-items: center;
  164. justify-content: center; */
  165. text-align: center;
  166. }
  167. .progress_bg,
  168. .progress_bar {
  169. position: absolute;
  170. }
  171. .bg {
  172. position: absolute;
  173. background: url("@/static/index/progress-bg.png") center 0 no-repeat;
  174. background-size: contain;
  175. }
  176. .canvasHide {
  177. position: fixed;
  178. left: 100%;
  179. }
  180. </style>