一步一步教你使用css实现环形进度条

文摘   科技   2024-10-05 22:40   福建  

css画一个圆相信大家肯定都会

<!DOCTYPE html><html><head>    <title>css画一个圆</title>    <meta charset="utf-8" name="viewport" content="width=device-width;initial-scale=1.0" />    <style type="text/css">        .round{            width: 200px;            height: 200px;            background: pink;            border-radius: 50%;        }</style></head>
<body> <div class="round"></div></body></html>


没错,关键属性就是 border-radius ,这个属性能够做圆角处理。那我们要如何画圆环呢?是不是在上面的圆加个border,去掉背景色即可?操作一下,效果如下

    <style type="text/css">        .round{            width: 200px;            height: 200px;            background: transparent;            border: 10px solid pink;            border-radius: 50%;        }</style>

    以前有讲到如何制作三角形,原理就是利用border实现的。那这回看下圆的border会是怎样的。

<!DOCTYPE html><html>
<head> <title>css画一个圆</title> <meta charset="utf-8" name="viewport" content="width=device-width;initial-scale=1.0" /> <style type="text/css"> .demo-box { width: 860px; height: 300px; display: flex; align-items: center; justify-content: space-around; } .round{ width: 200px; height: 200px; background: transparent; border-radius: 50%; border: 10px solid transparent; } .round-1 { border-top: 10px solid pink; } .round-2 { border-right: 10px solid pink; } .round-3 { border-bottom: 10px solid pink; } .round-4 { border-left: 10px solid pink; }</style></head>
<body> <div class="demo-box"> <div class="round round-1"></div> <div class="round round-2"></div> <div class="round round-3"></div> <div class="round round-4"></div> </div></body></html>

css画三角形

沈小布,公众号:爆米花小布CSS实战

    很显然,如果使用两个相邻border凑一块就会是一个半圆。

但是这时候的半圆有点歪,所以我们使用 transform属性的rotate功能把他调正,调整45°后就如下所示

    现在我们已经会画一个圆环,也会画半圆环了。那如何做一个环形进度条呢?环形进度条,首先需要有一个环形背景,接下来就是环形里面的进度条。1、画一个环形背景

2、画两个矩形,矩形里面藏着半圆并设置溢出隐藏

3、通过两个半圆配合,完成进度条的百分比展示

大致图形解释如下

接下来代码实现一个这个框架

<!DOCTYPE html><html>
<head> <title>css环形进度条实现框架</title> <meta charset="utf-8" name="viewport" content="width=device-width;initial-scale=1.0" /> <style type="text/css"> .demo-box { width: 860px; height: 300px; display: flex; align-items: center; justify-content: space-around; } .round { position: relative; width: 200px; height: 200px; } .round .ring-bg { position: absolute; top: 0; left: 0; width: 100%; height: 100%; border-radius: 50%; background: transparent; border-radius: 50%; border: 10px solid pink; box-sizing: border-box; /*很重要*/ } .round .rec-left, .round .rec-right { position: absolute; top: 0; width: 50%; height: 100%; margin: 0; padding: 0; overflow: hidden; } .round .rec-left { left: 0; } .round .rec-right { right: 0; } .half-round { position: absolute; width: 200px; height: 200px; border: 10px solid transparent; border-radius: 50%; box-sizing: border-box; /*很重要*/        } .round .rec-left .half-round{ left: 0; border-top: 10px solid yellow; border-right: 10px solid yellow; transform: rotate(210deg); } .round .rec-right .half-round{ right: 0; border-bottom: 10px solid green; border-left: 10px solid green; transform: rotate(210deg); }</style></head>
<body> <div class="demo-box"> <div class="round"> <div class="ring-bg"></div> <div class="rec-left"> <div class="half-round"></div> </div> <div class="rec-right"> <div class="half-round"></div>            </div> </div> </div></body></html>

仔细观察会有如上图的问题,解决方式就是将定位各移动1px

.round .rec-left .half-round {  left: 1px;  border-top: 10px solid yellow;  border-right: 10px solid yellow;  transform: rotate(45deg);}.round .rec-right .half-round {  right: 1px;  border-bottom: 10px solid yellow;  border-left: 10px solid yellow;  transform: rotate(45deg);}

接下来通过配合,画一个 25%,50%,75%,80% 的进度条。


<!DOCTYPE html><html>
<head> <title>css环形进度条实现框架</title> <meta charset="utf-8" name="viewport" content="width=device-width;initial-scale=1.0" /> <style type="text/css"> .demo-box { width: 860px; height: 300px; display: flex; align-items: center; justify-content: space-around; } .round { position: relative; width: 200px; height: 200px; } .round .ring-bg { position: absolute; top: 0; left: 0; width: 100%; height: 100%; border-radius: 50%; background: transparent; border-radius: 50%; border: 10px solid pink; box-sizing: border-box; /*很重要*/ } .round .rec-left, .round .rec-right { position: absolute; top: 0; width: 50%; height: 100%; margin: 0; padding: 0; overflow: hidden; } .round .rec-left { left: 0; } .round .rec-right { right: 0; } .half-round { position: absolute; width: 200px; height: 200px; border: 10px solid transparent; border-radius: 50%; box-sizing: border-box; /*很重要*/ } .round .rec-left .half-round{            left1px; border-top: 10px solid yellow; border-right: 10px solid yellow; transform: rotate(210deg); } .round .rec-right .half-round{            right1px; border-bottom: 10px solid yellow; border-left: 10px solid yellow; transform: rotate(210deg); }
.round-1 .rec-left .half-round { transform: rotate(45deg); } .round-1 .rec-right .half-round { transform: rotate(135deg); }
.round-2 .rec-left .half-round { transform: rotate(45deg); } .round-2 .rec-right .half-round { transform: rotate(225deg); }
.round-3 .rec-left .half-round { transform: rotate(135deg); } .round-3 .rec-right .half-round { transform: rotate(225deg); }
.round-4 .rec-left .half-round { transform: rotate(153deg); } .round-4 .rec-right .half-round { transform: rotate(225deg); }</style></head>
<body> <div class="demo-box"> <div class="round round-1"> <div class="ring-bg"></div> <div class="rec-left"> <div class="half-round"></div> </div> <div class="rec-right"> <div class="half-round"></div> </div> </div>
<div class="round round-2"> <div class="ring-bg"></div> <div class="rec-left"> <div class="half-round"></div> </div> <div class="rec-right"> <div class="half-round"></div> </div> </div>
<div class="round round-3"> <div class="ring-bg"></div> <div class="rec-left"> <div class="half-round"></div> </div> <div class="rec-right"> <div class="half-round"></div> </div> </div>
<div class="round round-4"> <div class="ring-bg"></div> <div class="rec-left"> <div class="half-round"></div> </div> <div class="rec-right"> <div class="half-round"></div> </div> </div> </div></body></html>

现在应该对环形进度条是如何实现的 大概了解了吧。

接下来就是将环形进度条封装成vue组件。封装组件,首先就是确定可配置参数,我们大致可配置参数如下

1、环形图外直径大小    roundSize

2、环形图进度宽度       ringWidth

3、环形图进度百分比    percentage

4、环的背景色               ringBgColor

5、进度条的背景色        ringColor


加上由于,进度条是两个图案拼凑的,要利用过渡实现动画效果,就需要计算。具体不多说。封装后的代码如下

<template>  <div class="round" :style="{'width': roundSize + 'px', height: roundSize + 'px'}">    <div class="ring-bg" :style="{'width': '100%', 'height': '100%', 'border': `${ringWidth}px solid ${ringBgColor}`}"></div>    <div class="rec-left">      <div class="half-round" :style="{'transition': leftTransition,'width': `${roundSize}px`, 'height': `${roundSize}px`,'border-width': ringWidth + 'px','transform': 'rotate('+ leftRotateDeg +'deg)','border-top-color': ringColor, 'border-right-color': ringColor}"></div>    </div>    <div class="rec-right">      <div class="half-round" :style="{'transition': rightTransition,'width': `${roundSize}px`, 'height': `${roundSize}px`,'border-width': ringWidth + 'px','transform': 'rotate('+ rightRotateDeg +'deg)','border-bottom-color': ringColor, 'border-left-color': ringColor}"></div>    </div>  </div></template>
<script>export default { props: { //百分比 percentage: { type: Number, default: 0 }, //环的背景颜色 ringBgColor: { type: String, default: "#002989" }, //占用环的颜色 ringColor: { type: String, default: "#4188FF" }, //圆的大小 roundSize: { type: Number, default: 100 }, //环的大小 ringWidth: { type: Number, default: 10 } }, data() { return { leftRotateDeg: 45, rightRotateDeg: 45, leftTransition: "none", //旋转过渡 rightTransition: "none" //旋转过渡 } }, watch: { percentage: { handler: function(newVal, oldVal) { if (newVal <= 50) { //小于50 const rotateDeg = newVal * 3.6
if (oldVal > 50) { //如果之前的进度大于 50% 说明是 跨 div 旋转 大角度 变 小角度 const instance = oldVal - newVal //计算跨度百分之几 const perSecond = instance/0.36 //每秒旋转百分之几 const leftInstanceTime = Math.floor((oldVal - 50) / perSecond * 1000) / 1000 //左边部分跑到 50一半的时间 this.leftTransition = `all ${leftInstanceTime}s` this.leftRotateDeg = 45 setTimeout(() => { this.rightTransition = `all ${0.36 - leftInstanceTime}s` this.rightRotateDeg = rotateDeg + 45 }, leftInstanceTime * 1000 - 50) //-50毫秒 减少 顿戳感 执行这个操作的时间 } else { this.leftTransition = "none" this.rightTransition = "all 0.36s" this.leftRotateDeg = 45 this.rightRotateDeg = rotateDeg + 45 } } else {
if (oldVal <= 50) { //如果之前的进度小雨等于 50% 说明是 跨 div 旋转 小变大 const instance = newVal - oldVal const perSecond = instance/0.36 //每秒旋转百分之几 const rightInstanceTime = Math.floor((50 - oldVal) / perSecond * 1000) / 1000 //左边部分跑到 50一半的时间 this.rightTransition = `all ${rightInstanceTime}s` this.rightRotateDeg = 45 + 180
setTimeout(() => { this.rightTransition = `all ${0.36 - rightInstanceTime}s` this.leftRotateDeg = (newVal - 50) * 3.6 + 45 }, rightInstanceTime * 1000 - 50) //-50毫秒 减少 顿戳感 执行这个操作的时间 } else { this.rightTransition = "none" this.leftTransition = "all 0.36s" this.rightRotateDeg = 45 + 180 this.leftRotateDeg = (newVal - 50) * 3.6 + 45 }
} }, deep: true, immediate: true } }}</script>
<style scoped>.round { position: relative; width: 200px; height: 200px;}.round .ring-bg { position: absolute; top: 0; left: 0; width: 100%; height: 100%; border-radius: 50%; background: transparent; border-radius: 50%; border: 10px solid pink; box-sizing: border-box; /*很重要*/}.round .rec-left,.round .rec-right { position: absolute; top: 0; width: 50%; height: 100%; margin: 0; padding: 0; overflow: hidden;}.round .rec-left { left: 0;}.round .rec-right { right: 0;}.half-round { position: absolute; width: 200px; height: 200px; border: 10px solid transparent; border-radius: 50%; box-sizing: border-box; /*很重要*/}.round .rec-left .half-round { left: 1px; border-top: 10px solid yellow; border-right: 10px solid yellow; transform: rotate(45deg);}.round .rec-right .half-round { right: 1px; border-bottom: 10px solid yellow; border-left: 10px solid yellow; transform: rotate(45deg);}</style>


就讲到这。

爆米花小布
总结前端开发经验,分享前端开发技术,提升前端开发效率,让开发变得更简单,更快乐。 生活不止于工作,同时也会分享其他相关文章,陶冶情操,扩展知识面。
 最新文章