diff --git a/examples/docs/en-US/progress.md b/examples/docs/en-US/progress.md index d5c195f7..9ead51ff 100644 --- a/examples/docs/en-US/progress.md +++ b/examples/docs/en-US/progress.md @@ -2,29 +2,100 @@ Progress is used to show the progress of current operation, and inform the user the current status. -### Linear progress bar (external percentage) +### Linear progress bar -:::demo Use `percentage` attribute to set the percentage. It's **required** and must be between `0-100`. +:::demo Use `percentage` attribute to set the percentage. It's **required** and must be between `0-100`. You can custom text format by setting `format`. ```html - - - + + + + + ``` ::: -### Linear progress bar (internal percentage) +### Internal percentage In this case the percentage takes no additional space. :::demo `stroke-width` attribute decides the `width` of progress bar, and use `text-inside` attribute to put description inside the progress bar. ```html - - - - - + + + + +``` +::: + +### Custom color + +You can use `color` attr to set the progress bar color. it accepts color string, function, or array. + +:::demo + +```html + + + + + +
+ + + + +
+ + ``` ::: @@ -34,20 +105,68 @@ In this case the percentage takes no additional space. ```html - + -``` +``` +::: + +### Dashboard progress bar + +You also can specify `type` attribute to `dashboard` to use dashboard progress bar. + +:::demo + +```html + +
+ + + + +
+ + +``` ::: ### Attributes | Attribute | Description | Type | Accepted Values | Default | | --- | ---- | ---- | ---- | ---- | | **percentage** | percentage, **required** | number | 0-100 | 0 | -| type | the type of progress bar | string | line/circle | line | +| type | the type of progress bar | string | line/circle/dashboard | line | | stroke-width | the width of progress bar | number | — | 6 | | text-inside | whether to place the percentage inside progress bar, only works when `type` is 'line' | boolean | — | false | -| status | the current status of progress bar | string | success/exception | — | -| color | background color of progress bar. Overrides `status` prop | string | — | — | +| status | the current status of progress bar | string | success/exception/warning | — | +| color | background color of progress bar. Overrides `status` prop | string/function/array | — | '' | | width | the canvas width of circle progress bar | number | — | 126 | | show-text | whether to show percentage | boolean | — | true | diff --git a/examples/docs/es/progress.md b/examples/docs/es/progress.md index 3008fe92..7cc028b3 100644 --- a/examples/docs/es/progress.md +++ b/examples/docs/es/progress.md @@ -1,28 +1,100 @@ ## Progreso Progreso es usado para mostrar el estado de la operación actual e informar al usuario acerca de ésta. -### Barra de progreso lineal (porcentage externo) +### Barra de progreso lineal + +:::demo Usa el atributo `percentage` para asignar el porcentage. Este es **requerido** y tiene que ser un valor entre `0-100`. You can custom text format by setting `format`. -:::demo Usa el atributo `percentage` para asignar el porcentage. Este es **requerido** y tiene que ser un valor entre `0-100`. ```html - - - + + + + + ``` ::: -### Barra de progreso lineal (porcentage interno) +### Pporcentage interno En este caso el porcentage no toma espacio adicional. :::demo El atributo `stroke-width` decide el ancho de la barra de progreso, y usa el atributo `text-inside` para poner la descripción dentro de la misma. ```html - - - - - + + + + +``` +::: + +### Custom color + +You can use `color` attr to set the progress bar color. it accepts color string, function, or array. + +:::demo + +```html + + + + + +
+ + + + +
+ + ``` ::: @@ -32,20 +104,67 @@ En este caso el porcentage no toma espacio adicional. ```html - + ``` ::: +### Dashboard progress bar + +:::demo You also can specify `type` attribute to `dashboard` to use dashboard progress bar. + +```html + + +
+ + + + +
+ + +``` +::: + ### Atributos | Atributo | Descripción | Tipo | Valores aceptado | Por defecto | | ------------ | ---------------------------------------- | ------- | ----------------- | ----------- | | percentage | porcentaje, requerido | number | 0-100 | 0 | -| type | tipo de barra de progreso | string | line/circle | line | +| type | tipo de barra de progreso | string | line/circle/dashboard | line | | stroke-width | ancho de la barra de progreso | number | — | 6 | | text-inside | mostrar el porcentaje dentro de la barra de progreso, solo funciona cuando `type` es 'line' | boolean | — | false | -| status | estado actual de la barra de progreso | string | success/exception | — | -| color | color de fondo de la barra de progreso. Sobreescribe la propiedad `status` | string | — | — | +| status | estado actual de la barra de progreso | string | success/exception/warning | — | +| color | color de fondo de la barra de progreso. Sobreescribe la propiedad `status` | string/function/array | — | '' | | width | ancho del canvas que contiene la barra de progreso circula | number | — | 126 | | show-text | mostrar porcentaje | boolean | — | true | diff --git a/examples/docs/fr-FR/progress.md b/examples/docs/fr-FR/progress.md index ea9cd712..142de3fd 100644 --- a/examples/docs/fr-FR/progress.md +++ b/examples/docs/fr-FR/progress.md @@ -2,29 +2,100 @@ Progress est utilisé pour afficher la progression d'une opération et informer l'utilisateur de son status actuel. -### Barre de progression linéaire (pourcentage externe) +### Barre de progression linéaire -:::demo Utilisez l'attribut `percentage` pour indiquer le pourcentage. Cet attribut est **requis** et doit être compris entre 0 et 100. +:::demo Utilisez l'attribut `percentage` pour indiquer le pourcentage. Cet attribut est **requis** et doit être compris entre 0 et 100. You can custom text format by setting `format`. ```html - - - + + + + + ``` ::: -### Barre de progression linéaire (pourcentage interne) +### Pourcentage interne Dans ce cas le pourcentage ne prends pas de place en plus. :::demo L'attribut `stroke-width` détermine le `width` de la barre de progression. Utilisez `text-inside` mettre la description à l'intérieur de la barre. ```html - - - - - + + + + +``` +::: + +### Custom color + +You can use `color` attr to set the progress bar color. it accepts color string, function, or array. + +:::demo + +```html + + + + + +
+ + + + +
+ + ``` ::: @@ -34,10 +105,57 @@ Dans ce cas le pourcentage ne prends pas de place en plus. ```html - + -Terminé +``` +::: + +### Dashboard progress bar + +You also can specify `type` attribute to `dashboard` to use dashboard progress bar. + +:::demo + +```html + +
+ + + + +
+ + ``` ::: @@ -46,10 +164,10 @@ Dans ce cas le pourcentage ne prends pas de place en plus. | Attribut | Description | Type | Valeurs acceptées | Défaut | | --- | ---- | ---- | ---- | ---- | | **percentage** | Le pourcentage, **requis**. | number | 0-100 | 0 | -| type | Le type de barre. | string | line/circle | line | +| type | Le type de barre. | string | line/circle/dashboard | line | | stroke-width | La largeur de la barre. | number | — | 6 | | text-inside | Si le pourcentage doit être à l'intérieur de la barre, ne marche que si `type` est 'line'. | boolean | — | false | | status | Le statut actuel de la progression. | string | success/exception/text | — | -| color | La couleur de fon de la barre. Écrase `status`. | string | — | — | +| color | La couleur de fon de la barre. Écrase `status`. | string/function/array | — | '' | | width | La largeur du canvas dans le cas d'une barre circulaire. | number | — | 126 | | show-text | Si le pourcentage doit être affiché. | boolean | — | true | diff --git a/examples/docs/zh-CN/progress.md b/examples/docs/zh-CN/progress.md index 6e8fb128..b47a95c8 100644 --- a/examples/docs/zh-CN/progress.md +++ b/examples/docs/zh-CN/progress.md @@ -2,55 +2,175 @@ 用于展示操作进度,告知用户当前状态和预期。 -### 线形进度条 — 百分比外显 +### 线形进度条 -:::demo Progress 组件设置`percentage`属性即可,表示进度条对应的百分比,**必填**,必须在 0-100。 +:::demo Progress 组件设置`percentage`属性即可,表示进度条对应的百分比,**必填**,必须在 0-100。通过 `format` 属性来指定进度条文字内容。 ```html - - - + + + + + ``` ::: -### 线形进度条 — 百分比内显 +### 百分比内显 百分比不占用额外控件,适用于文件上传等场景。 :::demo Progress 组件可通过 `stroke-width` 属性更改进度条的高度,并可通过 `text-inside` 属性来将进度条描述置于进度条内部。 ```html - - - - - + + + + +``` +::: + +### 自定义颜色 + +可以通过 `color` 设置进度条的颜色,`color` 可以接受颜色字符串,函数和数组。 + +:::demo + +```html + + + + + +
+ + + + +
+ + ``` ::: ### 环形进度条 -:::demo Progress 组件可通过 `type` 属性来指定使用环形进度条,在环形进度条中,还可以通过 `width` 属性来设置其大小。 +Progress 组件可通过 `type` 属性来指定使用环形进度条,在环形进度条中,还可以通过 `width` 属性来设置其大小。 + +:::demo ```html - + ``` ::: +### 仪表盘形进度条 + +:::demo 通过 `type` 属性来指定使用仪表盘形进度条。 + +```html + + +
+ + + + +
+ + +``` +::: + ### Attributes | 参数 | 说明 | 类型 | 可选值 | 默认值 | |------------- |---------------- |---------------- |---------------------- |-------- | -| **percentage** | **百分比(必填)** | number | 0-100 | 0 | -| type | 进度条类型 | string | line/circle | line | +| **percentage** | **百分比(必填)** | number | 0-100 | 0 | +| type | 进度条类型 | string | line/circle/dashboard | line | | stroke-width | 进度条的宽度,单位 px | number | — | 6 | | text-inside | 进度条显示文字内置在进度条内(只在 type=line 时可用) | boolean | — | false | -| status | 进度条当前状态 | string | success/exception | — | -| color | 进度条背景色(会覆盖 status 状态颜色) | string | — | — | -| width | 环形进度条画布宽度(只在 type=circle 时可用) | number | | 126 | +| status | 进度条当前状态 | string | success/exception/warning | — | +| color | 进度条背景色(会覆盖 status 状态颜色) | string/function/array | — | '' | +| width | 环形进度条画布宽度(只在 type 为 circle 或 dashboard 时可用) | number | | 126 | | show-text | 是否显示进度条文字内容 | boolean | — | true | diff --git a/packages/progress/src/progress.vue b/packages/progress/src/progress.vue index e1337d85..488d54b2 100644 --- a/packages/progress/src/progress.vue +++ b/packages/progress/src/progress.vue @@ -17,14 +17,27 @@
-
{{percentage}}%
+
{{content}}
- - + +
- +
@@ -44,7 +57,7 @@ type: { type: String, default: 'line', - validator: val => ['line', 'circle'].indexOf(val) > -1 + validator: val => ['line', 'circle', 'dashboard'].indexOf(val) > -1 }, percentage: { type: Number, @@ -53,7 +66,8 @@ validator: val => val >= 0 && val <= 100 }, status: { - type: String + type: String, + validator: val => ['success', 'exception', 'warning'].indexOf(val) > -1 }, strokeWidth: { type: Number, @@ -72,41 +86,65 @@ default: true }, color: { - type: String, + type: [String, Array, Function], default: '' - } + }, + format: Function }, computed: { barStyle() { const style = {}; style.width = this.percentage + '%'; - style.backgroundColor = this.color; + style.backgroundColor = this.getCurrentColor(this.percentage); return style; }, relativeStrokeWidth() { return (this.strokeWidth / this.width * 100).toFixed(1); }, + radius() { + if (this.type === 'circle' || this.type === 'dashboard') { + return parseInt(50 - parseFloat(this.relativeStrokeWidth) / 2, 10); + } else { + return 0; + } + }, trackPath() { - const radius = parseInt(50 - parseFloat(this.relativeStrokeWidth) / 2, 10); - - return `M 50 50 m 0 -${radius} a ${radius} ${radius} 0 1 1 0 ${radius * 2} a ${radius} ${radius} 0 1 1 0 -${radius * 2}`; + const radius = this.radius; + const isDashboard = this.type === 'dashboard'; + return ` + M 50 50 + m 0 ${isDashboard ? '' : '-'}${radius} + a ${radius} ${radius} 0 1 1 0 ${isDashboard ? '-' : ''}${radius * 2} + a ${radius} ${radius} 0 1 1 0 ${isDashboard ? '' : '-'}${radius * 2} + `; }, perimeter() { - const radius = 50 - parseFloat(this.relativeStrokeWidth) / 2; - return 2 * Math.PI * radius; + return 2 * Math.PI * this.radius; + }, + rate() { + return this.type === 'dashboard' ? 0.75 : 1; + }, + strokeDashoffset() { + const offset = -1 * this.perimeter * (1 - this.rate) / 2; + return `${offset}px`; + }, + trailPathStyle() { + return { + strokeDasharray: `${(this.perimeter * this.rate)}px, ${this.perimeter}px`, + strokeDashoffset: this.strokeDashoffset + }; }, circlePathStyle() { - const perimeter = this.perimeter; return { - strokeDasharray: `${perimeter}px,${perimeter}px`, - strokeDashoffset: (1 - this.percentage / 100) * perimeter + 'px', - transition: 'stroke-dashoffset 0.6s ease 0s, stroke 0.6s ease' + strokeDasharray: `${this.perimeter * this.rate * (this.percentage / 100) }px, ${this.perimeter}px`, + strokeDashoffset: this.strokeDashoffset, + transition: 'stroke-dasharray 0.6s ease 0s, stroke 0.6s ease' }; }, stroke() { let ret; if (this.color) { - ret = this.color; + ret = this.getCurrentColor(this.percentage); } else { switch (this.status) { case 'success': @@ -115,6 +153,9 @@ case 'exception': ret = '#ff4949'; break; + case 'warning': + ret = '#e6a23c'; + break; default: ret = '#20a0ff'; } @@ -122,6 +163,9 @@ return ret; }, iconClass() { + if (this.status === 'warning') { + return 'el-icon-warning'; + } if (this.type === 'line') { return this.status === 'success' ? 'el-icon-circle-check' : 'el-icon-circle-close'; } else { @@ -132,6 +176,47 @@ return this.type === 'line' ? 12 + this.strokeWidth * 0.4 : this.width * 0.111111 + 2 ; + }, + content() { + if (typeof this.format === 'function') { + return this.format(this.percentage) || ''; + } else { + return `${this.percentage}%`; + } + } + }, + methods: { + getCurrentColor(percentage) { + if (typeof this.color === 'function') { + return this.color(percentage); + } else if (typeof this.color === 'string') { + return this.color; + } else { + return this.getLevelColor(percentage); + } + }, + getLevelColor(percentage) { + const colorArray = this.getColorArray().sort((a, b) => a.percentage - b.percentage); + + for (let i = 0; i < colorArray.length; i++) { + if (colorArray[i].percentage > percentage) { + return colorArray[i].color; + } + } + return colorArray[colorArray.length - 1].color; + }, + getColorArray() { + const color = this.color; + const span = 100 / color.length; + return color.map((seriesColor, index) => { + if (typeof seriesColor === 'string') { + return { + color: seriesColor, + progress: (index + 1) * span + }; + } + return seriesColor; + }); } } }; diff --git a/packages/theme-chalk/src/progress.scss b/packages/theme-chalk/src/progress.scss index 1280fba1..e6139f59 100644 --- a/packages/theme-chalk/src/progress.scss +++ b/packages/theme-chalk/src/progress.scss @@ -20,7 +20,7 @@ } } - @include m(circle) { + @include m((circle,dashboard)) { display: inline-block; .el-progress__text { @@ -39,6 +39,7 @@ } } + @include m(without-text) { .el-progress__text { display: none; @@ -68,6 +69,16 @@ } } + @include when(warning) { + .el-progress-bar__inner { + background-color: $--color-warning; + } + + .el-progress__text { + color: $--color-warning; + } + } + @include when(exception) { .el-progress-bar__inner { background-color: $--color-danger; diff --git a/test/unit/specs/progress.spec.js b/test/unit/specs/progress.spec.js index 3bb3f25b..e1dcfefa 100644 --- a/test/unit/specs/progress.spec.js +++ b/test/unit/specs/progress.spec.js @@ -1,4 +1,4 @@ -import { createVue, destroyVM } from '../util'; +import { createVue, destroyVM, waitImmediate } from '../util'; describe('Progress', () => { let vm; @@ -78,6 +78,14 @@ describe('Progress', () => { }, true); expect(vm.$el.classList.contains('el-progress--circle')).to.be.true; }); + it('dashboard', () => { + vm = createVue({ + template: ` + + ` + }, true); + expect(vm.$el.classList.contains('el-progress--dashboard')).to.be.true; + }); it('width', () => { vm = createVue({ template: ` @@ -103,4 +111,81 @@ describe('Progress', () => { }, true); expect(vm.$el.querySelector('.el-progress-bar__inner').style.backgroundColor).to.equal('rgb(0, 0, 0)'); }); + it('color is function', async() => { + vm = createVue({ + template: ` + + `, + data() { + return { + percentage: 50 + }; + }, + methods: { + customColor(percentage) { + if (percentage > 50) { + return '#13ce66'; + } else { + return '#20a0ff'; + } + }, + increase() { + this.percentage = 60; + } + } + }, true); + + expect(vm.$el.querySelector('.el-progress-bar__inner').style.backgroundColor).to.equal('rgb(32, 160, 255)'); + vm.increase(); + + await waitImmediate(); + expect(vm.$el.querySelector('.el-progress-bar__inner').style.backgroundColor).to.equal('rgb(19, 206, 102)'); + }); + + it('color is array', async() => { + vm = createVue({ + template: ` + + `, + data() { + return { + percentage: 50, + colors: [ + {color: '#f56c6c', percentage: 20}, + {color: '#e6a23c', percentage: 40}, + {color: '#20a0ff', percentage: 60}, + {color: '#13ce66', percentage: 80}, + {color: '#6f7ad3', percentage: 100} + ] + }; + }, + methods: { + increase() { + this.percentage = 70; + } + } + }, true); + + // #20a0ff + expect(vm.$el.querySelector('.el-progress-bar__inner').style.backgroundColor).to.equal('rgb(32, 160, 255)'); + + vm.increase(); + await waitImmediate(); + // #13ce66 + expect(vm.$el.querySelector('.el-progress-bar__inner').style.backgroundColor).to.equal('rgb(19, 206, 102)'); + }); + + it('format content', () => { + vm = createVue({ + template: ` + + `, + methods: { + format(percentage) { + return `占比${percentage}%`; + } + } + }, true); + expect(vm.$el.querySelector('.el-progress__text').innerHTML).to.equal('占比50%'); + }); }); diff --git a/types/progress.d.ts b/types/progress.d.ts index 933347c4..0831514d 100644 --- a/types/progress.d.ts +++ b/types/progress.d.ts @@ -21,11 +21,14 @@ export declare class ElProgress extends ElementUIComponent { status: ProgressStatus /** Background color of progress bar. Overrides `status` prop */ - color: string + color: string | Function | Array /** The canvas width of circle progress bar */ width: number /** Whether to show percentage */ showText: boolean + + /** Template function of the content */ + format(percentage: number): string }