当前位置: 首页 > Web前端 > JavaScript

CSS渐变走样消失技巧

时间:2023-03-26 23:48:37 JavaScript

在CSS中,渐变(Gradient)是最强大的属性之一。但是有些同学在使用渐变的过程中,经常会遇到渐变图形走样的问题。什么是渐变混叠?那么,渐变图形产生的锯齿是什么?一个简单的演示:

div{width:500px;高度:100px;background:linear-gradient(37deg),#00050%,#f0050%,#f000);}效果如下:其实走样已经很明显了。当我们放大的时候,里面其实是这样的:orthis:有意思的是在DPR为1的屏幕上锯齿特别明显,而在一些高清屏幕(dpr>1)的屏幕下,感觉不会那么明显。DPR(DevicePixelRatio)即设备像素比,DPR=物理像素/设备独立像素,设备像素比描述了未缩放状态下物理像素与设备独立像素之间的初始比例关系。那么为什么会有锯齿感呢?传统网页的渲染是以像素为单位的。对于这样一种颜色直接过渡到另一种颜色状态的图片,很容易造成视觉质量下降(信息失真)。所以,对于普通的渐变元素,比如上述的写法,就会产生锯齿,这是渐变使用过程中非常普遍的棘手问题。失真问题有许多简单的解决方案。这里最简单的方法不是直接过渡,而是预留一个很小的梯度过渡空间。我们可以简单的修改上面的代码:div{width:500px;高度:100px;-背景:线性渐变(37deg),#00050%,#f0050%,#f00);+background:linear-gradient(37deg),#00049.5%,#f0050.5%,#f00);}仔细看变化,我们从直接过渡50%-->50%到1%预留渐变过渡空间,效果如下:可以看到,效果立刻有了很大的提升!当然,如果你不想修改原来的代码,也可以通过叠加一层伪元素来实现。下面是三张对比图:
:root{--deg:37deg;--c1:#000;--c2:#f00;--line-width:0.5px;}div{margin:auto;宽度:500px;高度:100px;background:linear-gradient(var(--deg),var(--c1)50%,var(--c2)50%,var(--c2)0);}//方法一:.gradient{background:线性梯度(var(--deg),var(--c1),var(--c1)calc(50%-var(--line-width)),var(--c2)calc(50%+var(--line-width)),var(--c2)0);}//方法二:.pesudo{position:relative;&::前{内容:””;位置:绝对;顶部:0;左:0;右:0;底部:0;背景:线性渐变(var(--deg),透明,透明calc(50%-var(--line-width)),var(--c1)calc(50%-var(--line-width)),var(--c2)calc(50%+var(--line-width)),transparentcalc(50%+var(--line-width)),transparent);}}通过伪元素叠加,就是实现平滑过渡,覆盖出现锯齿的地方:效果如下:CodePenDemo--EliminateGradientaliasingFocus!这种方法适用于线性渐变、径向渐变和角度渐变。这是消除CSS别名的最简单方法。更高级的抗锯齿方法当然,还有其他更高级的抗锯齿方法。BionicLion这篇文章中——CSSIllusion|抗锯齿,介绍另一种有趣的抗锯齿方式。以下内容部分摘自本文。我们可以构建边缘锯齿边缘的抗锯齿方法->重建锯齿边缘。我们需要做的是在锯齿上再叠加一层内容,让锯齿不那么强烈。它称为像素偏移抗锯齿(POAA)。在实施FXAA博客中,解释了FXAA的工作原理。对于一个已经找到的图形边缘,经过FXAA处理后会变成这样,看下面两张图:FXAA(FastApproximateAnti-Aliasing),快速近似抗锯齿,它找到屏幕中所有图形的边缘并执行平滑。我们可以很容易地找到渐变的边缘,渐变的颜色在这里发生变化。有了边缘信息后,接下来必须重建边缘。重建的边缘可能会再次分裂,分为以下步骤:需要以某种方式透明的点这些点需要能够形成线段线段完全匹配我们的梯度使线段覆盖上部Gradient的layer来应用我们的修改这是大体的思路,我们不参与浏览器的渲染,而是通过像FXAA这样的后处理方式。处理渲染图像。例如,我们有这样一张图片:.circle-con{$c1:#cd3f4f;$c2:#e6a964;位置:相对;高度:300px;background-image:repeating-radial-gradient(circleat0%50%,$c10,$c250px);}边缘信息如下:我们需要做的是利用梯度在它的位置重新生成一个梯度边缘,通过精确叠加消除梯度!示意图如下:原理是可行的,但实际操作起来很复杂,计算量会比较大。如果你有兴趣,你可以试试这个代码:.repeat-con{--c1:#cd3f4f;--c2:#e6a964;--c3:#5996cc;位置:相对;高度:300px;背景图像:重复线性渐变(var(--deg),var(--c1),var(--c1)10px,var(--c2)10px,var(--c2)40px,var(--c1)40px,var(--c1)50px,var(--c3)50px,var(--c3)80px);&.antialiasing{&:after{--offsetX:0.4px;--offsetY:-0.1px;--暗阿尔法:0.3;--light-alpha:0.6;--线宽:0.6px;内容:'';位置:绝对;顶部:var(--offsetY);左:var(--offsetX);宽度:100%;高度:100%;不透明度:0.5;背景图像:重复线性渐变(var(--deg),var(--c3),透明计算(0px+var(--line-width)),透明calc(10px-var(--line-width)),var(--c2)10px,var(--c1)10px,transparentcalc(10px+var(--line-width)),transparentcalc(40px-var(--line-width)),var(--c1)40px,var(--c2)40px,transparentcalc(40px+var(--line-width)),transparentcalc(50px-var(--line-width)),var(--c3)50px,var(--c1)50px,transparentcalc(50px+var(--line-width)),transparentcalc(80px-var(--line-width)),变量(--c1)80px);}}}最后,一个简短的总结。本文介绍几种消除CSS中渐变走样的可行方法。好了,本文到此结束。希望这篇文章能帮到你:)更多精彩的CSS技术文章汇总在我的Github——iCSS,持续更新中。欢迎点个星订阅收藏。有什么问题或者建议可以多交流。原创文章文笔有限,知识匮乏。如果文章中有任何不准确的地方,请告诉我。