CSS 实现环(圆)形进度条(渐变效果)

8,722 阅读3分钟
  • 上个月写了一篇关于环(圆)形进度条的文章: 原文地址
  • 有同学在文章下留言问: 渐变效果怎么实现
    • 如果你有任何问题都可以给我留言, 我会尽我所能回答你.
    • 也希望你能指出我的错误和不足, 我会及时改正.
  • 回归正题, 那我们就在原来的基础上实现渐变效果.

先看效果图

今天还是老规矩, 先看效果图, 如果满足你的需求再继续往下看 如果示例代码没有看懂, 或者你想了解一下实现过程, 那你可以继续往下看

原来的代码

  • 因为前面有文章讲了基本的实现过程, 我们在原来(原文地址)的基础上继续说, 我们直接贴一下原来的核心代码
<div className="g-progress-wrap">
    <div className="g-progress"></div>
    <div className="g-circle">
        <span className="g-circle-before"><i/></span>
        <span className="g-circle-after"><i/></span>
    </div>
    <div className="g-text"> 20% </div>
</div>
$progressSize: 100px; // 进度条的尺寸(width, height)
$progressGap: 6px; // 圆环的宽度
$activeColor: #1677ff;
$notActiveColor: #eeeeee;

.g-progress-wrap {
    display: inline-block;
    position: relative;

    .g-progress {
        width: $progressSize;
        height: $progressSize;
        border-radius: 50%;
        background: conic-gradient(
            $activeColor 0, $activeColor 25%,
            $notActiveColor 25%, $notActiveColor 1
        ); // 25% 表示进度是 25%;

        $maskSize: ($progressSize / 2) - $progressGap;
        mask: radial-gradient(transparent, transparent $maskSize,#000 $maskSize + 0.5px,#000 100%);
        -webkit-mask: radial-gradient(transparent, transparent $maskSize,#000 $maskSize + 0.5px,#000 100%);
    }

    .g-circle {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        transform: rotate(-90deg);

        &>span {
            position: absolute;
            top: ($progressSize - $progressGap) / 2;
            left: ($progressSize) / 2;
            width: 50%;
            transform-origin: left;

            &>i {
                width: $progressGap;
                height: $progressGap;
                float: right;
                border-radius: 50%;
                background: #1677ff;
                z-index: 1;
            }
        }

        & .g-circle-after {
            transform: rotate(0deg); // 设置尾部圆点的选择角度, 当 25% 时, 25% * 360 = 90deg 
        }
    }

    .g-text {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        font-size: 16px;
        color: #666666;
    }
}
  • 从原来的代码可以看出来, 当我们要设置一个进度为 50% 时, 我们需要修改 15~1650 行的代码
  • 并且一个是用了百分百设置, 一个用了角度的设置, 下一面我们先对这块做个简单的优化

通过使用变量, 设置环形的角度

  • 我们使用了 css 的 var() 函数, 设置一个角度的变量, 这样我们只需要改变这个变量, 所有依赖这个变量的地方就都会更新, 从而达到只修改一个地方就可以更新进度的效果
  • --rotate-deg: 200deg; 这样我们就设置了一个变量并且值为 200deg;
  • 我们怎么使用呢? 我们分别修改 14~1750 行的代码, 结果如下:
background: conic-gradient(
    $activeColor 0, $activeColor var(--rotate-deg, 0deg),
    $notActiveColor var(--rotate-deg, 0deg), $notActiveColor 360deg
);
transform: rotate(var(--rotate-deg, 0deg));

实现渐变

  • 其实 conic-gradient 本身就是用来实现渐变效果的;
  • 删掉 $activeColor 变量, 新增两个变量 $activeStartColor $activeEndColor 即开始的颜色和结束的颜色
  • 改动的位置也和上面的差不多, 来看一下 14~17 行的改动(其实只修改了 15 行)
$activeStartColor: #7b45f3;
$activeEndColor: #87dbff;
background: conic-gradient(
    $activeStartColor 0, $activeEndColor var(--rotate-deg, 0deg),
    $notActiveColor var(--rotate-deg, 0deg), $notActiveColor 360deg
);
  • 设置开始的小圆点为 $activeStartColor, 设置结束的小圆点为 $activenEndColor
.g-circle-before > i {
    background: $activeStartColor;
}
.g-circle-after > i {
    background: $activeEndColor;
}

实现另一种无限加载方式

image.png

image.png

  • 这些图是从百度搜索到的, 从图上可以看出来, 当 0 < a < 1 时, 当 x 属于 [0, ∞]: 值的区间为 [1, 0]
  • 并且当 a(0 < a < 1) 越大时, 值趋于 0 的速度越慢
  • 我可以得到这样一个表达式: f(x) = 1 - (a ** x) (a ** x 表示 a 的 x 次方 ) image.png
  • 上图是我在这个网站a = 0.6 生成的一个函数图像
  • 我们要的进度条也是从 0%(0) 开始, 到 100%(1), 是不是正好符合我们的要求呢, 那让我们写成代码看看
function VirtualProgress2({constant = 0.9}) {
    const [progress, setProgress] = React.useState(0);
    React.useEffect(() => {
        let count = 0;

        const timer = window.setInterval(() => {
            let progress = (1 - (constant ** count++)) * 100;
            if (progress > 94) {
                setProgress(100);
                window.clearInterval(timer);
                return;
            }

            setProgress(Math.floor(progress));
        }, 500);
    }, [])

    return <Progress progress={progress} />;
}

相关文档

CSS 绘制任意角度扇形--遮盖/旋转
CSS 绘制任意角度扇形--clip-path
CSS 绘制任意角度扇形-渐变图像(css)
CSS 绘制任意角度扇形-渐变图像-示例
CSS 绘制任意角度扇形-SVG
CSS 绘制任意角度扇形-总结
环(圆)形进度条
css 实现关闭(close) Icon 使用 SVG 实现圆(环)形 进度条