【问题标题】:SVG background-image blurriness in Chrome with repeating background带有重复背景的 Chrome 中的 SVG 背景图像模糊
【发布时间】:2020-12-13 06:24:10
【问题描述】:

在 Chrome 和其他基于 Blink/webkit 的浏览器中,SVG 背景出现模糊:

Chrome 中部分 SVG 的屏幕截图:

Firefox 中部分 SVG 的屏幕截图:

只有在显示带有“background-repeat:true”和“background-size:contain”CSS 值的 SVG 时才会发生这种情况。我们希望尽可能多地重复 SVG 背景高度,因为页面高度是动态的,并且拉伸矢量图像看起来很糟糕。

SVG 在下面示例页面的 CSS 中内联显示,但是当我链接到外部 SVG 图像时,问题以同样的方式发生。

这是一个显示此行为的测试页面: https://august-13-2020-test-canvas.bubbleapps.io/version-test/pagemaker-test-original-2 (使用“用户名”和“密码”登录,我们需要把这个认证放在这里)。

带有正确显示(清晰/平滑边缘)SVG 的测试页面在这里:https://august-13-2020-test-canvas.bubbleapps.io/version-test/pagemaker-test-online-1

边缘清晰/平滑的版本以完全相同的方式显示 - 唯一的区别是 SVG 的内容。

这里是模糊页面的背景 SVG 链接:https://dd7tel2830j4w.cloudfront.net/d44/f1588704991659x396570736162959360/background.svg

我从这个页面测试的所有 SVG 都有清晰的边缘:https://www.svgbackgrounds.com/#flat-mountains(右下角是上面链接中使用的那个)

在尝试解决此问题或在 SVG 代码中确定其原因的过程中,我对 SVG 进行了相当多的编辑,并尝试了以下操作:

  • 将所有 SVG 点值(路径的 d 属性)转换为整数
  • 将“PreserveAspectRatio”添加到 SVG 的开始标记
  • 从 SVG 的开头声明中删除高度和宽度
  • 从 SVG 中移除“线性渐变”并将其替换为静态颜色
  • 将 SVG 形状的大小加倍以查看模糊度是否会随着初始宽度和高度的增大而降低
  • 将“crispEdges”属性添加到 SVG 路径
  • 优化 SVG(使用 SVGomg)

此外,我尝试稍微更改 CSS,但无法正常工作。

我对解决方法的一些想法如下:

  • 使用多个背景图像重复显示 SVG(在背景中显示 5-10 次,模仿 background-repeat:repeat-y 效果,但包含多个背景图像)
  • 使用JS在页面上绘制内联SVG(这个bug不会发生的地方),创建一个与我们组动态高度完全相同的HTML(可以随时更改而不触发JS事件)并以某种方式在该组内重复 SVG。
  • 请设计师提供不同的 SVG 背景,并希望不再出现模糊问题。

这里的任何帮助都将不胜感激,我正在努力解决这个问题,在咨询了 CodeMentor.io 上的几位开发人员后,我无法解决这个问题。

【问题讨论】:

    标签: html css google-chrome svg vector-graphics


    【解决方案1】:

    Blink 似乎应用了错误的算法,首先以错误的大小渲染 SVG,然后缩放生成的光栅图像。这很难解决,因为涉及到两种缩放机制,SVG viewBox 和 CSS background-size

    我只能提供部分解决方案,在 Chrome 和 Edge(两种引擎)中工作,但在 Firefox 中失败。

    它将缩放和重复的责任从 CSS background 属性转移到带有 <pattern> 元素的 SVG 本身。 SVG 图像的完整内容在此元素内移动,包括将 viewBox 属性设置为相同的值。

    然后,模式重复的宽度和高度值设置为width="100vw" height="504vw"。这会填充视口宽度并保持高度的纵横比。 (Firefox 似乎无法在这种情况下解释 vw 单位)。

    最后,定义了一个宽度 = 高度 = 100% 的 <rect> 并用该模式填充,而没有 viewBox 属性的根 <svg> 元素同样设置为宽度 = 高度 = 100%。

    <svg width="100%" height="100%" fill="none" xmlns="http://www.w3.org/2000/svg">
      <pattern id="pt" width="100vw" height="504vw" x="0" y="0" viewBox="0 0 1440 7258" patternUnits="userSpaceOnUse" preserveAspectRatio="xMinYMin meet">
        <rect width="1440" height="7258" fill="white"/>
        <path d="M-137 1749L1546 1994.95V2870L-137 2624.64V1749Z" fill="#F7F8FF"/>
        <path d="M-137 3776L1546 4021.95V4897L-137 4651.64V3776Z" fill="url(#paint0_linear)"/>
        <path d="M-137 3969L1546 4214.95V4900L-137 4654.64V3969Z" fill="url(#paint1_linear)"/>
        <path d="M1319 2764L1545 2796.96V2870L1319 2837.12V2764Z" fill="#264CE9"/>
        <path d="M-53 2645L96 2666.68V2744L-53 2722.37V2645Z" fill="#FBE89F"/>
        <path d="M-29 2571L307 2620.13V2699L-29 2649.99V2571Z" fill="#54A5F2"/>
        <path d="M1209 2820L1545 2869.13V2948L1209 2898.99V2820Z" fill="#6AD2F6"/>
        <path d="M-147 4649L307 4715.42V4891L-147 4824.74V4649Z" fill="#6AD2F6"/>
        <path d="M-137 -233L1546 12.9461V688L-137 442.638V-233Z" fill="url(#paint2_linear)"/>
        <g style="mix-blend-mode:multiply">
          <path d="M987 -144L2119 21.4151V388L987 222.978V-144Z" fill="#6AD2F6"/>
        </g>
        <path d="M-137 27L1546 272.946V948L-137 702.638V27Z" fill="url(#paint3_linear)"/>
        <path d="M-258 455L490 564.509V794L-258 684.751V455Z" fill="url(#paint4_linear)"/>
      </pattern>
    
      <linearGradient id="paint0_linear" x1="43.9999" y1="3807" x2="458.5" y2="4665" gradientUnits="userSpaceOnUse">
        <stop stop-color="#264CE9" stop-opacity="0.06"/>
        <stop offset="1" stop-color="#F7F8FF" stop-opacity="0.26"/>
      </linearGradient>
      <linearGradient id="paint1_linear" x1="43.9999" y1="4000" x2="1229" y2="5099" gradientUnits="userSpaceOnUse">
        <stop stop-color="#264CE9" stop-opacity="0.06"/>
        <stop offset="1" stop-color="#F7F8FF" stop-opacity="0"/>
      </linearGradient>
      <linearGradient id="paint2_linear" x1="194" y1="87.4999" x2="1671" y2="300" gradientUnits="userSpaceOnUse">
        <stop offset="0.270833" stop-color="#264CE9"/>
        <stop offset="1" stop-color="#6AD2F6"/>
      </linearGradient>
      <linearGradient id="paint3_linear" x1="194" y1="347.5" x2="1671" y2="560" gradientUnits="userSpaceOnUse">
        <stop stop-color="#264CE9"/>
        <stop offset="1" stop-color="#6AD2F6"/>
      </linearGradient>
      <linearGradient id="paint4_linear" x1="-108" y1="550.5" x2="490" y2="638" gradientUnits="userSpaceOnUse">
        <stop stop-color="#264CE9" stop-opacity="0.43"/>
        <stop offset="1" stop-color="#264CE9"/>
      </linearGradient>
    
      <rect width="100%" height="100%" fill="url(#pt)" />
    </svg>
    

    我稍微简化了标记,但这些更改都是装饰性的,包括删除了 clipPath - 无论如何,它适用于模式元素。

    【讨论】:

    • 非常感谢这里的帮助,ccprog。这听起来很有希望,渲染问题(以一种尺寸渲染 SVG 并像 PNG/JPEG 一样重新缩放)也是我所想象的。在这个页面上,那个 SVG 在 Chrome 上仍然很模糊(Windows 的最新稳定版本,84.0.4147.135)。我尝试将 background-repeat 设置为“no-repeat”,并将 background-size 设置为多个不同的值 - 在此页面中,它设置为 100% 100%。 august-13-2020-test-canvas.bubbleapps.io/version-test/…
    【解决方案2】:

    从未找到此问题的解决方案(或至少未能实施 ccprog 提供的解决方案)。

    我们选择将 SVG 文件编辑得更长。我们的 SVG 文件被用作具有动态长度的网页的背景,理论上它们的高度没有限制。

    通过将大约 8000 像素高的 SVG 重复 5 次,它会覆盖到网页的高度达到 40000 像素,这对于我们的用例来说应该没问题。我使用 inkscape 进入并复制每个 SVG 的内容,然后多次复制该内容,使最终的 SVG 比原始的高 5 倍。

    【讨论】:

      猜你喜欢
      • 2017-10-24
      • 1970-01-01
      • 2018-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-13
      • 2016-12-22
      • 2014-07-13
      相关资源
      最近更新 更多