Share Posted October 18, 2016 Hi, Has anyone come across this before where an svg element that's been animated with CSS animation and has the animation-fill-mode: forwards applied to it means that GSAP can't animate that element's property? What I'm trying to achieve is an animated preloader that animates in via css animation, so that it's lightweight and GSAP doesn't have to load in the document head, but when the app fully loads GSAP is used to animate it out with a more complex animation. However… In the codepen example used, the marker is initially positioned outside it's native svg position, then after 0.5 sec it animates back to its native position. However to get the marker to remain in that position at the end of the animation it requires 'animation-fill-mode: forwards' otherwise it jumps back down. I've added a basic GSAP tween to simulate a window.load function by just adding a 2 second delay, to animate it up after the css animation has finished, but it doesn't animate due to this css property being added. You can see the console is logging out at the end of the 'non moving' GSAP animation. Any ideas folks? Or do I deserve a banana award today for being dim? I am very tired today Cheers, Pete. See the Pen 3ca350a215a9b7254201d6e17dadad9e by petebarr (@petebarr) on CodePen Link to post Share on other sites
Share Posted October 18, 2016 I think that's how it supposed to work. Forwards keeps whatever value it animated on there. If you look at the computed properties in the console, you'll see that it's still running. But what I'm wondering about is the reason for your lightweight approach. How much time passes between the head and the closing body tag? Or is this a hunch? Loading libraries from a CDN will cache a version on the user's browser, so that can improve your load time. And have you looked into using a service worker to hydrate your app. Google's sw-precache module is pretty popular. https://github.com/GoogleChrome/sw-precache 2 Link to post Share on other sites
Solution Share Posted October 18, 2016 Hello Pete Barr, If it was me doing this i would have a separate class for your CSS animation with the animation-fill-mode. And then either have that class on the element when the animation completes using the animationend event handler. Then when that CSS animation is complete, you remove the class with that CSS animation. Then just animate with GSAP as usual. See the Pen QKkQrK by jonathan (@jonathan) on CodePen The JS: var loaderTl = new TimelineMax(), element = document.querySelector(".marker"); // listen for CSS animationend event handler element.addEventListener("animationend", gsapAnimation, false); function gsapAnimation() { console.log('CSS animation complete'); // remove CSS animation class element.classList.remove("css-anim"); // run GSAPJS animation loaderTl.to('.marker', 1, { y: -100, delay: 2, onComplete: function() { console.log('GSAPJS animation complete') } }); } Your SVG DOM element has an extra class css-anim solely for the CSS animation: <circle class="marker css-anim" cx="163" cy="163" r="23" fill="#d60d0d"/> And the CSS targeting only .marker.css-anim so when .css-anim is removed any CSS animation will no longer be associated due to the class only being .marker and not .marker.css-anim .marker.css-anim { animation: markerAnim 0.5s 0.5s cubic-bezier(0.120, 0.900, 0.280, 1.175); transform-origin: center center; animation-fill-mode: forwards; transform: translateY(100px); } You want to be careful about mixing CSS animation with GSAP since both will be competing to animate the same element.. like a tug of war. But if it was me i would do it all with GSAP. Resources: animationend: https://developer.mozilla.org/en-US/docs/Web/Events/animationend 2 Link to post Share on other sites
Author Share Posted October 18, 2016 I think that's how it supposed to work. Forwards keeps whatever value it animated on there. If you look at the computed properties in the console, you'll see that it's still running. But what I'm wondering about is the reason for your lightweight approach. How much time passes between the head and the closing body tag? Or is this a hunch? Loading libraries from a CDN will cache a version on the user's browser, so that can improve your load time. And have you looked into using a service worker to hydrate your app. Google's sw-precache module is pretty popular. https://github.com/GoogleChrome/sw-precache The lightweight approach was so that I have skinny code in the head for the preloader animation allowing it to animate while waiting for the window load which would include custom js, tweenmax, and any other libraries we are going to use before the closing body. To be honest I haven't a scooby about service workers Link to post Share on other sites
Author Share Posted October 18, 2016 Cheers Jonathan, that's exactly what I should have done. Doh! I was kinda holding out for a simple css solution. Anyway, I've already binned that CSS animation idea and am just going with straight up GSAP. My eye was starting to twitch. Long live the king! 3 Link to post Share on other sites
Share Posted October 18, 2016 Great solution, Jonathan! Pete, a general rule of thumb is to avoid mixing any CSS animations / transitions with GSAP as they will most likely be competing for control over the same properties. 1 Link to post Share on other sites