携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第5天,点击查看活动详情
简介
本文将介绍如何实现进度条的自定义渐变色功能,耐心读完,相信会对您有所帮助。
属性
渐变色配置属性继续使用color属性,更新声明支持传入object。
color: {
type: [String, Array, Function, Object],
default: ''
},
传入对象格式为 { from: string; to: string; },排序不做要求。
{
"0%": "#afc163",
"25%": "#66FF00",
"50%": "#00CC00",
"75%": "#009900",
"100%": "#ffffff"
}
新增计算属性 gradientColor 将传入的 color 对象按照百分比排序并转成对象数组 [{percentage: string; color: string;}]。
gradientColor() {
if (typeof this.color !== 'object') {
return undefined;
}
const color = this.color;
const gradient = Object.keys(color)
.sort((a, b) => this.stripPercentToNumber(a) - this.stripPercentToNumber(b))
.map((key, index) => {
return {
percentage: key,
color: color[key]
};
});
return gradient;
},
// methods 排序方法 90% => 90
stripPercentToNumber(percentage) {
return percentage.replace('%', '');
}
线性和环形进度条渐变实现原理不同:
- 线性使用CSS的
linear-gradient()。 - 环形使用SVG的
linearGradient。
环形进度条实现
SVG的linearGradient元素用来定义线性渐变,用于图形元素的填充或描边。
代码中增加 linearGradient 线性渐变声明,元素 id 为计算属性svgGradientId,id 用作颜色填充引用 stroke="url(#id)"。
遍历数组 gradientColor 生成 stop元素列表,用于定义一个渐变上的颜色坡度。
<svg viewBox="0 0 100 100">
<defs v-if="gradientColor">
<linearGradient :id="svgGradientId" x1="100%" y1="0%" x2="0%" y2="0%"
>
<stop :key="index" :offset="item.percentage" :stop-color="item.color"
v-for="(item,index) in gradientColor"/>
</linearGradient>
</defs>
<path
class="el-progress-circle__path"
:stroke="stroke"></path>
</svg>
添加组件属性 processId 记录组件实例ID。新增计算属性svgGradientId,基于processId生成linearGradient元素 id 。
<script>
let processIdSeed = 1;
export default {
name: 'ElProgress',
created() {
this.processId = processIdSeed++;
},
computed: {
svgGradientId() {
return `el-progress--gradient-${this.processId}`;
}
},
}
</script>
进度条的颜色填充使用计算属性 stroke。当自定义颜色时,调用方法 getCurrentColor,接下来改写该方法,支持返回url(#id)内容格式。
新增方法getGradientColor用于生成渐变色配置下的环形颜色属性值 url(#id)。
getCurrentColor(percentage) {
if (typeof this.color === 'function') {
return this.color(percentage);
} else if (typeof this.color === 'string') {
return this.color;
} else if (typeof this.color === 'object') {
return this.getGradientColor();
} else {
return this.getLevelColor(percentage);
}
},
getGradientColor() {
if (this.type === 'circle' || this.type === 'dashboard') {
return `url(#${this.svgGradientId})`;
}
},
示例代码:
<el-progress :percentage="70" type="circle"
:color="{
'0%': '#108ee9',
'100%': '#87d068',
}"
></el-progress>
<el-progress :percentage="70" type="dashboard"
:color="{
'0%': '#108ee9',
'100%': '#87d068',
}"
></el-progress>
运行效果:
线性进度条实现
线性进度条将使用CSS linear-gradient()函数实现渐变色效果。
前文可知线性进度条自定义颜色使用了绑定到内联样式的计算属性barStyle,背景设置调用了方法getCurrentColor。上一章节中环形实现中已经对getCurrentColor一系列方法进行了改写,接下来继续更新支持线性进度条。
barStyle() {
const style = {};
style.width = this.percentage + '%';
style.backgroundColor = this.getCurrentColor(this.percentage);
return style;
},
对getGradientColor()新增逻辑,线性进度条时传入的颜色设置最终生成 backgroundImage: linear-gradient(to right, #afc163 0%, #66FF00 25%,#ffffff 100%),绑定到内联样式中进行渲染。
getGradientColor() {
if (this.type === 'circle' || this.type === 'dashboard') {
return `url(#${this.svgGradientId})`;
}
// type === 'line'
const direction = 'to right'; // 文本方向 LTR
const linearGradients = this.gradientColor
.map(({ color, percentage }) => `${color} ${percentage}`).join(', ');
return `linear-gradient(${direction}, ${linearGradients})`;
},
考虑到代码最小改动和兼容,将backgroundColor 改为background。
barStyle() {
const style = {};
style.width = this.percentage + '%';
style.background = this.getCurrentColor(this.percentage);
return style;
},
示例代码:
<el-progress :percentage="80"
:color="{
'0%': '#108ee9',
'100%': '#87d068',
}"
></el-progress>
运行效果:
组件最终修改代码 progress_new_features gist
参考&关联阅读
"SVG/linearGradient",MDN
"CSS/linear-gradient",MDN
关注专栏
此文章已收录到专栏中 👇,可以直接关注。