Jump to content
Search Community

Sometimes animations freeze mid-way

jrhager84 test
Moderator Tag

Recommended Posts

I'm not sure if I'm doing something wrong, but my CodePen version of this works perfectly, but when I implement it into my WordPress installation, it seems to 'pause' half-way through animations about 50% of the time.

Essentially, I have data-attributes on elements for both animation type, as well as whether or not to grab and animated child components. Here is the code. Maybe I'm doing something wrong?

The site I'm working on that has the issues is https://yourgalfriday.nyc

 

document.addEventListener("DOMContentLoaded", function() 
{
  const elements = document.querySelectorAll('[data-animationtype]');

  const observer = new IntersectionObserver((entries) => {
      entries.forEach((entry) => {
          if (entry.intersectionRatio > 0) {
              animator(entry.target);
          }
      });
  });
  elements.forEach((el) => {
      observer.observe(el);
  },
	{
		threshold: 1
	});

  function animator(element) {
      var targets = [];
      var animation = element.dataset.animationtype;
      if (element.dataset.animatechildren != undefined) {
          [].forEach.call(element.children, (el) => {
              if ((el.dataset.animationtype = "")) {
                  el.dataset.animationtype = animation;
              }
              targets.push(el);
          });
      } else {
          targets = element;
      }

      // Where we dispatch animations
      var timeLine = gsap.timeline();
      switch (animation) {
          case "slide-up":
              {
                  timeLine.from(targets, {
                      opacity: 0,
                      y: "5vh",
                      duration: 0.5,
                      stagger: 0.12
                  });
              }
              break;

          case "slide-left":
              {
                  timeLine.from(targets, {
                      opacity: 0,
                      x: "10vw",
                      duration: 0.5,
                      stagger: 0.1
                  });
              }
              break;

          case "slide-right":
              {
                  timeLine.from(targets, {
                      opacity: 0,
                      x: "-10vw",
                      duration: 0.5,
                      stagger: 0.1
                  });
              }
              break;
      }
  }
});

 

See the Pen vYNevpy?editors=1010 by jrhager84 (@jrhager84) on CodePen

Link to comment
Share on other sites

Kinda tough to diagnose a live site.

 

I'd say if it's working perfectly in the Codepen demo, but not in your actual site, that would tell me it's probably not GSAP related. Seems like something in your WordPress development to me, but I'm not much of a WP expert.

 

Depending on your project deadline, you may want to wait for the new GreenSock scroll triggering plugin. It will make this type of animation much easier. Unfortunately it won't be available for around a month (or so). No definite release date yet. 

  • Like 2
Link to comment
Share on other sites

10 minutes ago, PointC said:

Kinda tough to diagnose a live site.

 

I'd say if it's working perfectly in the Codepen demo, but not in your actual site, that would tell me it's probably not GSAP related. Seems like something in your WordPress development to me, but I'm not much of a WP expert.

 

Depending on your project deadline, you may want to wait for the new GreenSock scroll triggering plugin. It will make this type of animation much easier. Unfortunately it won't be available for around a month (or so). No definite release date yet. 

The crazy part is there are *no* errors. So it really doesn't make sense. All of the animations are triggering, it's just sometimes the start/end values are left at some mid-point.

Link to comment
Share on other sites

I must be doing something wrong. After expanding all of the collapsed <div>s in the dev tools, I've come to find out that certain elements are animating simultaneously while each one is in/out of frame. They should be being observed separately. I just don't know where my mistake is. 😕

Link to comment
Share on other sites

Perhaps it's due to the fact that you're using from() tweens and you're interrupting them. Remember, from() tweens use the CURRENT values as the destination ones. So, for example, if you've got obj.x at 0 and you do a gsap.from(obj, {x:100, ease:"none"}) it'll start animating down from 100 to 0, but then if halfway through that tween you create another gsap.from(obj, {x:100}), that'll animate from 100 to 50!! (not 0). It's a logic thing, not a GSAP bug. 

 

Just always watch out for those logic issues when using from() animations. You might want to use a fromTo() so that you can control both the start and end values. 

  • Like 1
Link to comment
Share on other sites

1 minute ago, GreenSock said:

Perhaps it's due to the fact that you're using from() tweens and you're interrupting them. Remember, from() tweens use the CURRENT values as the destination ones. So, for example, if you've got obj.x at 0 and you do a gsap.from(obj, {x:100, ease:"none"}) it'll start animating down from 100 to 0, but then if halfway through that tween you create another gsap.from(obj, {x:100}), that'll animate from 100 to 50!! (not 0). It's a logic thing, not a GSAP bug. 

 

Just always watch out for those logic issues when using from() animations. You might want to use a fromTo() so that you can control both the start and end values. 

That's what I was thinking. If I specify the to() being 0,0 essentially, it shouldn't affect the end position, and should clear this up, yes? I appreciate it. I'm trying to learn  more about conditional from and to objects, so I can build a helper function that assembles any given animation based on some values, making my little mini-engine very extensible and robust.

Re: your solution -- That's what I was thinking after some research. I appreciate the help! :)

Link to comment
Share on other sites

I forgot to add: I was trying to workshop a way to 'hide' the sliding animations without setting their default opacity to 0, so that way if for whatever reason GSAP didn't load or there was an issue, it wouldn't essentially be a blank page. Are there any links to resources that would aide me in achieving that effect? I wanted the animations to happen farther up the screen, but with opacity 1 and default position, they 'pop' out of existence and then animate in, which is not a very desirable effect. hahaha

Here's my updated code. If anybody has a free moment to criticize it for efficiency/errors, I'd be greatly appreciative. No worries otherwise. :)

 

document.addEventListener("DOMContentLoaded", function() 
{
  const elements = document.querySelectorAll('[data-animationtype]');
  
  const animationObj = 
	{
  	slideUp: 
    {
      opacity: 0,
      y: "5vh",
      stagger: 0.12
    },
    slideLeft:
    {
    	opacity: 0,
      x: "10vw",
      stagger: 0.1
  	},
    slideRight:
    {
      opacity: 0,
      x: "-10vw",
      stagger: 0.1
    },
    opacity:
    {
      opacity: 0
    },
    originalPos:
    {
      opacity: 1,
      x: 0,
      y: 0,
      duration: 0.5
    }
  }

  const observer = new IntersectionObserver((entries) => {
      entries.forEach((entry) => {
          if (entry.intersectionRatio > 0) {
              animator(entry.target);
          }
      });
  });
  elements.forEach((el) => {
      observer.observe(el);
  });

  function animator(element) {
      var targets = [];
      var animation = element.dataset.animationtype;
      if (element.dataset.animatechildren == "true") {
        console.log("Children true");
          [].forEach.call(element.children, (el) => {
              if ((el.dataset.animationtype == "")) {
                  el.dataset.animationtype = animation;
              }
              targets.push(el);
          });
      } 
    	else 
      {
          targets = element;
      }

    	console.log(targets);
      // Where we dispatch animations
      var timeLine = gsap.timeline();
      switch (animation) 
      {
          case "slide-up":
          {
              timeLine.fromTo(targets, animationObj.slideUp, animationObj.originalPos);
          }
          break;

          case "slide-left":
          {
              timeLine.from(targets, animationObj.slideLeft, animationObj.originalPos);
          }
          break;

          case "slide-right":
          {
              timeLine.from(targets, animationObj.slideRight, animationObj.originalPos);
          }
          break;
      }
  }
});

 

Link to comment
Share on other sites

I didn't have time to comb through it all, but I did notice a few things:

  1. You only changed the first tween to a fromTo(). The others are still just from(), so that code is definitely wrong.
  2. You've got "stagger" defined in the "from" vars object, but any special properties like stagger, duration, ease, delay, etc. go in the "to" vars object, not the "from". 

There's nothing wrong with this, but I noticed you're using [].forEach.call(element.children...) but did you know that GSAP has a utility that'll convert stuff to a real Array, so you could do gsap.utils.toArray(element.children).forEach(...) instead if you'd like. 

 

As for making things not be transparent initially just in case GSAP doesn't load, my personal opinion is that's not a very common concern and you may be causing yourself more trouble than it's worth. Most web apps these days won't function without JS and I assume that your users will have a poor experience anyway if GSAP doesn't load. Doesn't seem like a common problem at all. I mean stuff either needs to be transparent initially (and nicely fade in) or it won't be transparent initially...and then it'll suddenly jump to transparent and fade in. If you really want to have your cake and eat it too, you'd probably have to set things to transparent initially and apply CSS transitions with a delay that'd fade them in...and then use JS to REMOVE those transitions when you know that GSAP has loaded. You're introducing more complexity and delay with that, but it'll make it more bulletproof if you're really concerned that JS isn't gonna load. 

 

Good luck!

  • Like 1
Link to comment
Share on other sites

45 minutes ago, GreenSock said:

I didn't have time to comb through it all, but I did notice a few things:

  1. You only changed the first tween to a fromTo(). The others are still just from(), so that code is definitely wrong.
  2. You've got "stagger" defined in the "from" vars object, but any special properties like stagger, duration, ease, delay, etc. go in the "to" vars object, not the "from". 

There's nothing wrong with this, but I noticed you're using [].forEach.call(element.children...) but did you know that GSAP has a utility that'll convert stuff to a real Array, so you could do gsap.utils.toArray(element.children).forEach(...) instead if you'd like. 

 

As for making things not be transparent initially just in case GSAP doesn't load, my personal opinion is that's not a very common concern and you may be causing yourself more trouble than it's worth. Most web apps these days won't function without JS and I assume that your users will have a poor experience anyway if GSAP doesn't load. Doesn't seem like a common problem at all. I mean stuff either needs to be transparent initially (and nicely fade in) or it won't be transparent initially...and then it'll suddenly jump to transparent and fade in. If you really want to have your cake and eat it too, you'd probably have to set things to transparent initially and apply CSS transitions with a delay that'd fade them in...and then use JS to REMOVE those transitions when you know that GSAP has loaded. You're introducing more complexity and delay with that, but it'll make it more bulletproof if you're really concerned that JS isn't gonna load. 

 

Good luck!

I totally understand about 'assuming' GSAP loads because of the rarity. I may scrap that part, but my idea was just to iterate over the elements from the gsap/IntersectionObserver array and set their opacity to 0 on DOMContentLoaded so they're opacity one unless the GSAP/IntersectionObserver logic fires. Then, it'll set their states before a FOUC, but if for some reason GSAP/IO logic fails, they'll still be opaque. If that makes sense. 

I think I copied it from a different source, as I definitely changed them all to fromTo(). Somewhere else I was told to use [].forEach, so I can easily just change that out for more conformity. I moved the stagger, so I think I copied prematurely or got mixed up. Ugh. I'm a dingus.

 

Thanks again for all the help!

Link to comment
Share on other sites

I wouldn't worry about gsap not loading as that's just 1 of like 20 scripts you have on your page.

 

image.thumb.png.ae6bdfce4c00ea43a6fa762a974b1ed7.png

 

38 minutes ago, jrhager84 said:

I may scrap that part, but my idea was just to iterate over the elements from the gsap/IntersectionObserver array and set their opacity to 0 on DOMContentLoaded so they're opacity one unless the GSAP/IntersectionObserver logic fires. Then, it'll set their states before a FOUC, but if for some reason GSAP/IO logic fails, they'll still be opaque. If that makes sense. 

 

I'm pretty sure that will show FOUC. Setting the opacity to 0 after the dom has loaded is too late. You might not notice if all your scripts have been cached, but on a first time visit, it will most likely flash.

 

 

  • Like 2
Link to comment
Share on other sites

29 minutes ago, OSUblake said:

I wouldn't worry about gsap not loading as that's just 1 of like 20 scripts you have on your page.

 

image.thumb.png.ae6bdfce4c00ea43a6fa762a974b1ed7.png

 

 

I'm pretty sure that will show FOUC. Setting the opacity to 0 after the dom has loaded is too late. You might not notice if all your scripts have been cached, but on a first time visit, it will most likely flash.

 

 

I'm going to be going through and taking away all of the bloated js calls *after* I create the actual content. That's just standard whatever loads with WP/X Theme. I'm sure there's *crazy* redundancy, and I don't even have slider Revolution/The Grid on the page right now, so the 800 calls to those will go away as well. :)

  • 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.
×
×
  • Create New...