KevinRethwisch
KevinRethwisch

Reputation: 237

enlarged svg drop shadows

The following code displays an arrow with drop shadow. The requirement calls for making the shadow slightly larger than the arrow, so that if the arrow were straight and pointing directly forward then shadow could be seen on either side of the arrow in equal amounts. I tried creating two shadows that differ only in their horizontal position but never got it to work correctly.

The requirement calls for unblurred shadow, so "enlarging" by adding blur is not an option. The image is not supposed to look realistic.

I already have code that creates an enlarged, vertically shifted, black copy of the arrow. I hope for a more refined solution since that's a lot of code and redundant data.

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg id="785849135" width="960pt" height="720pt"
 viewBox="160 0 960 720"
 xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
  <defs>
    <filter id='drop-shadow'>
      <!-- Shadow Offset -->
      <!-- EDIT: dx and dy to change the size of the shadow -->
      <feOffset     
        dx='-4'
        dy='4'
      />
      <!-- Shadow Blur -->
      <!-- EDIT: edit stdDeviation to change the shadow blurriness -->
      <!-- "0" is no blur -->
      <feGaussianBlur
        stdDeviation='0'
        result='offset-blur'
      />
      <!-- Color & Opacity -->
      <feFlood
        flood-color='black'
        flood-opacity='1'
        result='color'
      />      
      <!-- Clip color inside shadow -->
      <feComposite
        operator='in'
        in='color'
        in2='offset-blur'
        result='shadow'
      />      
      <!-- Put original object over shadow -->
      <feComposite
        operator='over'
        in='SourceGraphic'
        in2='shadow'
      />
    </filter>
    </defs>
      <g  filter='url(#drop-shadow)'>
        <path fill="#654114" stroke="#654114" stroke-width="0.0" d="M547.71777 390.23407 L 527.47506 392.82273 540.08449 392.79837 539.86309 393.17777 426.68945 586.88612 399.23955 630.62126 361.53130 686.78918 337.97979 720.00000 362.91010 720.00000 391.19683 720.00000 410.65441 686.73793 441.43435 630.48495 463.47400 586.70712 552.51368 393.15324 552.68787 392.77403 565.28519 392.74969 547.71777 390.23407 z"/>
      </g>
</svg>

Upvotes: 2

Views: 2470

Answers (2)

Thomas W
Thomas W

Reputation: 15371

As I understand it, you don't want a blur effect but a solid arrow. Maybe still use the <feGaussianBlur> to make the arrow "larger" and then add an <feColorTransfre> to adjust the alpha channel, basically making the whole blurred area solid.

<svg id="785849135" width="960pt" height="720pt"
 viewBox="160 0 960 720"
 xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
  <defs>
    <filter id='drop-shadow'>
      <!-- Shadow Offset -->
      <!-- EDIT: dx and dy to change the size of the shadow -->
      <feOffset     
        dx='-4'
        dy='4'
      />
      <!-- Shadow Blur -->
      <!-- EDIT: edit stdDeviation to change the shadow blurriness -->
      <!-- "0" is no blur -->
      <feGaussianBlur
        stdDeviation='1'
        result='offset-blur'
      />
      <!-- Color & Opacity -->
      <feFlood
        flood-color='black'
        flood-opacity='1'
        result='color'
      />      
      <!-- Clip color inside shadow -->
      <feComposite
        operator='in'
        in='color'
        in2='offset-blur'
        result='shadow'
      />      
      <!-- Put original object over shadow -->
      <feComposite
        operator='over'
        in='SourceGraphic'
        in2='shadow'
      />
      <feComponentTransfer>
        <feFuncA type="linear" slope="99"/>
      </feComponentTransfer>
    </filter>
    </defs>
      <g  filter='url(#drop-shadow)'>
        <path fill="#654114" stroke="#654114" stroke-width="0.0" d="M547.71777 390.23407 L 527.47506 392.82273 540.08449 392.79837 539.86309 393.17777 426.68945 586.88612 399.23955 630.62126 361.53130 686.78918 337.97979 720.00000 362.91010 720.00000 391.19683 720.00000 410.65441 686.73793 441.43435 630.48495 463.47400 586.70712 552.51368 393.15324 552.68787 392.77403 565.28519 392.74969 547.71777 390.23407 z"/>
      </g>
</svg>

BTW, I think your <svg> element has an invlid ID. AFAIK, it must start with a letter or an underscore.

Upvotes: 2

Michael Mullany
Michael Mullany

Reputation: 31715

This should produce what you want (or at least what I think you want). Like Thomas suggests, it uses a Gaussian Blur - but only in the x direction. Then it uses a Component transfer to dial up the alpha to 1 for all but the edge of the blur - which is left basically alone. If you don't do this, you end up with a jaggy edge (you're essentially hand-anti-aliasing the edge of the shadow). The other feFunc's dial the color down to black. Enjoy.

<svg id="785849135" width="960pt" height="720pt"
 viewBox="160 0 960 720"
 xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
  <defs>
    <filter id='drop-shadow'>
      <!-- Shadow Offset -->
      <!-- EDIT: dx and dy to change the position of the shadow -->
      <feOffset     
        dx='-2'
        dy='4'
      />
      <!-- Shadow Blur -->
      <!-- EDIT: edit stdDeviation to change the shadow width -->
      <!-- "0 0 " is no blur -->
      <feGaussianBlur
        stdDeviation='3 0'
        result='offset-blur'
      />

      <feComponentTransfer in="offset-blur" result="shadow">
          <feFuncA type="table" tableValues="0 1 1 1 1 1 1 1 1 1 1 1 1 1"/>
          <feFuncR type="discrete" tableValues="0"/>
          <feFuncG type="discrete" tableValues="0"/>
          <feFuncB type="discrete" tableValues="0"/>

        </feComponentTransfer>
      <!-- Put original object over shadow -->
      <feComposite
        operator='over'
        in='SourceGraphic'
        in2='shadow'
      />
    </filter>
    </defs>
      <g filter="url(#drop-shadow)">
        <path fill="#654114" stroke="#654114" stroke-width="1" d="M547.71777 390.23407 L 527.47506 392.82273 540.08449 392.79837 539.86309 393.17777 426.68945 586.88612 399.23955 630.62126 361.53130 686.78918 337.97979 720.00000 362.91010 720.00000 391.19683 720.00000 410.65441 686.73793 441.43435 630.48495 463.47400 586.70712 552.51368 393.15324 552.68787 392.77403 565.28519 392.74969 547.71777 390.23407 z"/>
      </g>
</svg>

Upvotes: 2

Related Questions