half-ring-progress.vue 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. <template>
  2. <view class="progress-container">
  3. <!-- 半环进度容器 -->
  4. <view class="ring-wrapper">
  5. <!-- 背景环(半环底色) -->
  6. <view class="ring-bg"></view>
  7. <!-- 进度环(渐变+动态进度) -->
  8. <view class="ring-progress" :style="{ transform: `rotate(${progressDeg}deg)` }">
  9. <!-- 左侧环(青色渐变) -->
  10. </view>
  11. <!-- 进度原点(圆点) -->
  12. <view class="progress-dot" :style="{ transform: `rotate(${progressDeg}deg)` }"></view>
  13. <!-- 中间文字(百分比+提示) -->
  14. <view class="progress-text">
  15. <text class="percent">{{ progress }}%</text>
  16. <text class="tips">{{ tipText }}</text>
  17. </view>
  18. </view>
  19. </view>
  20. </template>
  21. <script>
  22. export default {
  23. name: "half-ring-progress",
  24. props: {
  25. // 进度值(0-100)
  26. progress: {
  27. type: Number,
  28. default: 30,
  29. validator: val => val >= 0 && val <= 100
  30. },
  31. // 底部提示文字
  32. tipText: {
  33. type: String,
  34. default: "充电枪正在充电中"
  35. },
  36. // 是否启用动画
  37. animated: {
  38. type: Boolean,
  39. default: true
  40. },
  41. // 主题颜色(用于渐变)
  42. themeColor: {
  43. type: String,
  44. default: '#49a6f4'
  45. }
  46. },
  47. computed: {
  48. // 计算进度对应的旋转角度(从左侧-90°开始,顺时针旋转)
  49. progressDeg() {
  50. return -90 + (this.progress * 1.8);
  51. },
  52. // 渐变颜色(从青色到蓝色)
  53. gradientColor() {
  54. return 'linear-gradient(99deg, #8FF8FB 0%, #47AEFF 100%)';
  55. }
  56. }
  57. };
  58. </script>
  59. <style scoped>
  60. .progress-container {
  61. display: flex;
  62. justify-content: center;
  63. align-items: center;
  64. padding: 20rpx;
  65. }
  66. .ring-wrapper {
  67. position: relative;
  68. width: 400rpx;
  69. height: 200rpx;
  70. overflow: hidden;
  71. }
  72. /* 背景半环样式 */
  73. .ring-bg {
  74. position: absolute;
  75. top: 0;
  76. left: 0;
  77. width: 400rpx;
  78. height: 400rpx;
  79. border-radius: 50%;
  80. border: 16rpx solid #97DAFF;
  81. box-sizing: border-box;
  82. clip: rect(0rpx, 400rpx, 200rpx, 0rpx);
  83. }
  84. /* 进度半环容器(控制旋转) */
  85. .ring-progress {
  86. position: absolute;
  87. top: 0;
  88. left: 0;
  89. width: 400rpx;
  90. height: 200rpx;
  91. overflow: hidden;
  92. transition: transform 0.6s ease-in-out;
  93. }
  94. /* 左侧半环(青色) */
  95. .ring-left {
  96. position: absolute;
  97. top: 0;
  98. left: 0;
  99. width: 400rpx;
  100. height: 400rpx;
  101. border-radius: 50%;
  102. border: 16rpx solid #8FF8FB;
  103. box-sizing: border-box;
  104. clip: rect(0rpx, 200rpx, 400rpx, 0rpx);
  105. }
  106. /* 中间过渡区 */
  107. .ring-middle {
  108. position: absolute;
  109. top: 0;
  110. left: 150rpx;
  111. width: 100rpx;
  112. height: 400rpx;
  113. background: linear-gradient(to right, #8FF8FB, #5EC8FE);
  114. clip: rect(0rpx, 100rpx, 200rpx, 0rpx);
  115. }
  116. /* 右侧半环(蓝色) */
  117. .ring-right {
  118. position: absolute;
  119. top: 0;
  120. left: 0;
  121. width: 400rpx;
  122. height: 400rpx;
  123. border-radius: 50%;
  124. border: 16rpx solid #47AEFF;
  125. box-sizing: border-box;
  126. clip: rect(0rpx, 400rpx, 400rpx, 200rpx);
  127. }
  128. /* 进度原点(末端圆点) */
  129. .progress-dot {
  130. position: absolute;
  131. top: 0;
  132. left: 50%;
  133. width: 28rpx;
  134. height: 28rpx;
  135. background: #FFFFFF;
  136. border: 5rpx solid #47AEFF;
  137. border-radius: 50%;
  138. transform-origin: center 200rpx;
  139. margin-left: -14rpx;
  140. margin-top: -14rpx;
  141. box-shadow: 0 0 16rpx rgba(71, 174, 255, 0.8);
  142. transition: transform 0.6s ease-in-out;
  143. z-index: 10;
  144. }
  145. /* 中间文字样式 */
  146. .progress-text {
  147. position: absolute;
  148. top: 65%;
  149. left: 50%;
  150. transform: translate(-50%, -50%);
  151. text-align: center;
  152. }
  153. .percent {
  154. display: block;
  155. font-size: 60rpx;
  156. font-weight: bold;
  157. color: #333;
  158. margin-bottom: 10rpx;
  159. }
  160. .tips {
  161. display: block;
  162. font-size: 24rpx;
  163. color: #666;
  164. }
  165. /* 高亮文字(如“充电中”) */
  166. .tips text {
  167. color: v-bind(themeColor);
  168. }
  169. </style>