React 通过svg实现进度环组件

效果图,如下图所示进度分别为25%,50%,75%, 100%渲染图形

         

 

css代码

.CircelProcess{
    position: relative;
    width: 100%;
    height: 100%;
}
.CircelProcess *{
    box-sizing: border-box;
}

.CircelProcess svg{
    transform: rotate(-90deg);
}

.ProcessCircle{
    transition: stroke-dashoffset 500ms cubic-bezier(0.99, 0.01, 0.62, 0.94);
}

js代码

import React from 'react'
import PropTypes from 'prop-types'
import './style.css'

class CircelProcess extends React.Component {
    static propTypes = {
        ratio: PropTypes.number,
        strokeColor: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
        percent: PropTypes.number.isRequired
    }
    static defaultProps = {
        strokeColor: '#F9C97B',
        ratio: 0.1
    }
    constructor(props) {
        super(props)
        let {ratio} = props
        let  r = 50 /(1 + ratio)
        let circumference = Math.PI * 2 * r
        this.state = {
            strokeDashoffset: circumference
        }
    }
    componentWillUnmount() {
        this.mounted = false
    }
    componentDidMount() {
        this.mounted = true
        let { percent, ratio } = this.props
        let  r = 50 /(1 + ratio)
        let circumference = Math.PI * 2 * r
        let strokeDashoffset = circumference - circumference * percent / 100.0
        setTimeout(() => {
            if (this.mounted) {
                this.setState({
                    strokeDashoffset
                })
            }
        }, 300)
    }
    render() {
        let { ratio} = this.props
        let { strokeDashoffset } = this.state
        let  r = 50 /(1 + ratio)
        let strokeDasharray = Math.PI * 2 * r
        let strokeWidth = r * ratio
        return (
            <div className='CircelProcess'>
                <svg width='100%' height='100%'
                    viewBox='0 0 100 100'>
                    <circle
                        className='BackgroundCircle'
                        cx={50}
                        cy={50}
                        r={r}
                        strokeWidth={strokeWidth}
                        stroke='#D3D3D3'
                        strokeOpacity={0.2}
                        fill='none' />
                    <circle
                        className='ProcessCircle'
                        cx={50}
                        cy={50}
                        r={r}
                        strokeWidth={strokeWidth}
                        stroke='url(#strokecolor)'
                        // strokeLinejoin='round'
                        strokeLinecap='round'
                        strokeDasharray={strokeDasharray}
                        strokeDashoffset={strokeDashoffset}
                        fill='none' />
                    <defs>
                        <linearGradient id='strokecolor' x1="0%" y1="0%" x2="100%" y2="0%">
                            <stop offset="0%" stopColor={'#00B3BC'} />
                            <stop offset="100%" stopColor={'#89D87A'} />
                        </linearGradient>
                    </defs>
                </svg>
            </div>
        )
    }
}

export default CircelProcess

实现思路:

1. 外层div作为组件容器,class设置宽、高为100%以自适应组件外层容器宽高,实现根据外容器宽、高变化自动变化;

<div className='CircelProcess'></div>

2.svg 通过两个circle实现进度环,一个circle作为背景,另外一个绘制进度条;

 <svg width='100%' height='100%' viewBox='0 0 100 100'></svg>

定义viewBox指定画布大小,方便后续计算,width='100', height='100%',自动填充占满父容器,以宽高较小者作为圆环的外直径;

3. svg中定义底1个circle 作为进度环背景,cx、cy 设置为50,代表circle圆心在画布中点,直径 r = 50 /(1 + ratio), ratio为圆环stroke宽度和圆直径大小比例,作为组件属性由使用组件方传递,上边完整代码中默认值为0.1 ,从圆心到圆外侧边长度为circle直径 + 绘制宽度,所以 r = 50 /(1 + ratio),所以圆环环形宽度为  strokeWidth = r * ratio, stroke属性设置背景色,strokeOpacity设置 stroke 边透明度, fill='none'表明绘制的圆形不需要填充内容;

<circle
	className='BackgroundCircle'
	cx={50}
	cy={50}
	r={r}
	strokeWidth={strokeWidth}
	stroke='#D3D3D3'
	strokeOpacity={0.2}
	fill='none' />

4. 绘制进度条:定义第2个circle 用来绘制进度。

圆心,直径、绘制宽度同第1个圆环,绘制颜色(stroke)引用 defs中定义的线性渐变元素实现绘制颜色渐变;

strokeDasharray定义绘制线段的虚线段数组,长度为圆的直径,strokeDashoffset设置绘制线段偏移量,通过修改其值来绘制进度条。strokeDashoffset初始值为圆周长,线段偏移长度和园周长大小一致,所以一开始圆环线段偏移之后显示为虚线部分,所以环2在默认情况下通过设置偏移长度在界面上是看不到的,然后通过percent来计算strokeDashoffset值,再修改其值,本例实现是为了进度条动态展示,设置在300ms之后修改strokeDashoffset值。

<circle
	className='ProcessCircle'
	cx={50}
	cy={50}
	r={r}
	strokeWidth={strokeWidth}
	stroke='url(#strokecolor)'
	// strokeLinejoin='round'
	strokeLinecap='round'
	strokeDasharray={strokeDasharray}
	strokeDashoffset={strokeDashoffset}
	fill='none' />
<defs>
	<linearGradient id='strokecolor' x1="0%" y1="0%" x2="100%" y2="0%">
		<stop offset="0%" stopColor={'#00B3BC'} />
		<stop offset="100%" stopColor={'#89D87A'} />
	</linearGradient>
</defs>

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值