动画:
传递颜色数组后,颜色过渡
宽度改变有0.6s过渡
参数:
percentage: PropTypes.number, 进度数值,0-100
onSuccess: PropTypes.func, 当加载到100%时,触发回调,第一个参数是状态
colors: PropTypes.array, 颜色数组,会根据传递的颜色,在不同进度现实不同颜色,默认为蓝色
suffix: PropTypes.bool, 后置图标,在整个轨道后出现,未实现逻辑,仅是展现,需自定义设置
show: PropTypes.bool, 是否在进度条尾部现实数字
width: PropTypes.string, 进度条长度
height: PropTypes.string, 进度条高度
borderRadius: PropTypes.string, 进度条圆角
fontSize: PropTypes.string, 数字和图标字体大小
outerColor: PropTypes.string, 轨道颜色
innerColor: PropTypes.string, 进度颜色
percentColor: PropTypes.string, 数字颜色
效果图:
代码示例:
使用:
import React,{useState,useRef,useEffect,useCallback} from 'react'
import Progress from './progress/progress'
function App(){
let [value,setValue] =useState(0);
const valf = useRef(null);
valf.current = value;
const _onClick = function ()
{
setInterval(() => {
setValue(v=>v+1);
},1000)
}
const _onSuccess = function (state)
{
console.log(state);
}
return(
<div>
<Progress colors={['#aaa', 'brown', 'blue', 'green']} percentage={value} onSuccess={_onSuccess} show ></Progress>
<br />
<br/>
<button onClick={_onClick}>开始</button>
</div>
)
}
export default App
progress.jsx:
import React,{useState,useEffect,useCallback,useRef,useMemo} from 'react'
import PropTypes from 'prop-types'
import './progress.css'
function App(props){
const progressf = useRef(null);
const innerf = useRef(null);
// 初始样式设置
useEffect(() => {
_styleHandler('width', props.width);
_styleHandler('height', props.height);
_styleHandler('borderRadius', props.borderRadius);
_styleHandler('fontSize', props.fontSize);
_styleHandler('outerColor', props.outerColor);
_styleHandler('innerColor', props.innerColor);
_styleHandler('percentColor', props.percentColor);
},[])
// 进度改变过程设置
useEffect(() => {
innerf.current.style.width = _percentHandler + '%';
props.percentage === 100 && props.onSuccess(true);
props.suffix && _situationHandler();
if(props.colors.length)
{
let index = Math.floor(100 / props.colors.length);
_percentColorHandler(_percentHandler, index);
}
},[props.percentage])
//统一处理初始化样式
const _styleHandler = useCallback((key, value) => {
props[key] && progressf.current.style.setProperty('--' + key, value)
},[])
//计算属性返回当前数值
const _percentHandler =useMemo(function ()
{
return Math.floor(Math.max(0,Math.min(100,props.percentage)))
},[props.percentage])
//如果传入数组的颜色变化
const _percentColorHandler =useCallback(function(num,index)
{
let _index = Math.floor(num / index);
(_index == props.colors.length) &&( _index = props.colors.length - 1);
innerf.current.style.backgroundColor=props.colors[_index]
},[])
//当有后置图标时,根据进度清空,对图标的处理函数
const _situationHandler = useCallback(() => {
// console.log(_percentHandler);
},[_percentHandler])
return(
<div className='jf-progress-container' ref={progressf}>
<div className='jf-progress-outer'>
<div className='jf-progress-inner' ref={innerf}>{props.show && <div className='jf-progress-num'>{_percentHandler}%</div>}</div>
</div>
{props.suffix && <span className='jf-progress-suffix'>√</span>}
</div>
)
}
App.propTypes = {
percentage: PropTypes.number,
onSuccess: PropTypes.func,
colors: PropTypes.array,
suffix: PropTypes.bool,
show: PropTypes.bool,
width: PropTypes.string,
height: PropTypes.string,
borderRadius: PropTypes.string,
fontSize: PropTypes.string,
outerColor: PropTypes.string,
innerColor: PropTypes.string,
percentColor: PropTypes.string,
}
App.defaultProps = {
percentage: 0,
onSuccess: () => { },
colors:[]
}
export default React.memo(App);
progress.css:
.jf-progress-container {
display: inline-block;
box-sizing: border-box;
width: var(--width);
height: var(--height);
position: relative;
vertical-align: middle;
--width: 400px;
--height: 20px;
--borderRadius: 20px;
--outerColor: #ebeef5;
--innerColor: #409eff;
--innerWidth: px;
--percentColor: white;
--fontSize: 12px;
}
.jf-progress-outer {
width: 100%;
height: 100%;
position: relative;
background-color: var(--outerColor);
border-radius: var(--borderRadius);
overflow: hidden;
vertical-align: middle;
/* display: flex; */
}
.jf-progress-inner {
position: absolute;
left: 0;
top: 0;
height: 100%;
background-color: var(--innerColor);
border-radius: var(--borderRadius);
text-align: right;
line-height: var(--height);
font-size: 0;
transition: width 0.6s ease, background-color 1s;
}
.jf-progress-num {
display: inline-block;
vertical-align: middle;
font-size: var(--fontSize);
color: var(--percentColor);
}
.jf-progress-suffix {
position: absolute;
top: 0;
right: 0;
font-size: var(--fontSize);
line-height: var(--height);
transform: translateX(120%);
}