• 如何去掉css 渐变时的锯齿效果


    渐变(Gradient)在 CSS 中可谓是最为强大的一个属性之一。

    但是,经常有朋友在使用渐变的过程中会遇到渐变图形产生的锯齿问题。

    什么是渐变锯齿?

    那么,什么是渐变图形产生的锯齿呢?

    举一个简单的例子:

    <div>div>
    1. div {
    2. width: 500px;
    3. height: 100px;
    4. background: linear-gradient(37deg), #000 50%, #f00 50%, #f00 0);
    5. }

    效果如下:

     其实,锯齿感已经非常明显了,我们再放大了看,其内部其实是这样的:

     又或者是这样:

     有意思的是,锯齿现象在 DPR 为 1 的屏幕下特别明显,而在一些高清屏(dpr > 1)的屏幕下,感受不会那么明显。(DPR(Device Pixel Ratio)为设备像素比,DPR = 物理像素 / 设备独立像素,设备像素比描述的是未缩放状态下,物理像素和设备独立像素的初始比例关系。)

    那么为啥会产生锯齿感呢?

    传统网页的呈现是基于像素单位的,对于这种一种颜色直接过渡另外一种颜色状态的图片,容易导致可视质量下降(信息失真)。因而对于普通的渐变元素,像是上述写法,产生了锯齿,这是非常常见的在使用渐变过程中的一个棘手问题。

    简单的解决办法

    解决失真的问题有很多。这里最简单的方式就是不要直接过渡,保留一个极小的渐变过渡空间。

    上述的代码,我们可以简单改造一下:

     

    1. div {
    2. width: 500px;
    3. height: 100px;
    4. - background: linear-gradient(37deg), #000 50%, #f00 50%, #f00);
    5. + background: linear-gradient(37deg), #000 49.5%, #f00 50.5%, #f00);
    6. }

    仔细看其中的变化,我们从 50% --> 50% 的直接过渡,变化成预留了 1% 的渐变过渡空间,效果如下:

     

    可以看到,效果立马有了大幅提升!

    当然,如果不想修改原代码,也可以通过叠加一层伪元素实现,这里给出 3 种方式的对比图:

    1. <div>div>
    2. <div class="gradient">div>
    3. <div class="pesudo">div>
    1. :root {
    2. --deg: 37deg;
    3. --c1: #000;
    4. --c2: #f00;
    5. --line-width: 0.5px;
    6. }
    7. div {
    8. margin: auto;
    9. width: 500px;
    10. height: 100px;
    11. background: linear-gradient(
    12. var(--deg),
    13. var(--c1) 50%,
    14. var(--c2) 50%,
    15. var(--c2) 0
    16. );
    17. }
    18. // 方法一:
    19. .gradient {
    20. background: linear-gradient(
    21. var(--deg),
    22. var(--c1),
    23. var(--c1) calc(50% - var(--line-width)),
    24. var(--c2) calc(50% + var(--line-width)),
    25. var(--c2) 0
    26. );
    27. }
    28. // 方法二:
    29. .pesudo {
    30. position: relative;
    31. &::before {
    32. content: "";
    33. position: absolute;
    34. top: 0;
    35. left: 0;
    36. right: 0;
    37. bottom: 0;
    38. background: linear-gradient(
    39. var(--deg),
    40. transparent,
    41. transparent calc(50% - var(--line-width)),
    42. var(--c1) calc(50% - var(--line-width)),
    43. var(--c2) calc(50% + var(--line-width)),
    44. transparent calc(50% + var(--line-width)),
    45. transparent
    46. );
    47. }
    48. }

    通过伪元素叠加的意思是,在产生锯齿的地方,实现一个平滑过渡进行覆盖:

     效果如下:

     

    CodePen Demo -- 消除 Gradient 锯齿

    划重点!此方法适用于线性渐变、径向渐变、角向渐变,是最为简单的消除 CSS 锯齿的方式。

    更为高阶的锯齿消除法

    当然,也还有其他更为高阶的锯齿消除法。

    仿生狮子的这篇文章中 -- CSS 幻术 | 抗锯齿,还介绍了另外一种有意思的消除锯齿的方式。以下内容,部分摘录至该文章。

    我们可以建立一种边缘锯齿边缘->重建锯齿边缘的锯齿消除方法。

    我们需要做的,就是在锯齿处,叠加上另外一层内容,让锯齿感不那么强烈。称为像素偏移抗锯齿(Pixel-Offset Anti-Aliasing,POAA)。

    Implementing FXAA 这篇博客中,解释了 FXAA 具体是如何运作的。对于一个已经被找到的图形边缘,经过 FXAA 处理后会变成这样,见下两幅图:

     

     ------FXAA(Fast Approximate Anti-Aliasing),快速近似抗锯齿,它找到画面中所有图形的边缘并进行平滑处理。

    我们可以轻易找到找到渐变的边缘地方,就是那些渐变的颜色改变的地方。有了边缘信息后,接着就要重建边缘。重建边缘也许可以再拆分,分为以下几个步骤:

    • 需要通过某种方法得到透明度的点
    • 这些点需要能够组成线段
    • 线段完全吻合我们的 Gradient
    • 使线段覆盖在 Gradient 的上一层以应用我们的修改

    这就是大体思路,我们并没有参与浏览器的渲染,而是通过像 FXAA 一样的后处理的方法。在已渲染的图像上做文章。

    比如说,我们有这样一张图:

    1. .circle-con {
    2. $c1: #cd3f4f;
    3. $c2: #e6a964;
    4. position: relative;
    5. height: 300px;
    6. background-image: repeating-radial-gradient(
    7. circle at 0% 50%,
    8. $c1 0,
    9. $c2 50px
    10. );
    11. }

    边缘信息如下:

     

     我们要做的,就是在它的边缘处,利用渐变再生成一段渐变,通过准确叠加,消除渐变!原理图如下:

    原理可行,但是实操起来非常之复杂,计算量会比较大。感兴趣的可以拿这段代码尝试一下:

    1. .repeat-con {
    2. --c1: #cd3f4f;
    3. --c2: #e6a964;
    4. --c3: #5996cc;
    5. position: relative;
    6. height: 300px;
    7. background-image: repeating-linear-gradient(
    8. var(--deg),
    9. var(--c1),
    10. var(--c1) 10px,
    11. var(--c2) 10px,
    12. var(--c2) 40px,
    13. var(--c1) 40px,
    14. var(--c1) 50px,
    15. var(--c3) 50px,
    16. var(--c3) 80px
    17. );
    18. &.antialiasing {
    19. &:after {
    20. --offsetX: 0.4px;
    21. --offsetY: -0.1px;
    22. --dark-alpha: 0.3;
    23. --light-alpha: 0.6;
    24. --line-width: 0.6px;
    25. content: '';
    26. position: absolute;
    27. top: var(--offsetY);
    28. left: var(--offsetX);
    29. width: 100%;
    30. height: 100%;
    31. opacity: 0.5;
    32. background-image: repeating-linear-gradient(
    33. var(--deg),
    34. var(--c3),
    35. transparent calc(0px + var(--line-width)),
    36. transparent calc(10px - var(--line-width)),
    37. var(--c2) 10px,
    38. var(--c1) 10px,
    39. transparent calc(10px + var(--line-width)),
    40. transparent calc(40px - var(--line-width)),
    41. var(--c1) 40px,
    42. var(--c2) 40px,
    43. transparent calc(40px + var(--line-width)),
    44. transparent calc(50px - var(--line-width)),
    45. var(--c3) 50px,
    46. var(--c1) 50px,
    47. transparent calc(50px + var(--line-width)),
    48. transparent calc(80px - var(--line-width)),
    49. var(--c1) 80px
    50. );
    51. }
    52. }
    53. }

     

    简单总结一下,本文介绍了几种 CSS 中可行的消除渐变锯齿的方法。

    好了,本文到此结束,希望本文对你有所帮助

  • 相关阅读:
    ElasticSearch7.3学习(二十一)----Filter与Query对比、使用explain关键字分析语法
    批量录入表格中回车事件处理
    三七互娱,oppo,快手25届暑期实习内推
    Go语言笔记
    缓存与数据库双写一致性几种策略分析
    【MM32F5270开发板试用】六、如何用 星辰内核 + 国产RTOS 通过I2S播放 “星辰大海”
    【概率论与数理统计(研究生课程)】知识点总结1(概率论基础)
    《MySQL实战45讲》——学习笔记20 “幻读、全表扫描的加锁方式、间隙锁、next-key lock“
    [附源码]Python计算机毕业设计Django茂名特产销售商城网站
    国漫推荐07
  • 原文地址:https://blog.csdn.net/lwf3115841/article/details/127978109