共计 5669 个字符,预计需要花费 15 分钟才能阅读完成。
前言
最近我的项目有用到圆环进度条,所以也找了一些文章,看看是如何实现的。市面上的文章讲述的实现形式根本都是两个长方形旋转和 canvas 这两种形式,大家如果有趣味能够本人去找找,百度一搜一大把????。
然而我做的我的项目是小程序(提供 demo 是 vue 版本),canvas 层级十分高,尽管官网提供了同层 canvas,然而同层 canvas 在官网社区上反馈 bug 十分多,而且感觉比拟重,所以就没思考。两个长方形旋转的形式我之前也试过,真机上两个长方形交接处会存在差不多 1px 的间距,始终无奈修复,也没法和设计说只能这样是不是。
而后无意之中看到了这样一个 demo,感觉关上了新世界,原来圆环进度条还能这样实现啊!!
linear-gradient 实现圆环
先看下先看下咱们要实现的成果
下面的图能够拆分为 4 个 dom 构造,或者这样看你更清晰
最底层为深红色的圆
两头红色的小圆,用来遮蔽最底层的圆,视觉上造成圆环的成果
彩色的两个小圆,用于实现带圆弧的圆环进度条
首先咱们先实现最底部深红色的圆
<div class="progress-radial"></div>
.progress-radial {
position: relative;
width: 120rpx;
height: 120rpx;
border-radius: 50%;
background-image: linear-gradient(90deg, #C40006 %, #FECC1C);
line-height: normal;
display: flex;
align-items: center;
justify-content: center;
z-index: 1;
}
这时咱们会失去这样一个圆
当然,这必定不是咱们想要的成果,咱们并不需要这个 过渡 的成果,所以能够批改一下 linear-gradient 的节点,让节点重合造成清晰的界限
background-image: linear-gradient(90deg, #C40006 50%, #FECC1C 50%, #FECC1C);
这时咱们就能够失去一个两种色彩对半分并且没有过渡色的圆
假如咱们把 黄色 作为以后进度,那咱们在这个圆上加个遮罩层,不就能够失去一个进度为 50% 的圆环进度条了吗!
<div class="progress-radial">
<div class="progress-text"></div>
</div>
.progress-radial {
position: relative;
width: 120rpx;
height: 120rpx;
border-radius: 50%;
background-image: linear-gradient(90deg, #C40006 50%, #FECC1C 50%, #FECC1C);
line-height: normal;
display: flex;
align-items: center;
justify-content: center;
z-index: 1;
}
.progress-radial .progress-text {
width: 88rpx;
height: 88rpx;
background: #ED1937;
border-radius: 50%;
}
尽管。。。咱们失去了这个 50% 的圆环进度条,然而进度不可能始终都是 50% 呀????,咱们必须依据理论的数据去算进度到底是多少,也就是说,咱们必须要让这个进度条动起来。
那咱们该怎么让进度条动起来那
假如咱们先动一下 linear-gradient 的 angle,让 angle = 145deg 会失去上面这样的状况
尽管进度是动了起来,然而进度条的起始点不在 90deg 上,那有没有方法能够实现起始点在 90deg 上,然而进度条还能够动起来呢?
答案必定是能够的。咱们将这个圆设想成高低两个局部,当进度小余 50% 的时候,高低两局部如下图所示
图一
图二
将 图一 盖到 图二 上的话就能够失去一个全红色的圆
.progress-radial {
position: relative;
width: 120px;
height: 120px;
border-radius: 50%;
background-image: linear-gradient(90deg, #C40006 50%, transparent 50%, transparent) , linear-gradient(90deg, #FECC1C 50%, #C40006 50%, #C40006);
line-height: normal;
display: flex;
align-items: center;
justify-content: center;
z-index: 1;
margin: 0 auto
}
而后咱们批改 图二 局部的 linear-gradient 的 angle 达到批改进度的成果,比方咱们试试将的 angle 改为 120deg,其实咱们能够想像成把下面 图二 转动了 30 度后失去以下成果
.progress-radial {
position: relative;
width: 120px;
height: 120px;
border-radius: 50%;
background-image: linear-gradient(90deg, #C40006 50%, transparent 50%, transparent) , linear-gradient(120deg, #FECC1C 50%, #C40006 50%, #C40006);
line-height: normal;
display: flex;
align-items: center;
justify-content: center;
z-index: 1;
margin: 0 auto
}
当大于 50% 进度的时候,图二 就转到了 270deg,就失去了之前的对半切的款式,这时候咱们将 linear-gradient 换成大于 50% 的款式,上下切图别离为
图一
图二
还是老办法,将 图一 盖到 图二 上能够失去一个 50% 进度的圆,而后咱们转动 图一
.progress-radial {
position: relative;
width: 120px;
height: 120px;
border-radius: 50%;
background-image: linear-gradient(-90deg, #FECC1C 50%, transparent 50%, transparent) , linear-gradient(270deg, #FECC1C 50%, #C40006 50%, #C40006);
line-height: normal;
display: flex;
align-items: center;
justify-content: center;
z-index: 1;
margin: 0 auto
}
而后咱们能够批改 图一 局部的 linear-gradient 的 angle 达到批改进度的成果,比方咱们试试将的 angle 改为 -60deg,能够想像把下面 图一 转动了 30 度后失去以下成果
这样咱们就实现了一个能够实现任意百分比的圆环,接下来咱们就间接依据数据联合上述两种状况实现动静计算进度的圆环把
<template>
<div id="app">
<div class="progress-radial" :style="point <= 50 ?'background-image: linear-gradient(90deg, #C40006 50%, transparent 50%, transparent), linear-gradient('+deg+'deg, #FECC1C 50%, #C40006 50%, #C40006);':'background-image: linear-gradient('+deg+'deg, #FECC1C 50%, transparent 50%, transparent), linear-gradient(270deg, #FECC1C 50%, #C40006 50%, #C40006)'">
<div class="progress-text"></div>
</div>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
deg: 0,
point: 0,
}
},
mounted() {
// 实现的数量,整体的数量
let {finishCount, totalCount} = {
finishCount: 1,
totalCount: 3,
};
// 实现数量的百分比,保留 2 位小数
let point = Math.floor((finishCount / totalCount) * 10000) / 100;
let deg = 0;
// 360 度,按百分比每分 3.6 度,小于 50% 以 90deg 为起始,大于 50% 以 -90deg 为起始
if (point <= 50) {deg = Math.round(90 + point * 3.6);
} else {deg = Math.round(-90 + (point - 50) * 3.6);
}
this.deg = deg
this.point = point
},
};
这时咱们就实现了批改 finishCount 批改进度的成果
transform-origin 实现头尾圆弧
头尾圆弧也就上下面咱们拆分的时候说的彩色圆,起始圆永远都位于最上方,所以只有定位好就能够,完结圆须要计算实在的进度,而后旋转到对于地位。
如何去转这个彩色的小圆,这里咱们是用了 transform-origin,也就是将这个彩色圆的旋转基点定到红色圆的圆心,而后用 rotate 就能够失去一个绕圆环边缘转的彩色小圆了,而后下面咱们计算失去的 deg 大于 50 和小于 50 的的起始基点不一样,所以咱们也须要对这个数值做一下解决。
最终代码和效果图如下
<template>
<div id="app">
<input v-model="finishCount" @change="draw" type="number" class="input" />
<div
class="progress-radial"
:style="
point <= 50
? 'background-image: linear-gradient(90deg, #C40006 50%, transparent 50%, transparent), linear-gradient(' +
deg +
'deg, #FECC1C 50%, #C40006 50%, #C40006);'
: 'background-image: linear-gradient(' +
deg +
'deg, #FECC1C 50%, transparent 50%, transparent), linear-gradient(270deg, #FECC1C 50%, #C40006 50%, #C40006)'
"
>
<div class="progress-text"></div>
<div
class="progress-radial-end"
:style="'transform: rotate('+(point <= 50 ? deg-90 : 270+deg)+'deg)'"
></div>
<div class="progress-radial-start"></div>
</div>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
finishCount: 1,
totalCount: 3,
deg: 0,
point: 0,
};
},
mounted() {this.draw();
},
methods: {draw() {
let point =
Math.floor((this.finishCount / this.totalCount) * 10000) / 100;
let deg = 0;
// 360 度,按百分比每分 3.6 度
if (point <= 50) {deg = Math.round(90 + point * 3.6);
} else {deg = Math.round(-90 + (point - 50) * 3.6);
}
this.deg = deg;
this.point = point;
},
},
};
</script>
<style>
.input {
margin: 30px auto;
display: block;
}
.progress-radial {
position: relative;
width: 120px;
height: 120px;
border-radius: 50%;
background-image: linear-gradient(
90deg,
#c40006 50%,
transparent 50%,
transparent
),
linear-gradient(90deg, #fecc1c 50%, #c40006 50%, #c40006);
line-height: normal;
display: flex;
align-items: center;
justify-content: center;
z-index: 1;
margin: 0 auto;
}
.progress-radial-end,
.progress-radial-start {
width: 16px;
height: 16px;
top: 0;
left: 52rpx;
border-radius: 50%;
background: #000;
position: absolute;
z-index: 999;
line-height: normal;
transform-origin: center 60px;
}
.progress-radial .progress-text {
width: 88px;
height: 88px;
background: #ed1937;
border-radius: 50%;
color: #fff;
font-size: 28px;
text-align: center;
line-height: 88px;
font-weight: bold;
}
</style>
参考地址文献和 demo 地址
- github
- 你真的了解 CSS 的 linear-gradient
**