注册
web

最近遇到的奇葩进度条

前言


本文将介绍几个我最近遇到的奇葩进度条,需求看似简单,但是我们可以用平常巧妙的属性来解决,再也不用复杂的html结构和颜色渐变算法。


“奇葩”的环形渐变进度条


需求描述:需要环形渐变的进度条让人快速理解进度实现程度,10-20%是青绿色,20%到30%是黄色.....


乍一看是不是很容易,但是我思来想去用了echarts的svg渲染,但是只要到了90%,一定会渐变到青绿色,从红色渐变到青绿色,做实让我心一凉。


image.png


思路一:径向渐变分割


网上思路很多,稍微复杂的比如分割区域做大量的颜色的径向渐变。原理是将rgba转为16进制计算颜色插值。这样我们通过计算step步长就可以根据细分做渐变了。但是好像无法很好满足我们的指定区域10%-20%是某种颜色,虽然可以但是也太麻烦了。


  function gradientColor(startRGB, endRGB, step) {
let startR = startRGB[0]
let startG = startRGB[1]
let startB = startRGB[2]
let endR = endRGB[0]
let endG = endRGB[1]
let endB = endRGB[2]
let sR = (endR - startR) / step // 总差值
let sG = (endG - startG) / step
let sB = (endB - startB) / step
var colorArr = []
for (var i = 0; i < step; i++) {
let color = 'rgb(' + parseInt((sR * i + startR)) + ',' + parseInt((sG * i + startG)) + ',' + parseInt((sB * i + startB)) + ')'
colorArr.push(color)
}
return colorArr
}

思路二:CSS结合svg


我们可以用css的background: conic-gradient


background: conic-gradient(#179067, #62e317, #d7f10f, #ffc403, #fcc202, #ff7327, #ff7327, #FF5800, #ff5900, #f64302, #ff0000, #ff0000);

image.png


看着好像不错,那么接下来只要我们做个遮罩,然后用svg的strokeDashoffset来形成我们的环状进度条就可以了。至于百分之几到百分之几我们可以将conic-gradient内部属性做个百分比的拆分就可以了


image.png


<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<style>
.circle {
width: 300px;
height: 300px;
background: conic-gradient(#179067, #62e317, #d7f10f, #ffc403, #fcc202, #ff7327, #ff7327, #FF5800, #ff5900, #f64302, #ff0000, #ff0000);
border-radius: 50%;
position: relative;
}

#progress-circle circle {
stroke-dasharray: 880;
stroke: #f2f2f2;
}

#progress-circle {
transform: rotate(-90deg);
}

.circle-mask {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 2;
width: 260px;
height: 260px;
background: #fff;
border-radius: 50%;
}
</style>

<body>
<div class="circle">
<svg id="progress-circle" width="300" height="300">
<circle r="140" cx="150" cy="150" stroke-width="21" fill="transparent" />
</svg>
<div class="circle-mask"></div>
</div>
</body>
<script>
const circle = document.querySelector('#progress-circle circle');
const radius = circle.r.baseVal.value;
const circumference = radius * 2 * Math.PI;
function setProgress(percent) {
const progress = circumference - (percent / 100) * circumference;
circle.style.strokeDashoffset = -progress;
}
let prog = 40
let val = 100 - prog
setProgress(val); //设置初始进度

</script>

</html>

这里简单讲下逻辑,我们通过计算环的周长,总长其实就是stroke-dasharray,通过strokeDashoffset来偏移我们的虚线线段,那么开始的就是我们的实线线段。其实就是一个蚂蚁线。让这个线长度等于我们的环长度,通过api让实线在开始的位置。


最终效果


image.png


"奇葩"的横向进度条


在我们平常需求用用组件库实现进度条很容易,但是我们看看这个需求的进度条的场景,文字要能被裁剪成黑白两色。


image.png


image.png


思路一: overflow:hidden


具体就不演示了,内部通过两个副本的文案,一套白色一套黑色,通过定位层级的不同,overflow:hidden来隐藏,缺点是相对繁琐的dom结构。


思路二: background-clip 裁剪


<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<style>
:root {
--d: 20%
}

.inverted {
padding: 0 8px;
display: flex;
justify-content: space-between;
background: linear-gradient(-90deg, #000 var(--d), #fff 0) no-repeat, linear-gradient(-90deg, #0000 var(--d), rgb(192, 23, 23) 0) no-repeat;
-webkit-background-clip: text, padding-box;
background-clip: text, padding-box;
color: #0000;
font-weight: bold;
cursor: pointer;
}

.box {
background: #ebebeb;
width: 300px;
border-radius: 24px;
overflow: hidden;
}
</style>

<body>
<div class="box">
<div class="inverted">
<div class="inverted-item">888w/12</div>
<div class="inverted-item">100%/10s</div>
</div>
</div>
</body>

<script>
function modifyProg(prog) {
let val = 100 - prog
document.documentElement.style.setProperty('--d', val + '%')
}
modifyProg(6)
</script>

</html>

这里我们主要用了background-clip的text和padding-box两个裁剪,一个裁剪文本,一个裁剪背景延伸至内边距padding外沿。不会绘制到边框处。在js中我们通过setProperty修改css变量即可。


最终效果


image.png


附录



  1. 卷出新高度,几百行的Canvas游戏秘籍 - 掘金 (juejin.cn)
  2. 为什么我的WebGL开发这么丝滑 🌊
  3. Echarts无法实现这个曲线图😭,那我手写一个 - 掘金 (juejin.cn)
  4. Redux已死,那就用更爽的Zustand - 掘金 (juejin.cn)<
    /a>

0 个评论

要回复文章请先登录注册