当前位置: 首页 > 工具软件 > react-circle > 使用案例 >

react+canvas绘制圆环

傅浩漫
2023-12-01

首先创建一个.jsx文件
输入rfc,创建组件模板

import React from 'react'

export default function index() {
    return (
        <div>
            
        </div>
    )
}

再把canvas元素引入,顺便把组件模板稍微改下

import React from 'react'

const index = props => {

    return (
        <canvas ></canvas>
    )
}
export default index

接着设置canvas的id,因为这个组件可能重复使用,所以我们要保证每次创建的时候生成不同的id

import React, { useState, useEffect } from 'react'

const index = props => {
    const [ids, setId] = useState()

    useEffect(() => {
        let id = ('_' + Math.random()).replace('.', '_');
        setId(id)
    }, [])

    return (
        <canvas id={ids}></canvas>
    )
}
export default index

再然后是关键的一步,绘制圆环,使用这个函数,具体见canvas api

const drawCircle = (_options) => {
        var options = _options || {}; //获取或定义options对象;

        options.angle = options.angle || [0.3, 0.3, 0.2, 0.2];    //定义默认角度1为360度(角度范围 0-1);
        options.color = options.color || '#111';    //定义默认颜色(包括字体和边框颜色);
        options.lineWidth = options.lineWidth || 10;    //定义默认圆描边的宽度;
        options.num = options.num || 0

        var oBoxOne = document.getElementById(options.id);
        oBoxOne.width = oBoxOne.width  //重置宽刷新canvas
        var sCenter = oBoxOne.width / 2;    //获取canvas元素的中心点;
        var ctx = oBoxOne.getContext('2d');
        var nBegin = Math.PI / 2;    //定义起始角度;
        var nEnd = Math.PI * 2;    //定义结束角度;

        ctx.textAlign = 'center';    //定义字体居中;
        ctx.font = 'normal normal bold 24px Arial';    //定义字体加粗大小字体样式;
        ctx.fillStyle = '#202224';    //判断文字填充样式为颜色,还是渐变色;
        ctx.fillText((options.angle[options.num] * 100).toFixed(1) + '%', sCenter, sCenter);    //设置填充文字;

        ctx.lineCap = options.lineCap;
        ctx.lineWidth = options.lineWidth;
        ctx.beginPath();    //设置起始路径,这段绘制360度背景;
        ctx.strokeStyle = '#D8D8D8';
        ctx.arc(sCenter, sCenter, (sCenter - options.lineWidth), -nBegin, nEnd, false);
        ctx.stroke();

        var nBegins = []
        var nEnds = []
        let sum = 0
        options.angle.forEach(item => {
            nBegins.push(sum * nEnd)
            sum += item
            nEnds.push(sum * nEnd)
        })

        const draw = (nBegin, nEnd, color) => {    //该函数实现角度绘制;
            var imd = ctx.getImageData(0, 0, 240, 240);
            ctx.putImageData(imd, 0, 0);
            ctx.beginPath();
            ctx.strokeStyle = color ? color : '#6699FF';
            ctx.arc(sCenter, sCenter, (sCenter - options.lineWidth), nBegin, nEnd, false);
            ctx.stroke();
        }

	  for (var i = 0; i < nBegins.length; i++) {
            draw(nBegins[i], nEnds[i], colors[i])
        }

    }

接着把这个函数在组件中使用,angle的数组表示把圆环分成4段,num表示环中间显示数字是数组的第一位,显示的样式是百分百。

import React, { useState, useEffect } from 'react'

const index = props => {
    const [ids, setId] = useState()

    useEffect(() => {
        let id = ('_' + Math.random()).replace('.', '_');
        setId(id)
    }, [])

    useEffect(() => {
        if (ids) {
            drawCircle({ id: ids, angle: [0.2,0.3,0.4,0.1] ,num={1})
        }
    }, [ids])

    const drawCircle = (_options) => { 
        ...
    }

    return (
        <canvas id={ids}></canvas>
    )
}
export default index

这个angle和num可以改成外部传入,外部还需要传入高度和宽度。

import React, { useState, useEffect } from 'react'

const index = props => {
    const { width, height, angle, num } = props
    const [ids, setId] = useState()

    useEffect(() => {
        let id = ('_' + Math.random()).replace('.', '_');
        setId(id)
    }, [])

    useEffect(() => {
        if (ids) {
            drawCircle({ id: ids, angle: angle, num: num })
        }
    }, [ids])

    const drawCircle = (_options) => { 
        ...
    }

return (
        <canvas id={ids} width={width ? width : 150} height={height ? height : 150}></canvas>
    )   
}
export default index

这样一个圆环就完成了

 类似资料: