import React, { useEffect, useRef } from 'react'
interface ProgressRingProps {
progress?: number
radius?: number
lineWidth?: number
bgColor?: string
progressColor?: string
}
const ProgressRing: React.FC<ProgressRingProps> = ({
progress = 0.8,
radius = 25,
lineWidth = 6,
bgColor = 'rgba(255, 255, 255, 0.3)',
progressColor = 'rgba(255, 255, 255, 0.4)',
}) => {
const canvasRef = useRef<HTMLCanvasElement>(null)
const size = 66
useEffect(() => {
const canvas = canvasRef.current
if (!canvas) return
const ctx = canvas.getContext('2d')
if (!ctx) return
// 获取设备像素比
const dpr = window.devicePixelRatio || 1
// 设置canvas实际绘制尺寸(乘以像素比)
canvas.width = size * dpr
canvas.height = size * dpr
// 缩放画布上下文
ctx.scale(dpr, dpr)
// 设置canvas的CSS尺寸保持原显示大小
canvas.style.width = `${size}px`
canvas.style.height = `${size}px`
// 清除画布
ctx.clearRect(0, 0, size, size)
const centerX = size / 2
const centerY = size / 2
// 绘制背景圆环(270度,开口90度)
ctx.beginPath()
// 从-45度开始到225度结束(总共270度)
ctx.arc(centerX, centerY, radius, -Math.PI / 4, (5 * Math.PI) / 4, false)
ctx.lineWidth = lineWidth
ctx.strokeStyle = bgColor
ctx.lineCap = 'round'
ctx.stroke()
if (progress > 0) {
// 绘制进度圆环
const startAngle = -Math.PI / 4
const endAngle = startAngle + ((3 * Math.PI) / 2 * Math.min(progress, 1))
ctx.beginPath()
ctx.arc(centerX, centerY, radius, startAngle, endAngle, false)
ctx.lineWidth = lineWidth
ctx.strokeStyle = progressColor
ctx.lineCap = 'round'
ctx.stroke()
}
}, [progress, radius, lineWidth, bgColor, progressColor, size])
return (
<canvas
ref={canvasRef}
style={{ display: 'block' }}
/>
)
}
export default ProgressRing
`