ProgressRing.vue 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. <template>
  2. <svg :width="size" :height="size" :viewBox="`0 0 ${size} ${size}`">
  3. <!-- 背景圆环 -->
  4. <circle
  5. :cx="center"
  6. :cy="center"
  7. :r="radius"
  8. fill="none"
  9. :stroke="backgroundColor"
  10. :stroke-width="strokeWidth"
  11. :stroke-linecap="softCorner ? 'round' : 'butt'"
  12. />
  13. <!-- 进度圆环 -->
  14. <circle
  15. :cx="center"
  16. :cy="center"
  17. :r="radius"
  18. fill="none"
  19. :stroke="progressColor"
  20. :stroke-width="strokeWidth"
  21. :stroke-dasharray="`${circumference * progress} ${circumference}`"
  22. :transform="`rotate(-90 ${center} ${center})`"
  23. :stroke-linecap="softCorner ? 'round' : 'butt'"
  24. />
  25. </svg>
  26. </template>
  27. <script lang="ts" setup>
  28. import { computed } from 'vue'
  29. interface Props {
  30. // 进度值 (0-1)
  31. progress?: number
  32. // 圆环大小
  33. size?: number
  34. // 背景圆环颜色
  35. backgroundColor?: string
  36. // 进度圆环颜色
  37. progressColor?: string
  38. // 圆环粗细
  39. strokeWidth?: number
  40. // 是否为软角
  41. softCorner?: boolean
  42. }
  43. const props = withDefaults(defineProps<Props>(), {
  44. progress: 0,
  45. size: 96,
  46. backgroundColor: 'rgba(239, 239, 239, 1)',
  47. progressColor: 'rgba(0, 188, 113, 1)',
  48. strokeWidth: 10,
  49. softCorner: false
  50. })
  51. // 计算中心点
  52. const center = computed(() => props.size / 2)
  53. // 计算半径 (减去strokeWidth的一半,确保圆环完全显示)
  54. const radius = computed(() => (props.size - props.strokeWidth) / 2)
  55. // 计算圆周长
  56. const circumference = computed(() => 2 * Math.PI * radius.value)
  57. </script>
  58. <style scoped>
  59. svg {
  60. vertical-align: middle;
  61. }
  62. </style>