Mark Hill February 2016

SVG filter won't disappear on hover using transitions

I am currently working on some new stuff and I have been introduced to the world of SVG objects. They are nice. Anyways, I have a button that I have built and I put a filter on it. The designer I'm working with would like the filter (a drop shadow) to go from opacity 1 to 0 on hover, and return to 1 off hover.

I have tried just normal transitions on the filter, and I can get the filter to disappear but the transition is far from smooth.

Here's my code:

html

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 216 216" style="enable-background:new 0 0 216 216;" xml:space="preserve">
  <filter id="fade" height="150%" width='150%'>
     <feMerge>
      <feMergeNode/>
      <!-- this contains the offset blurred image -->
      <feMergeNode in="SourceGraphic" />
      <!-- this contains the element that the filter is applied to -->
    </feMerge>
  </filter>
  <filter id="dropshadow" height="150%" width='150%'>
    <feGaussianBlur in="SourceAlpha" stdDeviation="25" />
    <!-- stdDeviation is how much to blur -->
    <feOffset dx="0" dy="15vh" result="offsetblur" />
    <!-- how much to offset -->
    <feComponentTransfer>
      <feFuncA type="linear" slope="0.4" />
    </feComponentTransfer>
    <feMerge>
      <feMergeNode/>
      <!-- this contains the offset blurred image -->
      <feMergeNode in="SourceGraphic" />
      <!-- this contains the element that the filter is applied to -->
    </feMerge>
  </filter>
  <a href='' id='playvideo_button'>
    <g>
      <path class="st0" d="M108,24c-46.4,0-84,37.6-84,84s37.6,84,84,84s84-37.6,84-84S154.4,24,108,24z" />
      <polygon class="st1" points="92,140 92,76 140,108" />
    </g>
  </a>
</svg>        

Answers


kevinkl3 February 2016

You can achieve this effect using a path with a gaussian blur to simulate the shadow instead of using a filter, the result i got is this:

path with gaussian blur

In this way you can handle the "drop shadow" directly, then with just simple CSS you can make the opacity transition.

svg #shadow{
  transition: all 0.65s;
  opacity:1;
}
svg:hover #shadow{
  opacity:0;
}

The complete SVG:

<svg
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   version="1.1"
   width="216"
   height="216"
   id="svg3013">
  <defs
     id="defs3015">
    <filter
       x="-0.14227594"
       y="-0.13746469"
       width="1.2845519"
       height="1.2749294"
       color-interpolation-filters="sRGB"
       id="filter3826">
      <feGaussianBlur
         id="feGaussianBlur3828"
         stdDeviation="8.4688065" />
    </filter>
  </defs>
  <g
     transform="translate(0,-836.36218)"
     id="layer1">
    <path
       d="m 183.57143,107.07143 a 71.428574,73.928574 0 1 1 -142.857143,0 71.428574,73.928574 0 1 1 142.857143,0 z"
       transform="matrix(1.064,0,0,1.0280193,-11.320001,836.29069)"
       id="shadow"
       style="fill:#1a1a1a;fill-opacity:1;stroke:none;filter:url(#filter3826)" />
    <g
       transform="translate(-0.14285916,0.7142867)"
       id="g3806">
      <path
         d="m 183.57143,107.07143 a 71.428574,73.928574 0 1 1 -142.857143,0 71.428574,73.928574 0 1 1 142.857143,0 z"
         transform="matrix(1.064,0,0,1.0280193,-11.177142,835.5764)"
         id="path3021"
         style="fill:#4982cf;fill-opacity:1;stroke:none" />
      <path
         d="m 8 


Michael Mullany February 2016

Using transitions on the filter is not the way to do this. Here is a more elegant way. There are a bunch of things here you should note:

  • You need to size both the svg and the filter regions properly to make sure the shadow isn't cut off
  • You can't transition filters
  • Support for CSS units isn't reliably supported inside an SVG filter, stick to either objectBoundingBox (%) or userSpaceOnUse (viewbox) units
  • Look at how I constructed the filter to allow it to be drawn on top of the shape (to capture hover) without obscuring it. That's the "operator="out" part of the filter.

  • Enclose your filter in a defs element. Some browsers require this.

  • DON'T use Illustrator export boilerplate, you need to remove the xmlns definitions if you want your svg fragment in the normal HTML5 namespace. Trust me, you'll save yourself javascript problems later.

In general, the worst way to learn SVG is by trying to decode or tweak Illustrator export code. It's just an unmitigated craptastic disaster.

svg {
  width: 30vw;
  height: 30vh;
  cursor: pointer;
}

svg .st0 {
  fill: #4982CF;
}

svg .st1 {
  fill: #ffffff;
}

#usedshadow {
   opacity: 1;
   transition: opacity 0.6s;
}

#usedshadow:hover {
   opacity: 0;
   transition: opacity 0.6s;
}
<svg version="1.1" x="0px" y="0px" width="300px" height="300px" viewBox="0 0 300 300">

  <defs>
    <filter id="dropshadow" x="-50%" y="-50%" height="200%" width='200%'>
      <feGaussianBlur in="SourceAlpha" stdDeviation="10" />
      <!-- stdDeviation is how much to blur -->
      <feOffset dx="0" dy="15" result="offsetblur" />
      <!-- how much to offset - 

Post Status

Asked in February 2016
Viewed 2,211 times
Voted 11
Answered 2 times

Search




Leave an answer