Jump to content
GreenSock

Chuck Taylor

Looking for opinions regarding SVG vs Canvas with this example animation

Recommended Posts

Hello everyone, I realize this is not a GSAP specific question, but I would love an opinion on this. I have created the attached animation for a website's homepage hero section - so it would be something that loads up right away. I am currently using an inline SVG and animating the elements. I notice that while I am developing this page and the animation is running, if I look at another browser window open on another screen, there is a lag when I scroll around on other webpages. I do not have a wimpy machine either - Macbook Pro - Apple M1 MAX with 64gb memory. This surprised me, but maybe there is no need for alarm - as the page I am currently working on runs fine on its own - it's just other sites on other screens when this animation is running. I'm also unsure how to measure performances - perhaps this is a Google Chrome (v104) thing...

 

Anyway, I have read general guidelines that SVG is great for simple things like logos, and canvas is great for things with lots of objects, and interactions (like games). Since this example falls between these 2 things, I was looking for any advice or feedback from fellow gsap users who likely have much more experience with both svg and canvas - before I embark on the task of converting all this work to canvas (something I admittedly know very little about).

 

In terms of svg optimization - I took time to merge many of the overlapping shapes, and run it through SVGOMG to reduce the file size substantially from where it was at the beginning. I realize the gradients are likely affecting some of this. Lastly, it seems to run fine on my phone, so I am taking that as a positive sign that it might be okay as is.

 

I initially planned to throw Scrolltrigger into the mix in order to have some parallax with the different layers of gears moving vertically at slightly different rates when scrolling down the page - but I am concerned I may be pushing things too far.

 

Thanks in advance for everyone's time taking a look.

See the Pen mdxGrBd by chucktaylor (@chucktaylor) on CodePen

Link to comment
Share on other sites

It weird that it would effect other pages since most browsers suspend/throttle animations when you go to another tab. Performance should definitely be a concern though. My machine begins to run pretty hot even being on this GSAP page while the SVG animation is running.

It comes down to whether it works or not. You seem to have done everything you can to optimize the SVG. If you are still having performance issues after that, then it might be worth considering canvas animations. I don't have much experience with GSAP + Canvas but I do know that if you get the animation in after effects you can export to a lottie file and the lottie web player has a canvas renderer.

  • Like 2
Link to comment
Share on other sites

Infinitely looping animations and animating elements with gradients are two of the big SVG animation no-no's in my opinion.

You can sometimes get away with infinite animation if it's very small and simple, and again, sometimes get away with gradients if it's small and simple. But large, lots of elements, infinitely animating, AND using gradients is going to be a perf killer I'm afraid.

I'd look at scaling this down a little if I were you.

 

Link to comment
Share on other sites

Also - hooking up the wheels to scrollTrigger would likely be more performant as there's only going to be movement as the user scrolls, not continuously. So that's a good route I reckon!

Link to comment
Share on other sites

Thank you both for your time in checking this out. @SteveS thank you also for letting me know what the result was like on your machine. Looks like I will be delving into the world of canvas. Seems like canvg might be a good place to start with converting this over.

Link to comment
Share on other sites

You may also consider setting this up as a responsive HTML doc with lots of layers using individual <SVG /> elements and sizing everything relative to the container. It'll likely take a lot of math, and time, but with if you are animating the wrapping <SVG/> instead of the paths inside the SVG you can take advantage of hardware acceleration. And if you need to supplement with some internal shape/gradient animation you can do that, in tandem, but those just won't be hardware accelerated (yet!).

Link to comment
Share on other sites

This also seems like it'd be a good candidate for a lottie animation, which sprites out the animation so it's less taxing on resources, but results in a larger file size: http://airbnb.io/lottie/#/

Link to comment
Share on other sites

For what it's worth, in my experience the runtime performance has absolutely nothing to do with file size. The biggest impact seems to be related to: 

  1. Overall bounding rect of the changing pixels on each render. You could have a super heavy, complex SVG that's only changing a 50x50 pixels area and it'll run way faster than a simple one that's changing a 3000x3000 pixels area. 
  2. Specific things that are expensive to render, like filters, masks and maybe gradients. 
  3. I believe strokes can be more difficult for browsers to paint than just filled paths. Not a big deal, but if you have a ton of stroked elements that are also being animated, that could be pricey. 

My guess is that your Mac was having issues partly because it has a very high-DPI screen. So again, think about how many pixels have to be fabricated on every single tick. And I noticed you've got things masked but keep in mind that if you've got things moving outside the mask (invisible), the browser still has to fabricate all those pixels in their new positions...and then mask them out (wasteful). So be very careful about how far that bounding box extends in terms of changing pixels, even if you don't technically see them. 

 

Good luck!

Link to comment
Share on other sites

Yeah, I also wouldn't advise Lottie for perf reasons. I made some full page Lottie animations a while back and they were ok if you cut the frames down to 30 fps and used the canvas renderer, with the SVG renderer they were brutal. But the canvas renderer also has a lot of limitations - you can't use as many after effects techniques.

  • Like 1
Link to comment
Share on other sites

(Also SVG elements are hardware accelerated in firefox and chrome now)

  • Like 1
Link to comment
Share on other sites

1 hour ago, elegantseagulls said:

if you are animating the wrapping <SVG/> instead of the paths inside the SVG you can take advantage of hardware acceleration

I didn't realize this. Might be a good option. Thanks for the suggestion!

1 hour ago, GreenSock said:

if you've got things moving outside the mask (invisible), the browser still has to fabricate all those pixels in their new positions...and then mask them out (wasteful)

Interesting. The gear in the bottom-left (foreground), is huge. So yeah, lot's of pixels being unnecessarily calculated... As that gear does a sort of clock-like ticking motion, I suppose I could Just be drawing a much smaller portion of that gear, calculate the amount of rotation for 1 tooth, and repeat it. Currently it rotates 9degrees on each rotation - a bit arbitrary, and does not line up on each 'tick'. As I am not animating any of the gradients, or strokes, and only have the 1 non-animated clippath, I think I may first try to eliminate as much stuff as possible that exists outside the clippath first. See where that gets me...

 

33 minutes ago, Cassie said:

Yeah, I also wouldn't advise Lottie for perf reasons.

My feeling was this too. I am using Nuxt (Vue) with SSR for this project. As this is the first big image that shows right on the homepage, I loved the idea of an inline SVG here as it could be pre-rendered (showing up fast), and then start moving after the scripts have loaded. I was concerned about having a Lottie animation right at the top as I don't think anything would show until the supporting javascript was loaded.

 

Once again, thank you all for your time. I know this is not a GSAP specific thing, so I really appreciate the input. I think I will start off with minimizing the content outside that clippath. If the performance still seems off (better way to actually measure this?), I will remove some of the extra gradients which give the 'glow' between the gear layers, and check again. If there are still issues, I think I will look at the suggestion of @elegantseagulls and consider breaking out each of those groups into their own svg element, and do some absolute positioning inside a container to try and recreate it that way.

  • Like 2
Link to comment
Share on other sites

48 minutes ago, Cassie said:

(Also SVG elements are hardware accelerated in firefox and chrome now)

Oh, we are living in the future! I didn't realize it was that well supported yet! Sadly, we still have a Safari that takes us through the dark ages....

  • Like 1
Link to comment
Share on other sites

It might sound like a strange question, but why don't you just go for video? with all the effort you put in you surely could render several size videos that shouldn't be too large considering the kind of content you have. if you need some interactivity putting a small number of animated elements on top should visually work fine...

Link to comment
Share on other sites

9 hours ago, GreenSock said:

if you've got things moving outside the mask (invisible), the browser still has to fabricate all those pixels in their new positions...and then mask them out (wasteful)

Hey @GreenSock, I had a follow-up question regarding this - curious if you know the answer. Does the browser only have to fabricate pixels that would  be visible if the mask were not there? To clarify, I am working on slicing some of the gears so that they do not extend so far outside the clippath - and I am struggling to visually animate a precise rotation on the supposed center since the end gear 'piece' after reducing them down to a visible portion might be more of a rectangular bounds.

A possible solution I had was to group the portion of gear with a circle that has the full size - but no fill or stroke. Then, I would rotate that group's center to keep the movement correct. Let me know if that description makes sense or not.

 

7 hours ago, iDad5 said:

but why don't you just go for video?

It's not a bad question. I've thought about this. I want to use some transparency, and still might add some parallax effect. I'm not entirely ready to give up on this quite yet, but a video is a possible alternative.

Link to comment
Share on other sites

1 hour ago, Chuck Taylor said:

Does the browser only have to fabricate pixels that would  be visible if the mask were not there?

I can't say for sure, but I'm pretty sure that isn't the case. It doesn't matter if it's masked or not - either way, it has to fabricate the pixels. 

 

I didn't quite follow your description, but if you're struggling with the "spinning" happening around the wrong point, you can use svgOrigin or transformOrigin to set it wherever you want. Don't feel like you've gotta add artwork in order to make the center stay the center for rotational reasons - just set the origin to be off center as much as you need. 

Link to comment
Share on other sites

Posted (edited)
49 minutes ago, GreenSock said:

but if you're struggling with the "spinning" happening around the wrong point, you can use svgOrigin or transformOrigin

Thanks for the reply. Yes, I was struggling with getting the exact right point for 'spinning' a piece of gear. Figuring out how to supply a precise transformOrigin (outside the piece of gear bounding box, but where the center would have been for a full gear) to make it look right eludes me.

 

Again, thanks for your time and thoughts. I have a couple of very young kids, and this is outside the scope of my regular work hours, so I squeeze these efforts in where I can. If I had all day to keep trying things out I certainly would. So your's and everyone else's thoughts and expertise has been really appreciated.

 

Edited by Chuck Taylor
clarification
Link to comment
Share on other sites

2 hours ago, Chuck Taylor said:

hanks for the reply. Yes, I was struggling with getting the exact right point for 'spinning' a piece of gear. Figuring out how to supply a precise transformOrigin (outside the piece of gear bounding box, but where the center would have been for a full gear) to make it look right eludes me.

One approach to simplify things is to take your ORIGINAL artwork and use .getBBox() on it to get the bounds so you can then calculate the center point in terms of the overall SVG coordinate system, sorta like:

let b = yourSVGElement.getBBox();
let centerX = b.x + b.width / 2;
let centerY = b.y + b.height / 2;

Now that you've got the exact coordinate, you can edit your artwork to delete the non-visible parts. Then when you want to animate from that "center" (which is no longer the center because you deleted parts of that artwork), plug centerX and centerY into the svgOrigin of the tween like svgOrigin: centerX + " " + centerY

 

I hope that helps. Good luck with the project...and kids ;) 

  • Like 1
Link to comment
Share on other sites

@GreenSock, yes that walkthrough makes complete sense! I've never used svgOrigin before (always transform origin), but I found your demo here on codepen.

See the Pen waKrNj by GreenSock (@GreenSock) on CodePen

 

Thank you immensely!

  • Like 2
Link to comment
Share on other sites

I have taken another crack at this. I was hoping someone could give this a run and see how their computer handles it?

Note: It might be necessary to close the codepen I had previously uploaded at the start of this thread so that it is not negatively impacting you before trying out this new one.

 

I have taken @GreenSock's advice, and removed excess shape outside the clipPath are so that it is not being calculated. I then used temporary shapes to get the rotation point, and then removed those elements after I got the numbers I needed. I removed several gradients. They were not being animated, but I did this just in case, and feel that it looks great without the ones I took out. I also removed extra paths that were being used on each gear to imply thickness, and instead am embracing more of a flat design.

 

I'm curious if this did the trick, or if anyone is still seeing issues / their device quickly gets warm?

 

See the Pen qBogWbY by chucktaylor (@chucktaylor) on CodePen

Link to comment
Share on other sites

It never really ran poorly for me, but I'm on a pretty fast Mac. The new one runs fine for me!

Link to comment
Share on other sites

For me it takes around 40% of my CPU (when I closed the codepen browser tab it decreased by that amount) on Safari version 15.5 (17613.2.7.1.8), but it runs very smooth.

 

MacBook Pro (15-inch, 2017), Processor 3,1 GHz Quad-Core Intel Core, Memory 16 GB 2133 MHz LPDDR3, Graphics Radeon Pro 560 GB/Intel HD Graphics 630 1536 MB

Link to comment
Share on other sites

Thank you for taking a quick look! It runs just fine for me (again a fast mac), and runs just fine on my phone. I think I am going to add in some logic to pause and play it depending on whether or not it is in the viewport and clean it up some of the markup a little bit more. Aside from that, and someone commenting that was simply too much for their device to handle, I think I am going to call this done for the time being.

 

Thanks again to everyone for the advice!

  • Like 1
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.
×