首页 > 解决方案 > 带有重复背景的 Chrome 中的 SVG 背景图像模糊

问题描述

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

Chrome 中部分 SVG 的屏幕截图:

铬合金

Firefox 中部分 SVG 的屏幕截图:

火狐

这仅在使用“background-repeat: true”和“background-size: contains” 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 进行了相当多的编辑,并尝试了以下操作:

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

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

在这里的任何帮助将不胜感激,我正在为此烦恼,并且在咨询了 CodeMentor.io 上的几位开发人员后无法解决该问题。

标签: htmlcssgoogle-chromesvgvector-graphics

解决方案


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

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

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

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

最后,<rect>定义了 width = height = 100% 的 a 并用模式填充,没有属性的根<svg>元素viewBox同样设置为 width = height = 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- 它适用于模式元素,无论如何。


推荐阅读