将 feDropShadow 添加到 SVG 中的垂直线使其消失

Adding feDropShadow to a vertical line in SVG makes it disappear

我有以下 SVG 文档:

  <svg preserveAspectRatio="xMinYMin meet" viewBox="0 0 21 484" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <filter id="dropShadow">
      <feDropShadow dx="4" dy="0" stdDeviation="4"></feDropShadow>
    </filter>
  </defs>
  <g id="Artboard" stroke-width="5" stroke="#FF0000" fill="#000000" stroke-linecap="round">
    <path style="filter: url(#dropShadow)" d="M7.5,8.5 L7.5,471.5" id="path-1"></path>
  </g>
</svg>

在 Firefox 中,当我打开 SVG 文档时,它只显示一条很细(不是 5 宽)的垂直线。在 Chrome 中,它没有显示任何内容(在 codepen 中也没有,这里:https://codepen.io/jwir3/pen/BJBqEK)。

我不太确定我在这里做错了什么,但这与过滤器有关,因为如果我从 path 定义中删除 filter: url(#dropShadow),行按预期显示。

如果您的形状没有高度或宽度,则不能使用 objectBoundingBox units

Keyword objectBoundingBox should not be used when the geometry of the applicable element has no width or no height, such as the case of a horizontal or vertical line, even when the line has actual thickness when viewed due to having a non-zero stroke width since stroke width is ignored for bounding box calculations. When the geometry of the applicable element has no width or height and objectBoundingBox is specified, then the given effect (e.g., a gradient or a filter) will be ignored.

filterUnits 的默认值是 objectBoundingBox 单位,因此您需要将其更改为 userSpaceOnUse,即

<svg preserveAspectRatio="xMinYMin meet" viewBox="0 0 21 484" xmlns="http://www.w3.org/2000/svg">
  <title>Line Drop Shadow</title>
  <description>A red line with 5px width thickness and round caps, having a drop-shadow. This highlights the regression documented in PURP-1017.</description>
  <defs>
    <filter id="dropShadow" filterUnits="userSpaceOnUse">
      <feDropShadow dx="4" dy="0" stdDeviation="4"></feDropShadow>
    </filter>
  </defs>
  <g id="Artboard" stroke-width="5" stroke="#FF0000" fill="#000000" stroke-linecap="round">
    <path style="filter: url(#dropShadow)" d="M7.5,8.5 L7.5,471.5" id="path-1"></path>
  </g>
</svg>

处理过滤器时,不同的浏览器以不同的方式处理stroke
Chrome 将笔画视为具有零像素的值,因此不会将其包含在过滤区域中。
所以,为了让结果在不同的浏览器中看起来一样,最好把path换成stroke-width ="5",宽5px的矩形不带strokestroke="none"

此外,过滤器区域的默认值是:x =" - 10% "" y = "- 10%" `` width = "120%" `` height = "120%"- 较大的模糊尺寸通常会被截断。

默认情况下,filterUnits = "objectBoundingBox" 因此值以百分比指定。

为了更容易计算 filter region 动作的大小,请以像素为单位指定 filterUnits = "userSpaceOnUse" and then you can specify all dimensions for the过滤区域的值。

<svg preserveAspectRatio="xMinYMin meet" width="100%" height="100%" viewBox="0 0 21 484" xmlns="http://www.w3.org/2000/svg" >
  <defs>
    <filter id="dropShadow" filterUnits = "userSpaceOnUse" x="4" y="0"  width="12" height="472">
      <feDropShadow dx="6" dy="4" stdDeviation="3"></feDropShadow>
    </filter>
  </defs>
  <g id="Artboard"  fill="#FF0000" filter="url(#dropShadow)" >
   <!-- <path style="filter: url(#dropShadow)" d="M7.5,8.5 L7.5,471.5" id="path-1" stroke-width="5" ></path>--> 
    <rect x="5" y="5" width="5" stroke="none" height="463"  /> 
  </g>
</svg>

在大多数情况下换成 userSpaceOnUse 是正确答案,但有以下限制:

  1. 滤镜效果区域将应用​​ canvas 的 -10% 到 120%,而不是 元素的边界框(使用更多内存和处理时间)
  2. 对于大型动态 SVG(例如由 d3 创建),可能很难计算所需的过滤器 x/y/width/height 以确保过滤器适用于所有元素。

另一种(不太优雅)的解决方案是将过滤器应用于 <g> 并使用其中的隐藏节点为组提供正确的宽度或高度:

  <svg xmlns="http://www.w3.org/2000/svg">
  <defs>
    <filter id="dropShadow" width="20">
      <feDropShadow dx="4" dy="0" stdDeviation="4"></feDropShadow>
    </filter>
  </defs>
  <g id="Artboard" style="filter: url(#dropShadow)">
    <circle r="5" cx="0" cy="0" visibility="hidden"></circle>
    <path d="M10,10 L10,100" stroke-width="5" stroke="#FF0000" fill="#000000" stroke-linecap="round"></path>
  </g>
</svg>