代码实现 环形进度条

2,421 阅读1分钟

前言

进度条在日常的开发中使用的很频繁,比如文件的上传和下载,资源的准备进度都需要用到。常见的形式为两种(条形和环形)。文本手把手实现一个简单的环形进度条。

Snipaste_2022-05-03_15-03-10.jpg

原理

实现环形进度条的原理:使用两个半圆来拼成一个整圆。再监听进度,调整旋转的角度。

左半圆为蓝色的部分,左半圆在进度大于50%时使用,先看一下没有加overflow: hidden;时的样子 动画.gif

再看一下加了overflow: hidden; 动画1.gif

右半圆和左半圆的实现基本一致,看完整效果

动画2.gif

实现代码

<template>
  <div class="cd-propgress-circle-frame">
    <div :class="{ 'cd-propgress-circle-div': true }">
      <div class="cd-propgress-circle-left-div">
        <div :class="{ 'cd-propgress-circle-left': true }"></div>
      </div>
      <div class="cd-propgress-circle-right-div">
        <div :class="{ 'cd-propgress-circle-right': true }"></div>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { ref, watch } from "vue";
let leftRotate = ref<number>();
let rightRotate = ref<number>();
let widthData = ref<number>(300);
let color = ref<string>("red");
let percentage = ref<number>(0);
setInterval(() => {
  percentage.value += 5;
}, 200);
watch(
  percentage,
  (newval, oldval) => {
    if (newval >= 0 && newval <= 50) {
      rightRotate.value = (newval / 50) * 180;
      leftRotate.value = 0;
    } else if (newval > 50 && newval <= 100) {
      rightRotate.value = 180;
      leftRotate.value = ((newval - 50) / 50) * 180;
    }
  },
  { immediate: true }
);
</script>

<style>
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
.cd-propgress-circle-frame {
  position: relative;
  height: v-bind(widthData + "px");
  width: v-bind(widthData + "px");
  border-radius: 50%;
  border: 2px solid #ebeef5;
}
.cd-propgress-circle-div {
  position: absolute;
  top: -2px;
  left: 0;
  display: flex;
  height: v-bind(heightData + "px");
  width: v-bind(widthData + "px");
}
.cd-propgress-circle-left-div {
  overflow: hidden;
  height: v-bind(widthData + "px");
  width: v-bind(widthData/2 + "px");
}
.cd-propgress-circle-left {
  height: v-bind(widthData + "px");
  width: v-bind(widthData + "px");
  border-radius: 50%;
  border-width: 2px;
  border-color: v-bind(color);
  border-top-color: transparent;
  border-right-color: transparent;
  border-style: solid;
  transform: v-bind("'rotate('+(-135+leftRotate)+'deg'+')'");
}
.cd-propgress-circle-right-div {
  position: relative;
  overflow: hidden;
  height: v-bind(widthData + "px");
  width: v-bind(widthData/2 + "px");
}
.cd-propgress-circle-right {
  position: absolute;
  right: 0;
  height: v-bind(widthData + "px");
  width: v-bind(widthData + "px");
  border-radius: 50%;
  border-width: 2px;
  border-color: v-bind(color);
  border-top-color: transparent;
  border-left-color: transparent;
  border-style: solid;
  transform: v-bind("'rotate('+(-225+rightRotate)+'deg'+')'");
}
</style>

结语

了解下是怎样实现的就行,关键时候还是直接上组件库。