如何防止高像素比率设备(视网膜)上的半像素SVG偏移?

Fin*_*sse 5 html css svg retina

我有一个带有SVG图片的HTML网页。当我使用iOS Safari或Android浏览器访问网页时,出现网页问题(白线过多,如下图所示)。屏幕截图分辨率为2倍,锯边为SVG图像。

期望与结果

我发现,当SVG图片的页面Y位置不是CSS像素的整数(px),即½ 时,就会发生这种情况px。浏览器px在渲染网页时将SVG图片位置四舍五入为整数,而不对其他元素位置四舍五入。这就是为什么px出现½ 行的原因。

说明

您可以使用下面的代码段(或此CodePen)重现该问题。您应该在具有高像素密度的设备上运行该代码段。如果您进入自适应设计模式并选择iPhone或iPad,也可以在桌面Safari中重现它。

.common-bg {
  background: #222;
  fill: #222;
}
.block {
  max-width: 300px;
  margin: 20px auto;
}
.block_content {
  height: 50.5px;
}
.block_edge {
  display: block;
}
Run Code Online (Sandbox Code Playgroud)
<div class="block">
  <div class="block_content common-bg"></div>
  <svg
    class="block_edge"
    width="100%"
    height="10"
    xmlns="http://www.w3.org/2000/svg"
    version="1.1"
    xmlns:xlink="http://www.w3.org/1999/xlink"
  >
    <defs>
      <pattern id="sawPattern" x="50%" width="20" height="10" patternUnits="userSpaceOnUse">
        <path d="M 0 0 L 10 10 L 20 0 Z" class="common-bg"/>
      </pattern>
    </defs>
    <rect x="0" y="0" width="100%" height="10" fill="url(#sawPattern)"/>
  </svg>
</div>
Run Code Online (Sandbox Code Playgroud)

如何防止pxiOS Safari和Android浏览器发生½SVG 偏移?这是一个错误,我应该向WebKit开发人员报告吗?也许有一种方法可以使浏览器四舍五入到px页面上的其他元素?

我可以解决这个问题而不必防止½ px移位:

  • 删除非整数高度 .block_content
  • 进行这样的布局,其中半像素线不会导致白线移动

但我想知道是否有一种方法可以防止½ px移位,因为上述解决方案并非总是可行的。

Fin*_*sse 5

iOS:您只需要向SVG元素添加任何CSS转换即可在Safari中修复它。例如.block_edge {-webkit-transform: scale(1); transform: scale(1)}

Android:首先,您需要向SVG元素添加一个微小的CSS比例转换。完成此操作后,<svg><rect>元素将在必须放置的位置进行渲染,但<rect>背景将在顶部和底部重复:

在此处输入图片说明

要修复它,您需要将图案扩展到顶部和底部以防止背景重复。然后,您需要<rect>在SVG顶部的上方添加一个填充,以删除顶部的最后一个空白行。在Android浏览器的顶部仍然会留下几乎看不见的深灰线。

.common-bg {
  background: #222;
  fill: #222;
}
.block {
  max-width: 300px;
  margin: 20px auto;
}
.block_content {
  height: 50.5px;
}
.block_edge {
  display: block;
  
  /* Fix. No more than 5 zeros. */
  -webkit-transform: scale(1.000001);
  transform: scale(1.000001);
}
Run Code Online (Sandbox Code Playgroud)
<div class="block">
  <div class="block_content common-bg"></div>
  <svg
    class="block_edge"
    width="100%"
    height="10"
    xmlns="http://www.w3.org/2000/svg"
    version="1.1"
    xmlns:xlink="http://www.w3.org/1999/xlink"
  >
    <defs>
      <pattern id="sawPattern" x="50%" y="-1" width="20" height="12" patternUnits="userSpaceOnUse">
        <path d="M 0 0 L 0 1 L 10 11 L 20 1 L 20 0 Z" class="common-bg"/>
      </pattern>
    </defs>
    <rect x="0" y="-1" width="100%" height="1" common-bg="common-bg"/>
    <rect x="0" y="0" width="100%" height="10" fill="url(#sawPattern)"/>
  </svg>
</div>
Run Code Online (Sandbox Code Playgroud)

CodePen上的代码段

我在移动和台式机Safari 10,Android 4.4和Android上的Chrome 58上进行了测试。

结论:修复程序太复杂且不可靠,因此我建议进行这样的布局,其中半像素移位不会导致空白行。

.common-bg {
  background: #222;
  fill: #222;
}
.block {
  max-width: 300px;
  margin: 20px auto;
}
.block_content {
  height: 50.5px;
}
.block_edge {
  display: block;
  
  /* Overflow for unexpected translateY */
  margin-top: -1px;
}
Run Code Online (Sandbox Code Playgroud)
<div class="block">
  <div class="block_content common-bg"></div>
  <svg
    class="block_edge"
    width="100%"
    height="12"
    xmlns="http://www.w3.org/2000/svg"
    version="1.1"
    xmlns:xlink="http://www.w3.org/1999/xlink"
  >
    <defs>
      <!-- The teeth pattern is extended to the top -->
      <pattern id="sawPattern" x="50%" width="20" height="12" patternUnits="userSpaceOnUse">
        <path d="M 0 0 L 0 1 L 10 11 L 20 1 L 20 0 Z" class="common-bg"/>
      </pattern>
    </defs>
    <rect x="0" y="0" width="100%" height="11" fill="url(#sawPattern)"/>
  </svg>
</div>
Run Code Online (Sandbox Code Playgroud)

CodePen上的代码段