3种纯CSS实现中间镂空的12色彩虹渐变圆环方法 - 牛奶泡芙

时间:2024-02-25 15:45:41

3种纯CSS实现中间镂空的12色彩虹渐变圆环方法

彩条圆环倒计时效果,大概长下面这样子:

彩条圆环

原理是使用两个渐变半圆无缝叠加在一起。

使用SVG实现的优点是兼容性非常好,IE9浏览器也是支持的。

不足在于学习成本比较高,相关的SVG代码要想完整的手写出来,还是需要不少积累的。

于是我就琢磨有没有更简单的方法实现类似的多彩圆环渐变效果,最好纯CSS就能搞定。

绞尽脑汁想出了下面三种实现方法,为了尽可能验证方法的可行性,我把圆环的渐变颜色从3色变成了12色。

下面依次介绍这三种方法。

二、借助CSS3 conic-gradient锥形渐变实现12色渐变圆环

环形带上的渐变效果,本质上就是一种锥形渐变,因此,我们直接使用,CSS3 conic-gradient锥形渐变实现应该是最简单最直接的方法。

如下HTML和CSS:

<div class="circle"></div>
.circle {
    width: 300px; height: 300px;
    background: conic-gradient(#9ED110, #50B517, #179067, #476EAF, #9f49ac, #CC42A2, #FF3BA7, #FF5800, #FF8100, #FEAC00, #FFCC00, #EDE604);
    border-radius: 50%;
}

此时的效果如下图所示:
12色锥形渐变效果截图

但是我们需要的效果不是圆饼,而是一个圆环,也就是中间区域需要镂空。

有一种比较巧妙的做法,就是搞一个跟背景色一样半径小一点的圆形饼覆盖在中间,这样视觉看上去就是一个圆环,这也是不一个不错的方法。但是如果我们的背景是一个复杂的图案,此时,这种方法恐怕就不能适用。

你怎么需要找到一种中间区域是真实镂空的方法,怎么处理呢?

我们可以借助CSS3遮罩mask属性来实现,CSS3 mask遮罩除了支持PNG图片,SVG图形,其还支持CSS3渐变背景图。于是,我们只需要使用CSS3径向渐变radial-gradient语法生成一个中间透明,边缘实色的圆环即可。

于是有(这里省略了mask属性的webkit私有前缀):

.circle {
    width: 300px; height: 300px;
    background: conic-gradient(#9ED110, #50B517, #179067, #476EAF, #9f49ac, #CC42A2, #FF3BA7, #FF5800, #FF8100, #FEAC00, #FFCC00, #EDE604);
    border-radius: 50%;
    mask: radial-gradient(transparent 110px, #000 110px);
}

于是我们的12色圆环渐变效果就实现了:
锥形渐变下的12色彩虹圆环效果

再配合JS设置clip-path剪裁我们的图形,就可以实现12色的彩虹圆环倒计时效果了。

眼见为实,您可以狠狠地点击这里:借助CSS3 mask遮罩和conic-gradient实现的多彩圆环demo

优点和不足
这个方法看上去很简单,很完美,但是却有个致命的缺陷,那就是兼容性问题!

CSS3锥形渐变conic-gradient目前仅Chrome浏览器才支持,并且Chrome浏览器还是需要开启实验功能选项才能支持!

锥形渐变糟糕的兼容性问题

因此当下此方法基本上没有在实际项目中应用的可能性,需要看看有没有什么其他解决方案?

三、借助CSS3 linear-gradient线性渐变近似实现12色渐变圆环

虽然锥形渐变浏览器的兼容性不怎么样,但是线性渐变它兼容性很好啊,是不是可以李代桃僵呢?

和一开始SVG圆环原理类似:
把我们的圆环分成左半部分和右半部分,左半部分是一套线性渐变,右半部分是另外一套线性渐变,然后最底部的线性渐变颜色是一样的,理论上在视觉上看起来就能够形成一个完美的环。

如下HTML和CSS代码:

<div class="circle">
    <div class="circle-left"></div>
    <div class="circle-right"></div>
</div>
.circle {
    width: 300px; height: 300px;
    border-radius: 50%;
    mask: radial-gradient(transparent 110px, #000 110px);
    overflow: hidden;
}
.circle-left {
    width: 50%; height: 100%;
    background: linear-gradient(to bottom, #EDE604, #FFCC00, #FEAC00, #FF8100, #FF5800, #FF3BA7, #CC42A2);
    float: left;
}
.circle-right {
    width: 50%; height: 100%;
    float: right;
    background: linear-gradient(to bottom, #9ED110, #50B517, #179067, #476EAF, #9f49ac, #CC42A2);
}

然而最后的效果却是下面这样:

两个渐变无缝连接失败示意

咦,奇怪,同样的实现原理,为什么一开始的SVG实现没有这样的现象呢?

实际上,SVG的实现底部的连接也是不完美的,但是由于我们上面的这个圆环渐变颜色比较少,同时颜色比较接近,因此不仔细看,根本看不出来,连接有问题的。

但是这里的12色渐变就不一样了,渐变颜色跨度明显区分大,因此很明显看出来接缝有问题,那有没有什么办法可以解决这个问题呢?

有!我想的办法是,就是在下面接缝不完美的地方打一个小补丁,就像是我国桥梁建造接缝处重新浇筑一样,于是HTML变成下面这样,增加一个.circle-bottom

<div class="circle">
    <div class="circle-left"></div>
    <div class="circle-right"></div>
    <div class="circle-bottom"></div>
</div>

对应的CSS如下:

.circle-bottom {
    position: absolute; 
    height: 40px; width: 30px;
    bottom: 3px; left: 0; right: 0;
    margin: auto;
    /* 下面两个声明是补丁关键 */
    background: linear-gradient(to right, #DB3FA3, #C443A3);
    filter: blur(5px);
}

也就是接缝处搞一个小小的水平渐变,同时适当高斯模糊,淡化边界。然后肉眼所见的效果就变成下面这样,几乎看不出任何异常:
接缝处打完补丁之后的圆环效果

接下来就简单了,同样地,JS设置圆环clip-path动态剪裁,实现我们想要的倒计时效果。