feat: 添加进度条自定义颜色配置 (#3837)

Co-authored-by: liujintao03 <liujintao03@baidu.com>
This commit is contained in:
gooolh 2022-03-24 17:52:42 +08:00 committed by GitHub
parent e2a1be9ce0
commit b3c043c80f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 107 additions and 60 deletions

View File

@ -22,10 +22,14 @@ order: 60
## 颜色映射
可以配置`map`,指定颜色映射,例如,默认的 map 配置为:`['bg-danger', 'bg-warning', 'bg-info', 'bg-success', 'bg-success']`
可以配置`map`为单独颜色,例如:`#F96D3E`
若配置为字符串数组,指定颜色映射,例如,默认的 map 配置为:`['bg-danger', 'bg-warning', 'bg-info', 'bg-success', 'bg-success']`
它意味着将进度条分成了 5 份,`前20%`将会添加`bg-danger` css 类名到进度条上,`20%~40%`,将会添加`bg-warning`,以此类推,你可以自定义`map`来配置想要的进度效果
若配置为`[{value: 30, color: "#007bff"}, {value: 60, color: "#F96D3E"}]`, 表示为 value 小于`30`的区间显示`#007bff`, 大于等于`30`则显示`#F96D3E`
```schema
{
"type": "page",
@ -33,7 +37,7 @@ order: 60
{
"type": "progress",
"value": 40,
"map": ["bg-danger", "bg-success"]
"map": "#F96D3E"
},
{
"type": "divider"
@ -48,8 +52,15 @@ order: 60
},
{
"type": "progress",
"value": 60,
"map": ["bg-danger", "bg-success"],
"value": 20,
"map": [{
value: 30,
color: "#007bff"
},
{
value: 60,
color: "#fad733"
}],
"mode": "circle"
},
{
@ -57,8 +68,15 @@ order: 60
},
{
"type": "progress",
"value": 10,
"map": ["bg-danger", "bg-success"],
"value": 50,
"map": [{
value: 50,
color: "#007bff"
},
{
value: 60,
color: "#fad733"
}],
"mode": "circle"
}
]
@ -226,20 +244,18 @@ List 的内容、Card 卡片的内容配置同上
## 属性表
| 属性名 | 类型 | 默认值 | 说明 |
| -------------------- | --------------- | -------------------------------------------------------------------- | ------------------------------------------------- |
| type | `string` | | 如果在 Form 中用作静态展示,为`"static-progress"` |
| mode | `string` | `line` | 进度「条」的类型,可选`line circle dashboard` |
| className | `string` | | 外层 CSS 类名 |
| progressClassName | `string` | `progress-xs progress-striped active m-b-none` | 进度条 CSS 类名 |
| progressBarClassName | `string` | | 完成进度条 CSS 类名 |
| value | `string` | | 进度值 |
| placeholder | `string` | `-` | 占位文本 |
| showLabel | `boolean` | `true` | 是否展示进度文本 |
| stripe | `boolean` | `false` | 背景是否显示条纹 |
| animate | `boolean` | `false` | type 为 line可支持动画 |
| map | `Array<string>` | `['bg-danger', 'bg-warning', 'bg-info', 'bg-success', 'bg-success']` | 进度颜色映射 |
| valueTpl | `string` | `${value}%` | 自定义格式化内容 |
| strokeWidth | `number` | line 类型为`10`circle、dashboard 类型为`6` | 进度条线宽度 |
| gapDegree | `number` | `75` | 仪表盘缺角角度,可取值 0 ~ 295 |
| gapPosition | `string` | `bottom` | 仪表盘进度条缺口位置,可选`top bottom left right` |
| 属性名 | 类型 | 默认值 | 说明 |
| ----------- | ---------------------------------------------------------------- | -------------------------------------------------------------------- | ------------------------------------------------- |
| type | `string` | | 如果在 Form 中用作静态展示,为`"static-progress"` |
| mode | `string` | `line` | 进度「条」的类型,可选`line circle dashboard` |
| className | `string` | | 外层 CSS 类名 |
| value | `string` | | 进度值 |
| placeholder | `string` | `-` | 占位文本 |
| showLabel | `boolean` | `true` | 是否展示进度文本 |
| stripe | `boolean` | `false` | 背景是否显示条纹 |
| animate | `boolean` | `false` | type 为 line可支持动画 |
| map | `string \| Array<string> \| Array<{value:number, color:string}>` | `['bg-danger', 'bg-warning', 'bg-info', 'bg-success', 'bg-success']` | 进度颜色映射 |
| valueTpl | `string` | `${value}%` | 自定义格式化内容 |
| strokeWidth | `number` | line 类型为`10`circle、dashboard 类型为`6` | 进度条线宽度 |
| gapDegree | `number` | `75` | 仪表盘缺角角度,可取值 0 ~ 295 |
| gapPosition | `string` | `bottom` | 仪表盘进度条缺口位置,可选`top bottom left right` |

View File

@ -1,12 +1,15 @@
.#{$ns}Progress {
display: flex;
align-items: center;
color: var(--text-color);
font-size: var(--fontSizeXs);
&-line {
display: inline-block;
width: 100%;
height: 10px;
&-inter {
height: 10px;
height: 100%;
background-color: var(--Progress-bar-backgroundColor);
overflow: hidden;
border-radius: var(--Progress-borderRadius);
@ -16,8 +19,6 @@
display: inline-block;
flex-grow: 1;
margin-left: 8px;
color: var(--text-color);
font-size: var(--fontSizeXs);
white-space: nowrap;
text-align: left;
word-break: normal;
@ -84,9 +85,6 @@
width: 100%;
margin: 0;
padding: 0;
color: var(--text-color);
font-size: 1em;
line-height: 1;
white-space: normal;
text-align: center;
transform: translate(-50%, -50%);

View File

@ -3,21 +3,26 @@ import cx from 'classnames';
import {Circle} from 'rc-progress';
import {ClassNamesFn, themeable, ThemeProps} from '../theme';
import {SchemaClassName} from '../Schema';
interface ColorProps {
value: number;
color: string;
}
export type ColorMapType = Array<string> | Array<ColorProps> | string;
interface ProgressProps extends ThemeProps {
type: 'line' | 'circle' | 'dashboard';
showLabel: boolean;
value: number;
stripe?: boolean;
animate?: boolean;
map?: Array<string>;
map?: ColorMapType;
placeholder?: string;
format?: (value?: number) => JSX.Element;
gapDegree?: number;
gapPosition?: 'top' | 'bottom' | 'left' | 'right';
strokeWidth?: number;
classNames?: string;
progressClassName?: SchemaClassName;
progressBarClassName?: SchemaClassName;
classnames: ClassNamesFn;
}
export class Progress extends React.Component<ProgressProps, Object> {
@ -25,19 +30,46 @@ export class Progress extends React.Component<ProgressProps, Object> {
type: 'line',
placeholder: '-',
progressClassName: '',
progressBarClassName: '',
map: ['bg-danger', 'bg-warning', 'bg-info', 'bg-success', 'bg-success'],
showLabel: true
};
autoClassName(value: number) {
const map = this.props.map;
if (!map || !map.length) {
return '';
getCurrentColor() {
const color = this.props.map;
if (!color || !color.length) {
return 'bg-primary';
}
let index = Math.floor((value * map.length) / 100);
index = Math.max(0, Math.min(map.length - 1, index));
return map[index];
if (typeof color === 'string') {
return color;
} else {
return this.getLevelColor(color);
}
}
getLevelColor(color: Array<string> | Array<ColorProps>) {
const value = this.props.value;
const colorArray = this.getColorArray(color).sort(
(a: {value: number}, b: {value: number}) => a.value - b.value
);
for (let i = 0; i < colorArray.length; i++) {
if (colorArray[i].value > value) {
return colorArray[i].color;
}
}
return colorArray[colorArray.length - 1].color;
}
getColorArray(color: Array<string> | Array<ColorProps>) {
const span = 100 / color.length;
return color.map((item, index) => {
if (typeof item === 'string') {
return {
color: item,
value: (index + 1) * span
};
}
return item;
});
}
getLabel(prefixCls: string) {
@ -56,15 +88,13 @@ export class Progress extends React.Component<ProgressProps, Object> {
render() {
const {
classNames,
className,
progressClassName,
progressBarClassName,
type,
value,
placeholder,
stripe,
animate,
showLabel,
gapDegree,
gapPosition,
strokeWidth,
@ -73,28 +103,33 @@ export class Progress extends React.Component<ProgressProps, Object> {
const isLineType = type === 'line';
const prefixCls = isLineType ? 'Progress-line' : 'Progress-circle';
const bgColor = this.getCurrentColor();
const isColorClass = /bg-/.test(bgColor);
let viewValue: React.ReactNode;
if (typeof value !== 'number') {
viewValue = <span className="text-muted">{placeholder}</span>;
} else if (type === 'line') {
const style: any = {};
const barStyle: any = {
width: `${value}%`
};
strokeWidth && (style.height = strokeWidth);
!isColorClass && (barStyle.backgroundColor = bgColor);
viewValue = [
<div key="progress" className={cx(prefixCls, progressClassName)}>
<div className={cx(`${prefixCls}-inter`)} style={style}>
<div
className={cx(
`${prefixCls}-bar`,
progressBarClassName || this.autoClassName(value),
{[bgColor]: isColorClass},
{[`${prefixCls}-bar--stripe`]: stripe},
{[`${prefixCls}-bar--animate`]: animate && !stripe},
{[`${prefixCls}-bar--stripe-animate`]: animate && stripe}
)}
title={`${value}%`}
style={{
width: `${value}%`
}}
style={barStyle}
/>
</div>
</div>,
@ -114,13 +149,13 @@ export class Progress extends React.Component<ProgressProps, Object> {
};
viewValue = [
<div className={cx(prefixCls)} key="circle">
<div className={cx(prefixCls, progressClassName)} key="circle">
<Circle
percent={value}
strokeColor=""
strokeColor={!isColorClass ? bgColor : ''}
strokeWidth={circleWidth}
trailWidth={circleWidth}
prefixCls={this.autoClassName(value)}
prefixCls={isColorClass ? bgColor : ''}
gapDegree={getGapDegree()}
gapPosition={gapPos}
/>
@ -129,7 +164,7 @@ export class Progress extends React.Component<ProgressProps, Object> {
];
}
return <div className={cx('Progress', classNames)}>{viewValue}</div>;
return <div className={cx('Progress', className)}>{viewValue}</div>;
}
}

View File

@ -6,6 +6,8 @@ import {autobind, getPropValue, createObject} from '../utils/helper';
import {filter} from '../utils/tpl';
import Progress from '../components/Progress';
import {ColorMapType} from '../components/Progress';
/**
*
* https://baidu.gitee.io/amis/docs/components/progress
@ -29,14 +31,9 @@ export interface ProgressSchema extends BaseSchema {
progressClassName?: SchemaClassName;
/**
* CSS
*
*/
progressBarClassName?: SchemaClassName;
/**
*
*/
map?: Array<string>;
map?: ColorMapType;
/**
*
@ -62,14 +59,17 @@ export interface ProgressSchema extends BaseSchema {
* 线
*/
strokeWidth?: number;
/**
* 0 ~ 295
*/
gapDegree?: number;
/**
*
*/
gapPosition?: 'top' | 'bottom' | 'left' | 'right';
/**
*
*/
@ -106,7 +106,6 @@ export class ProgressField extends React.Component<ProgressProps, object> {
className,
placeholder,
progressClassName,
progressBarClassName,
map,
stripe,
animate,
@ -137,7 +136,6 @@ export class ProgressField extends React.Component<ProgressProps, object> {
gapPosition={gapPosition}
className={className}
progressClassName={progressClassName}
progressBarClassName={progressBarClassName}
/>
);
}