Zlerp
Zlerp

Reputation: 467

Use jquery to animate the Fill of an SVG?

I am trying to use jQuery to animate the path of my SVG, THEN after the first animation completes, animate the fill of the SVG with a duration and an easing function.

Is this possible?

$(function() {
  $('svg').hover(function() {
    $(this).find('.social-circle').stop()
      .animate({'stroke-dashoffset': 0}, 1000, 'easeOutBounce')
      .css('fill', '#f4321e');
      console.log('on');
  }, function() {
    $(this).find('.social-circle').stop()
      .animate({'stroke-dashoffset': 900}, 1000, 'easeOutBounce')
      .css('fill', 'none');
  });
});

thanks for your time!

Upvotes: 3

Views: 7638

Answers (1)

Mi-Creativity
Mi-Creativity

Reputation: 9654

One way to do it is by using CSS transition (*), but you need to make the fill:transparent instead of fill:none, like below (1):

JS Fiddle 1

$(function() {
  
  $('svg').hover(function() {
    $('svg').find('.social-circle').stop()
      .animate({'stroke-dashoffset': 0}, 1000)
      .css({'fill': 'red', 'transition': 'fill 1s'});
    console.log('on');
  }, function() {
    $('svg').find('.social-circle').stop()
      .animate({'stroke-dashoffset': 900}, 1000)
      .css({'fill': 'transparent', 'transition': 'fill 1s'});
  });
  
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<svg height="100" width="100">
  <circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="orange" class="social-circle" />
</svg>


Also you can make use of the callback function which the .animate() function provides

.animate( properties [, duration ] [, easing ] [, complete ] )

Where "complete is a function to call once the animation is complete, called once per matched element", we can here call another function that animates fill of the element using CSS transition like this:

JS Fiddle 2

$(function() {

  $('svg').hover(function() {
    $('svg').find('.social-circle').stop()
      .animate({'stroke-dashoffset': 0}, 1000, animateFill('red'))
    console.log('on');
  }, function() {
    $('svg').find('.social-circle').stop()
      .animate({'stroke-dashoffset': 900}, 1000, animateFill('transparent'))
  });


  function animateFill(theColor) {
    $('svg').find('.social-circle').css({'fill': theColor, 'transition': 'fill 1s'});
  }

})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<svg height="100" width="100">
  <circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="orange" class="social-circle" />
</svg>



Alternatively you can achieve the same effect with Snap.svg -which supports IE9+ while CSS transition is supported by IE10 and above- using its animate() (*) function, but when I tried to pass animFill('transparent') or animFill('none') it defaults the color to black rather than transparent. So I made the function animates both the fill and the fill-opacity (2) so it could be used for both transitioning colors or fill opacity. as following:

JS Fiddle 3

$(function() {
  $('svg').hover(function() {
    $('svg').find('.social-circle').stop()
      .animate({'stroke-dashoffset': 0}, 1000, animFill('red', 1));
    console.log('on');
  }, function() {
    $('svg').find('.social-circle').stop()
      .animate({'stroke-dashoffset': 900}, 1000, animFill('red', 0))
  });
});

function animFill(theColor, theOpacity) {
  Snap('svg').select('.social-circle')
    .animate({'fill': theColor,'fill-opacity': theOpacity}, 1000);
}
<script src="//cdnjs.cloudflare.com/ajax/libs/snap.svg/0.4.1/snap.svg-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<svg height="100" width="100">
  <circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="orange" class="social-circle" id="social" />
</svg>

--------------------------------------------------------------------------------

(*) For both CSS transition and Snap.svg animation you can use easing just like jQuery. For CSS it could be done like this:

transition: fill 1s ease-out 

For Snap.svg the easing could be set through the mina() method, same as above:

element.animate({'fill':theColor, 'fill-opacity':theOpacity}, 1000, mina.easeout);

(1) I removed the easing for simplicity.

(2) By using fill-opacity we control the opacity of the fill only, if we use opacity, the whole element will be affected as fill and stroke. And there's stroke-opacity as well for controlling the opacity of the stroke too.

Upvotes: 2

Related Questions