1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
| <script setup> import { onMounted, ref, onUpdated } from 'vue'
const props = defineProps({ value: { type: Number, default: 0.3 }, color: { type: String, default: '#46ebb7' // default: '#ffe699' }, width: { type: Number, default: 200 }, height: { type: Number, default: 200 } })
const canvasRef = ref(null)
const draw = () => { const canvas = canvasRef.value const context = canvas.getContext('2d') const x = 0 const y = 0 const lineWidth = 20 const radius = Math.min(canvas.width / 2, canvas.height / 2) - lineWidth / 2 const segmentCount = 12 // 分割线数量 const segmentAngle = (2 * Math.PI) / segmentCount // 每个分割线的角度 const offsetAngle = Math.PI / 7 // 每个圆环偏移较多 const halfWidth = canvas.width / 2 const halfHeight = canvas.height / 2
context.clearRect(0, 0, canvas.width, canvas.height)
// 偏移画布起点到中心 context.translate(halfWidth, halfHeight) context.rotate((-90 * Math.PI) / 180)
// 绘制分割线 for (let i = 0; i < segmentCount; i++) { const angle = i * segmentAngle const angleEnd = angle + offsetAngle
// 绘制底部圆环 context.beginPath() context.arc(x, y, radius, angle, angleEnd) context.lineWidth = lineWidth context.strokeStyle = 'rgba(55,76,121,0.5)' context.stroke()
// 绘制进度圆环 const maxAngle = Math.PI * 2 * props.value if (angle <= maxAngle) { context.beginPath() context.arc(x, y, radius, angle, Math.min(angleEnd, maxAngle)) context.lineWidth = lineWidth context.strokeStyle = props.color context.stroke() } }
// 绘制中间文本 context.rotate((90 * Math.PI) / 180) context.font = 'bold 32px serif' context.textAlign = 'center' context.textBaseline = 'middle' context.fillStyle = props.color context.fillText('92%', 0, 0) }
onMounted(() => { draw() })
onUpdated(() => { draw() }) </script>
<template> <div class="circle-process-container"> <canvas :width="width" :height="height" ref="canvasRef"></canvas> <div class="bottom-bg"></div> </div> </template>
<style> .circle-process-container { display: inline-block; } .bottom-bg { height: 200px; background: url('./bottom-bg.png'); background-size: cover; background-position: center; background-repeat: no-repeat; height: 48px; } canvas { border: solid 4px v-bind(color); border-radius: 50%; padding: 8px; box-shadow: v-bind(color) 0px 0px 26px; width: v-bind(width); height: v-bind(height); margin: 0 auto; display: block; } </style>
|