教你用css来做个半环进度条vue组件

这是我参与11月更文挑战的第22天,活动详情查看:2021最后一次更文挑战

介绍

不知道之前讲过用svg写个环形进度条vue组件,本期作为其后的延续,我们将单纯使用css不借助svg看看怎么做一款带有科技感半环的进度条。我们先来一睹为快吧~

VID_20211121_193856.gif

还可以吧,接下来,就要实现他了,因为这是一款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;
  }
}
复制代码

这些就是我们将会用到的所有样式了。接下来讲一下主要都做了那些事:

  1. 这里将创造一个200*100的矩形,用border-radius: 200px 200px 0 0;这样就变了一个半圆。

    微信截图_20211121200126.png

  2. 下来我们用before伪类在里面再画一个小半圆,切记小圆环的色值一定要和背景色一直,这里其实就是用了障眼法,盖住圆环内部使之就会留一道外边,这样空进度条就做完了。为了稍加点缀,再用after伪类border样式用double绘制两条圆弧线。

    微信截图_20211121200838.png

  3. 现在我们要画填充的圆弧,其实还是一样,再画一个矩形,以半圆中心为底,当有值时我们进行旋转,这样会盖住整个盒子的底色,就是用这种障眼法去实现了一个进度条加载。不懂的请看示意图:

    VID_20211121_201606.gif

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去初始化一下,就大功告成了。

微信截图_20211121201012.png

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,紧靠这个半环进度条组件就实现完成了。

VID_20211121_193856.gif

结语

最后,我们可以思考一下svg与css的来实现这种的优缺点吧。

svg需要一些学习成本,毕竟这块很多前端都是软肋,但是其扩展,适应性上都算是比较好的方案了。

css无疑是最容易实现的,连小白都可以看懂使用和改造,兼容性也会好些。但是缺点也很明显,这次用了障眼法叠底去实现的,如果背景色换了,这个也需要去改,比较麻烦,而且放大缩小也不会像svg那样完美。当然,还有其他方案可以不考虑背景色的转换问题,要么是通过绘制渐变背景或者通过clip裁切去完成,但是其缺点都是兼容问题和扩展问题比较麻烦,最后还是障眼法叠底适用范围会更广,就选择了它作为本期案例。

大家有时间都可以练习一下这些方式,对css的学习很有帮助的。

猜你喜欢

转载自juejin.im/post/7033233412806672414