UNPKG

zent

Version:

一套前端设计语言和基于React的实现

198 lines (187 loc) 5.29 kB
import React, { Component, PureComponent } from 'react'; import Icon from 'icon'; import cx from 'classnames'; import PropTypes from 'prop-types'; export default class Progress extends (PureComponent || Component) { static propTypes = { className: PropTypes.string, prefix: PropTypes.string, type: PropTypes.string, percent: PropTypes.number, showInfo: PropTypes.bool, status: PropTypes.string, format: PropTypes.func, strokeWidth: PropTypes.number, width: PropTypes.number, style: PropTypes.object, normalColor: PropTypes.string, exceptionColor: PropTypes.string, successColor: PropTypes.string, bgColor: PropTypes.string }; static defaultProps = { type: 'line', percent: 0, showInfo: true, className: '', prefix: 'zent', strokeWidth: 10 }; render() { const { type, percent, showInfo, status, className, prefix, format, strokeWidth, width, style, normalColor, exceptionColor, successColor, bgColor } = this.props; const progressWidth = width || (type === 'circle' ? 132 : 580); const containerCls = cx( `${prefix}-progress`, `${prefix}-progress-${type}`, { [className]: !!className } ); const statusCls = cx({ [`${prefix}-progress-inprogress`]: percent < 100 && status !== 'exception', [`${prefix}-progress-exception`]: percent < 100 && status === 'exception', [`${prefix}-progress-success`]: percent >= 100 }); const getCurrentColor = () => { if (percent < 100 && status === 'exception') { return exceptionColor || normalColor; } if (percent >= 100) { return successColor; } return normalColor; }; const renderInfoCont = () => { let infoCont; if (format) { infoCont = format(percent); } else { infoCont = `${percent}%`; if (percent >= 100) { infoCont = ( <Icon type={type === 'circle' ? 'check' : 'check-circle'} style={{ color: getCurrentColor() }} /> ); } else if (status === 'exception') { infoCont = ( <Icon type={type === 'circle' ? 'close' : 'close-circle'} style={{ color: getCurrentColor() }} /> ); } } return infoCont; }; const renderProgressCont = () => { let progressCont; switch (type) { case 'circle': progressCont = ( <div className={statusCls} style={{ width: progressWidth, height: progressWidth }} > <div className={`${prefix}-progress-wrapper`} style={{ borderRadius: progressWidth, borderWidth: strokeWidth, borderColor: bgColor }} /> <svg className={`${prefix}-progress-inner`}> <circle className={`${prefix}-progress-inner-path`} cx={progressWidth / 2} cy={progressWidth / 2} r={(progressWidth - strokeWidth) / 2} style={{ stroke: getCurrentColor(), strokeWidth, strokeDasharray: Math.PI * (progressWidth - strokeWidth), strokeDashoffset: Math.PI * (progressWidth - strokeWidth) * (100 - percent) / 100 }} /> </svg> {showInfo ? ( <div className={`${prefix}-progress-info`} style={{ lineHeight: `${progressWidth}px` }} > {renderInfoCont()} </div> ) : null} </div> ); break; case 'line': default: progressCont = ( <div className={statusCls}> <div className={`${prefix}-progress-wrapper`} style={{ background: bgColor, width: progressWidth, height: strokeWidth, borderRadius: strokeWidth }} > <div className={`${prefix}-progress-inner`} style={{ background: getCurrentColor(), width: `${percent}%`, height: strokeWidth, borderRadius: strokeWidth }} /> </div> {showInfo ? ( <div className={`${prefix}-progress-info`}> {renderInfoCont()} </div> ) : null} </div> ); break; } return progressCont; }; return ( <div className={containerCls} style={style}> {renderProgressCont()} </div> ); } }