Search code examples
svgsvg-filters

oddly shaped SVG drop shadow


Here's the source:

<svg width="640" height="480" xmlns="http://www.w3.org/2000/svg">
 <g>
  <defs>
    <filter id="f1" x="0" y="0" width="200%" height="200%">
      <feOffset result="offOut" in="SourceGraphic" dx="0" dy="0" />
      <feColorMatrix result="matrixOut" in="offOut" type="matrix"
      values="0.2 0 0 0 0 0 0.2 0 0 0 0 0 0.2 0 0 0 0 0 1 0" />
      <feGaussianBlur result="blurOut" in="matrixOut" stdDeviation="10" />
      <feBlend in="SourceGraphic" in2="blurOut" mode="normal" />
    </filter>
  </defs>
  <path fill="#E0E0E0" stroke="#FFFFFF" stroke-width="5" d="M 50 50 l 100 0 l -50 86.6 z" filter="url(#f1)"/>
 </g>
</svg>

And here's what it looks like rendered by Firefox: Chrome is similar.

Why is the drop shadow asymmetrical? I was hoping to make it look as though the illumination is from directly above the image, so the shadow should be symmetrical. It should end up looking something like the following raster image:

(I'm sorry the colours of the interiors don't match, but I'll fix that later.)


Solution

  • Is this more like what you want?

    <svg width="640" height="480" xmlns="http://www.w3.org/2000/svg">
     <g>
      <defs>
        <filter id="f1" x="-1" y="-1" width="300%" height="300%">
          <feOffset result="offOut" in="SourceGraphic" dx="0" dy="10" />
          <feColorMatrix result="matrixOut" in="offOut" type="matrix"
          values="0.2 0 0 0 0 0 0.2 0 0 0 0 0 0.2 0 0 0 0 0 1 0" />
          <feGaussianBlur result="blurOut" in="matrixOut" stdDeviation="10" />
          <feBlend in="SourceGraphic" in2="blurOut" mode="normal" />
        </filter>
      </defs>
      <path fill="#E0E0E0" stroke="#FFFFFF" stroke-width="5" d="M 50 50 l 100 0 l -50 86.6 z" filter="url(#f1)"/>
     </g>
    </svg>
    

    Edit: Explanation:

    I made the filter effect region larger (using width/height on <filter>) so that it is larger than the bounding box of the shape (300% its width). Of course it has to be repositioned (using x/y) so that the shape sits in the center of the effect region. I also moved the shadow a little downwards using the y attribute on feOffset.

    Side note: As Erik Dahlström mentioned in the comments, using 3 instead of 300% for width and height is equivalent in this case because filterUnits is implicitly set to objectBoundingBox. The same is true for -1 and -100% on x and y. I mixed both notations.