React 实现圆环进度条

780 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第15天,点击查看活动详情

概述

之前用 Vue3 + TypeScript 实现了进度条功能,今天我们用 React 来实现下这个功能,感受下它们的不同之处。

这是 React 版的完成效果

iShot_2022-06-16_22.51.42.gif

项目初始化

首先我们来初始化一个 React 项目

pnpm create vite reactjs-circleprogress -- --template react

cd 进入根目录,执行命令 pnpm install 安装依赖包, 依赖包安装完成后,我们可以先启动项目,看看项目是否运行正常,输入命令 pnpm run dev

  vite v2.9.9 dev server running at:

  > Local: http://localhost:3000/
  > Network: use `--host` to expose

  ready in 468ms.

可以看到在终端中输出了如上内容,在浏览器地址输入上述地址,可以看到初次运行的页面,说明项目启动正常

圆环进度条

删除多余的代码和文件,我们在 src 下新建如下文件

  • src/components/progress.jsx
  • src/components/progress.css

progress.jsx 是我们的进度条组件, progress.css文件则是进度条组件的样式文件

实现圆环进度条功能,我们首先需要一个 svg 文件

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 96 96" style="width: 96px; height: 96px;"><circle r="40" cx="48" cy="48" fill="none" stroke-miterlimit="20" stroke-width="10" style="stroke-dasharray: 275, 279.602;stroke:#eee;"></circle><circle r="40" cx="48" cy="48" fill="none" stroke-miterlimit="20" stroke-width="10" style="stroke-dasharray: 251, 279.602;stroke:#fdd835;"></circle></svg>

截屏2022-06-16 下午9.25.11.png

在 React 中 使用 svg, 我们需要安装一个相关的插件 react-svg ,在终端中执行如下命令

pnpm install react-svg -D

progress.jsx 进度条组件中,我们引入这个插件和 svg 文件,代码如下

import { ReactSVG } from "react-svg";
import circle from "./circle.svg"
import './progress.css'

function CircleProgress () {
    return (
        <div className="progress" >
            <ReactSVG className='svg-wapper' src={circle} />
        </div >
    )
}
export default CircleProgress

将这个在 App.jsx 中引入,在浏览器中就可以看到 svg 文件已经展示出来了

import { useState } from 'react'
import CircleProgress from "./components/progress"
import './App.css'

function App() {
  return (
    <div className="App">
        <CircleProgress progress={progress} color={'#fdd835'}  />
    </div>
  )
}

export default App

同时,我们需要调整下svg 的样式,在 progress.css 样式文件中添加如下内容

.progress {
    display: inline-block;
    position: relative;
    height: 100px;
    text-align: center;
}
.mask {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}
.svg-wapper{
    width: 100px;
    height: 100px;
    transition: all .3s linear;
}

考虑到进度值,颜色等属性是由组件外部传递进来配置的,我们在进度条组件内部接收下他们的值,添加如下代码,这里我们分别给了进度值和颜色一个默认值

const { progress=20, color="#fdd835" } = props
let progressValue = (progress / 100) * 250

进度值,颜色属性传递进来后,我们需要把属性绑定到 svg 上,实现进度值的动态变化,代码如下

return (
    <div className="progress" >
        <ReactSVG className='svg-wapper' style={{ strokeDasharray: `${progressValue}, 279.602`, stroke: color }}
                beforeInjection={(svg) => {
                    svg.children[1].style=`strokeDasharray: ${progressValue}, 279.602, stroke: ${color}`
                }} src={circle} />
        <div className="mask">{progress}%</div>
    </div >
)

在显示了进度条颜色变化的同时,我们还在圆环中心添加动态变化的进度值,

接着我们 App.jsx 中, 添加一个动态变化的进度值,并将值传递进去,最终我们的 React 版 圆环进度条功能就此实现了

import { useState } from 'react'
import CircleProgress from "./components/progress"
import './App.css'

function App() {
 const [progress, setProgress] = useState(50)

 setInterval(() => {
   setProgress(() => Math.floor(Math.random()*100+1))
}, 1500);

 return (
   <div className="App">
       <CircleProgress progress={progress} color={'#fdd835'}  />
   </div>
 )
}
export default App