Canvas实现进度圈

import React, { useEffect } from 'react'

import './index.less'

const ProgressCircleDemo: any = (props: any) => {
    const { clientWidth = 1 } = document.querySelector('html') || {}
    console.log('=====', clientWidth)
    const calcCssFn = (num: any) => {
        return (clientWidth * num) / 750
    }
    const {
        children,
        percent,
        clockwise,
        trackColor = '#ffe7d8',
        fillStartColor = '#ff873d',
        size = 120,
        lineNum = 10,
        keys = 0,
    } = props || {}
    const width = calcCssFn(size) / 2
    const height = width
    const lineWidth = calcCssFn(lineNum)
    const radius = width - lineWidth / 1.5
    const progress = percent
    useEffect(() => {
        setTimeout(() => {
            const canvas: any = document.querySelector('#myCanvas' + keys)
            if (canvas) {
                const ctx = canvas.getContext('2d')
                const size = Math.min(canvas.width, canvas.height)
                // 解决 canvas 绘制毛边问题
                const sizePX = `${size}px`
                canvas.style.width = sizePX
                canvas.style.height = sizePX
                canvas.height = size * window.devicePixelRatio
                canvas.width = size * window.devicePixelRatio
                ctx.scale(window.devicePixelRatio, window.devicePixelRatio)

                ctx.beginPath()
                // arc(定义一个中心点,半径,起始角度,结束角度,和绘图方向:顺时针或逆时针)
                ctx.arc(width, height, radius, 0, Math.PI * 2)
                ctx.lineWidth = lineWidth
                ctx.lineCap = 'round'
                ctx.strokeStyle = trackColor

                ctx.stroke()
                ctx.closePath()
                // 绘制进度条数据为0不渲染
                if (progress) {
                    const startAngle = 0 || (3 / 2) * Math.PI
                    const percentage = progress
                    const diffAngle = (percentage / 100) * Math.PI * 2
                    ctx.beginPath()
                    ctx.arc(
                        width,
                        height,
                        radius,
                        startAngle,
                        diffAngle + startAngle,
                        clockwise < 0 ? true : false
                    )

                    ctx.strokeStyle = fillStartColor
                    ctx.stroke()
                    ctx.closePath()
                }

                // ctx.beginPath()
                // ctx.fillStyle = '#000'
                // ctx.textAlign = 'center'
                // ctx.font = '16px serif'
                // ctx.fillText(percentage + '%', width + 2, height + 5)
            }
        }, 100)
    })
    return (
        <div className="div-wrap">
            <canvas
                id={'myCanvas' + keys}
                width={width * 2}
                height={width * 2}
            ></canvas>
            <div className="progress-content">{children}</div>
        </div>
    )
}
export default ProgressCircleDemo

.div-wrap {
    display: flex;
    justify-content: center;
    align-items: center;
    position: relative;
    .progress-content {
        position: absolute;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
    }
}

<DemoCircle
    percent={25}
    keys={'onlyKey'}
    clockwise={clockwise'? 1 : -1}
>
    25%                     
</DemoCircle>
进度圈.png
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容