<marker> 中的 SVG "vector-effect: non-scaling-stroke":Firefox 与 Chrome

SVG "vector-effect: non-scaling-stroke" in <marker>: Firefox vs Chrome

考虑以下代码片段,其中包含两个版本的 SVG,其箭头由 <marker> 定义。线条和路径的样式为 vector-effect: non-scaling-stroke。第二个版本只是第一个版本,所有坐标都除以 10(并且标记 id 更改为其他内容)。

JSFiddle:https://jsfiddle.net/nkevo5ja

在 Windows 10:

谁的实现不正确?

<!-- Styles -->
<svg width="0" height="0">
  <style>
    line, path {
      stroke: black;
      vector-effect: non-scaling-stroke;
    }
  </style>
</svg>

<!-- Larger version -->
<svg width="120px" height="100%" viewBox="0 0 400 300">
  <defs>
    <marker id="larger"
      viewBox="0 -20 70 40"
      refX="70" refY="0"
      markerWidth="70" markerHeight="40"
      orient="auto"
    >
      <path d="M 70 0 L 0 -20 L 0 20 z"/>
    </marker>
  </defs>
  <line x1="400" y1="300" x2="0" y2="0" marker-end="url(#larger)"/>
</svg>

<!-- Smaller version (larger version with all coordinates divided by 10) -->
<svg width="120px" height="100%" viewBox="0 0 40 30">
  <defs>
    <marker id="smaller"
      viewBox="0 -2 7 4"
      refX="7" refY="0"
      markerWidth="7" markerHeight="4"
      orient="auto"
    >
      <path d="M 7 0 L 0 -2 L 0 2 z"/>
    </marker>
  </defs>
  <line x1="40" y1="30" x2="0" y2="0" marker-end="url(#smaller)"/>
</svg>

Chromium 问题:https://crbug.com/1107791

Firefox 有正确的行为,在 the specs 中甚至有关于这个确切案例的注释:

When ‘markerUnits’ has the value strokeWidth, the size of the marker is relative to the stroke-width after it has had any transforms applied that affect the width of the stroke in the user coordinate system for the stroke. This means that, for example, the vector-effect attribute with a value of non-scaling-stroke will result in the markers also being non scaling.

strokeWidthmarkerUnits.

的默认值

编辑: 原来我对规格的阅读是错误的,应该发生的是 markerWidthmarkerHeight 乘以最终计算strokewidth 描边线 - 此处为 1px - 就像 Chrome 所做的那样。

您可以参考 ,他为 Firefox 推送了一个修复程序,因此它符合 Chrome 和规范。


使用这个确切的片段,您可以通过将此 markerUnits 属性设置为 userSpaceOnUse 在 Chrome 和 Firefox 中获得相同的结果。

<!-- Styles -->
<svg width="0" height="0">
  <style>
    line, path {
      stroke: black;
      vector-effect: non-scaling-stroke;
    }
  </style>
</svg>

<!-- Larger version -->
<svg width="120px" height="100%" viewBox="0 0 400 300">
  <defs>
    <marker id="larger"
      viewBox="0 -20 70 40"
      refX="70" refY="0"
      markerUnits="userSpaceOnUse"
      markerWidth="70" markerHeight="40"
      orient="auto"
    >
      <path d="M 70 0 L 0 -20 L 0 20 z"/>
    </marker>
  </defs>
  <line x1="400" y1="300" x2="0" y2="0" marker-end="url(#larger)"/>
</svg>

<!-- Smaller version (larger version with all coordinates divided by 10) -->
<svg width="120px" height="100%" viewBox="0 0 40 30">
  <defs>
    <marker id="smaller"
      viewBox="0 -2 7 4"
      refX="7" refY="0"
      markerUnits="userSpaceOnUse"
      markerWidth="7" markerHeight="4"
      orient="auto"
    >
      <path d="M 7 0 L 0 -2 L 0 2 z"/>
    </marker>
  </defs>
  <line x1="40" y1="30" x2="0" y2="0" marker-end="url(#smaller)"/>
</svg>

Firefox 出错了,我刚刚修复了它,现在它与 Chrome 在这种情况下具有相同的渲染效果。

这里有两个效果,non-scaling-stroke 在标记内的路径上,non-scaling-stroke 在标记使用的 markerWidth 上。该 markerWidth 基于标记线的 stroke-width 并且该笔划也是 non-scaling.

Firefox 和 Chrome 确实将 non-scaling-stroke 转换应用于标记的线条,但只有 Chrome 也更正了 strokeWidth。从明天开始,Firefox nightlies 将正确处理 strokeWidth。 Firefox 83 将是第一个包含该修复程序的版本。