Jump to content
Search Community

Using cycle with attr:{} for SVG animation, and using values that depend on the tl's progress?

Acccent test
Moderator Tag

Go to solution Solved by Carl,

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

Hi :)
If you've read this thread you know I've been trying to animate SVG masks. From what I gather, this is only possible by manipulating the SVG attributes directly, not with CSS transforms – which makes it easy for things like a circle's radius, but less so for rotation.


Here's how I've attempted to do it (you can check the linked codepen):

tl.staggerTo(el, 1, { cycle:{attr:function(){
  var a = {cx:0, cy: 0};
  a.cx = Math.cos((tl.progress() - 0.5) * 2 * Math.Pi) * 20;
  a.cy = Math.sin((tl.progress() - 0.5) * 2 * Math.Pi) * 20;
  return a;
}}, ease: Linear.easeNone })

The goal is to change the cx and cy attributes over time so that the SVG element moves along a circle.


There are two problems:

  • using cycle and attr in conjunction doesn't seem to work? The function returns an object that should look like {cx:..., cy:...} but it's not interpreted correctly. I suspect I'm doing something really wrong here that has to do with not knowing javascript enough...
  • here I'm trying to use tl.progress() to calculate cx and cy depending on the animation's progress, but this approach doesn't work; the progress is always 0 when accessed within the timeline itself I think, since the calculations are made prior to it running. How could I make it update properly? Using an onUpdate function, maybe?


Cheers ^_^

See the Pen yYPJOL by Acccent (@Acccent) on CodePen

Link to comment
Share on other sites

  • Solution

Hi accent,


This is a basic example of using cycle with the AttrPlugin:

tl.staggerTo("circle", 1, {
  cycle: {
   attr: function(i) {
        var a = {};
        a.cx = (i+1) * 100
        a.cy = (i+1) * 100
        return a;
  ease: Linear.easeNone
}, 0.8)



And yes, the values that are generated using cycle are only generated once when the tween is created. 





Also, after spending a bit of time hacking at your demo I realized you were using /latest/TweenMax.min.js  Unfortunately, and its cloudfare's fault, that still doesn't load up 1.18.0 (which you need for cycle). I'm sure it was frustrating for you too. Sorry about that.


Be sure to load /1.18.0/TweenMax.min.js like I am doing in the pen above.


Also you can always do


incase you have any doubts.


From what I gather, an onUpdate callback seems like an avenue worth exploring.

  • Like 5
Link to comment
Share on other sites

Thanks a lot! After changing the TweenMax.min.js version, and Math.Pi to Math.PI (sigh), I got it to work :)


var eyeL = $("#eyeL"),
    eLx = 1*eyeL.attr("cx"),
    eLy = 1*eyeL.attr("cy"),
    tl = new TimelineMax({paused:true, repeat:-1});

tl.to(eyeL, 1, { ease: Linear.easeNone, onUpdate: rotatesvg, onUpdateParams:[eyeL] });

function rotatesvg(el){
  var a = eLx + Math.sin(tl.progress() * 2 * Math.PI) * 20,
      b = eLy + Math.cos(tl.progress() * 2 * Math.PI) * -20;
  TweenMax.to(el, 0, {attr:{cx:a, cy:b}});

This makes the left eye in the codepen rotate in Chrome and IE (can't test with FF at the moment).


There's a caveat: on each update of tl, the rotatesvg function is called, which instantly moves the circle to the next point. There's no smoothing, and you can indeed see a slight difference between the two eyes in Chrome. If you could pass to the onUpdate function the delay between each step of tl, then you could specify a duration for the TweenMax in rotatesvg(), and it would be smoother.


This could probably be implemented in GSAP? It could be used when you use rotate: inside attr:{}, since it provides a cross-browser solution for svg rotation, which the CSSPlugin doesn't have.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...