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

时间:2017-12-11 17:51:22

标签: svg svg-filters dropshadow

我有以下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)。

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

3 个答案:

答案 0 :(得分:4)

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

  

当适用元素的几何图形没有宽度或没有高度时,不应使用关键字objectBoundingBox,例如水平线或垂直线的情况,即使由于具有非零值而在查看时线条具有实际厚度时也是如此因为边界框计算忽略了笔划宽度,所以笔划宽度。当适用元素的几何体没有宽度或高度且指定了objectBoundingBox时,将忽略给定的效果(例如,渐变或滤镜)。

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

&#13;
&#13;
<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>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

处理过滤器时,不同的浏览器会处理不同的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>
   

答案 2 :(得分:0)

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

  1. 滤镜效果区域将应用​​画布的-10%到120%,而不是 element 的边框(使用更多的内存和处理时间)
  2. 对于大型动态SVG(例如d3创建的SVG),可能难以计算所需的过滤器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>