重構-線性進度條
阿新 • • 發佈:2020-12-09
動畫: 傳遞顏色陣列後,顏色過渡 寬度改變有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%);
}