这是我参与11月更文挑战的第22天,活动详情查看:2021最后一次更文挑战
介绍
不知道之前讲过用svg写个环形进度条vue组件,本期作为其后的延续,我们将单纯使用css不借助svg看看怎么做一款带有科技感半环的进度条。我们先来一睹为快吧~
还可以吧,接下来,就要实现他了,因为这是一款vue组件,至于怎么创建项目和怎么使用过于基础,这里就不做赘述了,我们的精力都集中在组件的实现上。
正文
1.传参介绍
export default {
name: "ProgressBar",
props: {
value: {
type: [String, Number],
defalut: 0
},
text: {
type: String,
defalut: "speed"
},
color: {
type: String,
defalut: "#63cdda"
}
},
mounted() {},
methods: {}
}
复制代码
我们这里会接收3个参数:
- value:进度值
- text:介绍文本
- color:主色调
2.基础结构
<template>
<div class="progress-bar" ref="bar">
<div class="hoop" ref="hoop"></div>
<h5>
<span ref="speed">0</span>%
</h5>
<p>{{text}}</p>
</div>
</template>
复制代码
这里我们只会把text写进去,色调后面会通过js去改变,而进度值我们后面也会通过动画去实现这里就只能传0。
3.全部样式
@import "https://fonts.googleapis.com/css?family=Share+Tech+Mono";
.progress-bar {
--skin-color: #63cdda;
position: relative;
width: 200px;
height: 100px;
border-radius: 200px 200px 0 0;
overflow: hidden;
background: rgba(48, 47, 47,.5);
&::before {
content: "";
display: block;
position: absolute;
top: 5px;
left: 5px;
right: 5px;
height: 100px;
border-radius: 200px 200px 0 0;
background-color: #000;
z-index: 8;
}
&::after {
content: "";
display: block;
position: absolute;
top: 10px;
left: 10px;
right: 10px;
height: 100px;
border: 5px double var(--skin-color);
opacity: 0.25;
border-radius: 200px 200px 0 0;
z-index: 8;
}
.hoop {
position: absolute;
width: 220px;
height: 420px;
left: -10px;
background-color: var(--skin-color);
bottom: -5px;
transform: rotate(180deg);
transform-origin: 50% bottom;
}
h5 {
font-family: "Share Tech Mono", monospace;
font-size: 2em;
color: white;
font-weight: normal;
text-shadow: 0 0 0.2em var(--skin-color), 0 0 0.3em white;
text-align: center;
position: relative;
margin-top: 40px;
z-index: 9;
}
p {
position: relative;
text-transform: uppercase;
font-weight: normal;
font-family: "Share Tech Mono", monospace;
font-size: 1.2em;
margin: 0.3em 0;
color: white;
text-align: center;
text-shadow: 0 0 0.3em var(--skin-color), 0 0 0.6em white;
z-index: 9;
}
}
复制代码
这些就是我们将会用到的所有样式了。接下来讲一下主要都做了那些事:
-
这里将创造一个200*100的矩形,用border-radius: 200px 200px 0 0;这样就变了一个半圆。
-
下来我们用before伪类在里面再画一个小半圆,切记小圆环的色值一定要和背景色一直,这里其实就是用了障眼法,盖住圆环内部使之就会留一道外边,这样空进度条就做完了。为了稍加点缀,再用after伪类border样式用double绘制两条圆弧线。
-
现在我们要画填充的圆弧,其实还是一样,再画一个矩形,以半圆中心为底,当有值时我们进行旋转,这样会盖住整个盒子的底色,就是用这种障眼法去实现了一个进度条加载。不懂的请看示意图:
4.修改主色
我们在此之前用了css定义了主色调--skin-color,接下来将通过js去根据闯入的值去进行修改
export default {
name: "ProgressBar",
mounted() {
this.initSkin();
},
methods: {
initSkin() {
this.$refs.bar.style.setProperty('--skin-color',this.color)
},
}
}
复制代码
这里用setProperty就可以修改主色调了,在mounted去初始化一下,就大功告成了。
5.加载动画
现在其实还动不起来,因为我们要通过动画来完成他的数值和样式变化,为了后面的更好扩展与体验,这里选用了anime.js来协助我们完成动画。
import anime from "animejs";
export default {
name: "ProgressBar",
methods: {
render() {
anime({
targets: this.$refs.speed,
textContent: [0, this.value],
round: 1,
easing: "easeOutCirc",
duration: 1000
});
anime({
targets: this.$refs.hoop,
rotate: {
value: [180, (this.value * 180) / 100 + 180]
},
easing: "easeOutCirc",
duration: 1000
});
}
}
}
复制代码
第一个anime是字体动画,切记一定要把 round设置成1,不然不设置那么会出现小数。
第二个anime就是颜色块旋转动画,因为一开始我们在rotate设置了180deg让他水平在底部,其变化就在于180到360之间,所以要用百进制去换算一下他的度数。
现在我们没有借助svg,紧靠这个半环进度条组件就实现完成了。
结语
最后,我们可以思考一下svg与css的来实现这种的优缺点吧。
svg需要一些学习成本,毕竟这块很多前端都是软肋,但是其扩展,适应性上都算是比较好的方案了。
css无疑是最容易实现的,连小白都可以看懂使用和改造,兼容性也会好些。但是缺点也很明显,这次用了障眼法叠底去实现的,如果背景色换了,这个也需要去改,比较麻烦,而且放大缩小也不会像svg那样完美。当然,还有其他方案可以不考虑背景色的转换问题,要么是通过绘制渐变背景或者通过clip裁切去完成,但是其缺点都是兼容问题和扩展问题比较麻烦,最后还是障眼法叠底适用范围会更广,就选择了它作为本期案例。
大家有时间都可以练习一下这些方式,对css的学习很有帮助的。