elegantseagulls

Custom Ease vs Bezier vs Bigger Timeline Performance Question

Recommended Posts

Hey GSAP friends!

I'm tweening a SVG circle's radius value and need it to sorta vibrate as it expands and contrasts. I'm just wondering, from a performance standpoint, what should give me best performance:

 

var tl = new TimelineMax({repeat: -1, ease:Power0.easeNone})

//A:
tl
  .to(svg, 2, {attr:{r:150}, ease: CustomEase.create("custom", "M0,0,C0,0,0.051,0.218,0.06,0.256,0.073,0.245,0.138,0.197,0.155,0.185,0.166,0.209,0.213,0.311,0.22,0.324,0.222,0.316,0.291,0.284,0.294,0.276,0.299,0.29,0.362,0.23,0.386,0.284,0.466,0.375,0.446,0.529,0.474,0.56,0.479,0.538,0.574,0.486,0.58,0.462,0.622,0.505,0.803,0.689,0.905,0.792,0.911,0.871,0.923,1.026,0.925,1.045,0.929,1.038,0.973,0.959,0.98,0.948,0.982,0.954,1,1,1,1")})
  .to(svg, 2, {attr:{r:100}, ease: CustomEase.create("custom", "M0,0,C0,0,0.051,0.218,0.06,0.256,0.073,0.245,0.138,0.197,0.155,0.185,0.166,0.209,0.213,0.311,0.22,0.324,0.222,0.316,0.291,0.284,0.294,0.276,0.299,0.29,0.362,0.23,0.386,0.284,0.466,0.375,0.446,0.529,0.474,0.56,0.479,0.538,0.574,0.486,0.58,0.462,0.622,0.505,0.803,0.689,0.905,0.792,0.911,0.871,0.923,1.026,0.925,1.045,0.929,1.038,0.973,0.959,0.98,0.948,0.982,0.954,1,1,1,1")})

//B:
tl
  .to(svg, 4, {bezier:{curviness:1.25, values:[{
    {attr:{r:90}}, {attr:{r:40}},{attr:{r:50}},{attr:{r:80}},{attr:{r:150}},/*...etc...*/{attr:{r:95}},{attr:{r:100}} 
  ]}} })

//or C:
tl
  .to(svg, .1, {attr:{r:90}})
  .to(svg, .1, {attr:{r:40}})
/*...etc...*/
  .to(svg, .1, {attr:{r:150}})
/*...etc...*/
  .to(svg, .1, {attr:{r:100}})


I know the level of control/readability will be different with each, but just wondering from a performance standpoint what will be best, or if it'd be minimal? Also, how would one go about testing this? There will be more going on in the timeline (several circles being animated in a similar way).

Share this post


Link to post
Share on other sites

It's a waste of time to worry about such things because they probably won't matter. At least, not for the scenario you described. Go for the solution that is the easiest to read, understand, and update, C.

 

If you notice a performance problem, investigate it, but there's a 99.99% chance that it will be related to what you're animating, i.e. SVG.

  • Like 5

Share this post


Link to post
Share on other sites

Yep, I'd agree with @OSUblake. Technically, though, I personally favor CustomEase when creating very nuanced movements because (at least in my experience) when I try to recreate an effect using a bunch of sequenced to() values it just doesn't quite feel as fluid. That's not because of anything in GSAP - it's just the nature of the beast. Like I've seen lots of attempts at doing an Elastic.easeOut or a realistic bounce with squash/stretch using straight-up CSS keyframes and it looked really weird. With CustomEase, it felt natural. 

 

In terms of raw runtime performance, the CustomEase one is likely the best but there's a bit more up-front work to create the ease itself and cache the values. Once they're built, though, it's very fast to actually get/set the values during the tween. I optimized the snot out of it ;)

 

Again, performance-wise I doubt you're gonna notice any real-world difference in any of them. Rendering performance in the browser is typically 99%+ of the load on the browser especially with SVG.

 

Happy tweening!

  • Like 4

Share this post


Link to post
Share on other sites

Thanks for the info @GreenSock. On those lines, is there an easy way to 'inspect' a RoughEase's randomly generated path value (outside of the ease visualizer)?

Share this post


Link to post
Share on other sites

So decided to do performance test with Custom Ease vs Bezier, and also show look and feel. Performance looks very similar. 

Here they are if anyone is interested:

 

 

 

 

Any and all feedback/ideas are welcome!

 

Thanks!

 

  • Like 5

Share this post


Link to post
Share on other sites

Nice work! Both worked flawlessly on my Mac (no discernible performance difference). You'd probably have to crank the instances WAY up to notice any difference. 

 

Thanks for sharing. 

  • Like 1

Share this post


Link to post
Share on other sites

Greetings, Greetings, fellow GSAPers.

 

Up until this point I've pretty much only worked with SVG/Dom animations, but it seems that Safari is having some performance issues animating a SVG pattern that's also an SVG mask (see: https://codepen.io/elegantseagulls/pen/OBKPba ) so: Hello Canvas. I've never worked with animating canvas so I'm wondering if my approach is they way I should be approaching it:

 

 

I initially had it looping every line and adding a `tl.to()` for that, but changed it to just be the number of custom eases and am adding the additional lines in the update function instead.

I'm not looking a full code review, and I know this is not a direct question, but just making sure I'm not approaching Canvas in a completely backwards way. Any thoughts are welcome.

 

 

 

Share this post


Link to post
Share on other sites

I didn't see any problems with it. The only other thing you could consider doing to optimize performance (though probably not significant) is to batch all your canvas drawing into a single onUpdate that sits on your timeline (or a TweenLite.ticker.addEventListener("tick")) instead of an onUpdate in every tween. But again, we're probably splitting hairs here. @OSUblake is our resident canvas expert, and @Sahil has been diving in lately too, so those guys may have other advice. 

  • Like 2

Share this post


Link to post
Share on other sites

@GreenSock

 

Glad to know I'm at least on the the right track. Good tip on the `ticker`. I'll look into that.

 

Thanks,

Ryan

 

Share this post


Link to post
Share on other sites

Ya moving all draw calls to single place would be better for performance. As you are using same stroke, you can construct path in loop and stroke it just once. Also use clearRect on entire canvas because everything is updating on every frame.

 

https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Optimizing_canvas

 

As for coding style, I would have used prototype maybe, because that's how I learned to do using Foundation HTML5 Animation book. You will find it useful if you plan to do more stuff with canvas.

 

 

  • Like 4

Share this post


Link to post
Share on other sites

@Sahil Really helpful tips here! Thank you! I'm still wrapping my head around some of the canvas properties and how they work, constructing the path in loop will really help simplify. Appreciate the resource links too! thanks!

  • Like 1

Share this post


Link to post
Share on other sites

@Sahil @GreenSock

 

Thank you so much for your tips! I was able to apply them, as well as some I picked up diving a bit deeper in the forms here. Here's what I'm hoping is near the final product:

 

  • Like 1

Share this post


Link to post
Share on other sites

That's close but in your case you are not using different strokes so you can do everything in render function to optimize further.

 

TweenLite.ticker.addEventListener("tick", render);

function render(event) {
  
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  // set style and beginPath
  for (let i = 0; i < lines.length; i++) {    
    // call draw function of prototype but don't stroke in prototype
    // to avoid stroke calls because you are not using different strokes
    // or draw lines here directly if you are sure you won't need to make changes
    // like randomizing stroke etc
  }
  ctx.stroke();
}

 

  • Like 4

Share this post


Link to post
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.