Jump to content
Search Community

How to repeat an animation on user input

Matt Moon test
Moderator Tag

Recommended Posts

What I'm after is to give a user the ability to fire off a simple animation in a rapid-fire like manner. If the animation took, say 4 seconds to complete (an svg floating up the screen in a random way), the user should be able fire off fast button clicks 4 or 5 times per second and start a new animation each click. Could this be done? Apologies for the simple question. Just starting out with gs. 

Link to comment
Share on other sites

Hey Matt, and welcome! 

 

This sort of thing is definitely possible! I'm guessing you want to affect a different element each click, correct? In which case your setup could be something like so:

function newAnim(e) {
  // Either create the new target or get it from a list of potential elements depending on your needs.
  // If getting it from a list, you should keep track of how many clicks have occurred.
  var target = document.createElement("div");
  
  // style/add content to target
  
  // append it to our page
  document.body.appendChild(target);
  
  // animate it
  gsap.to(target, {...});
}

button.addEventListener("click", newAnim);

We're happy to help if you run into any snags or this isn't what you're looking to do.

 

Happy tweening.

Link to comment
Share on other sites

Hi, Zach

 

Cool. That looks like it would work. If I have the elements, say 5 of them all ready to use, would I place them in the DOM ready to be fired off? Each button click would keep track of how many clicks, and then fire off each one in sequence. Once the fifth one was fired, the first one is ready to go again, like a revolving door. Is that right?

 

So you get a picture of what I'm doing: I've got an iframe that contains a video player that shows a live stream. I'm placing, say, 5 small svg hearts below the frame so not to reveal them. When the user clicks/taps a button, they'll send one of the hearts up the screen. The app is real time so all users connected will see the hearts any user sends. 

 

Let me know if I have the right idea on how to implement.

Link to comment
Share on other sites

43 minutes ago, Matt Moon said:

If I have the elements, say 5 of them all ready to use, would I place them in the DOM ready to be fired off? Each button click would keep track of how many clicks, and then fire off each one in sequence. Once the fifth one was fired, the first one is ready to go again, like a revolving door. Is that right?

Sounds right :) 

 

43 minutes ago, Matt Moon said:

I've got an iframe that contains a video player that shows a live stream. I'm placing, say, 5 small svg hearts below the frame so not to reveal them. When the user clicks/taps a button, they'll send one of the hearts up the screen. The app is real time so all users connected will see the hearts any user sends. 

That sounds like it could be hard on performance if every user can have up to 5 hearts at a time (using the DOM) and every other user can add hearts as well. To do that well you should probably, every tick from the server, tell the client how many hearts have been sent the last tick and have their browser paint to a canvas that many hearts. Using canvas would be better than DOM. GSAP works great with it :) You'd just do the drawing inside of a gsap.ticker call. 

 

If the total amount of hearts is limited to 5 (i.e. it's not a max of 5 * number of users) then you could use DOM elements without a worry about performance.

Link to comment
Share on other sites

Quote

To do that well you should probably, every tick from the server, tell the client how many hearts have been sent the last tick and have their browser paint to a canvas that many hearts.

Not sure I follow. Every tick from the server would be one heart. Can you clarify? But I think you're right, I was only thinking about server load, which would be OK. The server could handle it. But the client-side load on each CPU. Yeah, especially on mobile. 

 

I've never used Canvas. I'm assuming you mean the html element <canvas>. I'll have to get up to speed. 

 

One other question. How do I reset a gsap animation where once it's finished, it resets to its original position? If I have 

gsap.to('.a', {duration: 2.5, physics2D: {velocity: 500, angle: -60, acceleration: 100, accelerationAngle: 180}});

and then fire it off again, it picks up where it left off. 

Link to comment
Share on other sites

8 hours ago, Matt Moon said:

Not sure I follow

When I said, "tick" I meant update from the server (related to the hearts). I assume you won't send an individual message/package ("tick") for each heart because if there's a lot of people on the same stream all sending hearts that'd be a lot of individual message/packages. You should just every n amount of time send all the hearts since the last message/packet. 

 

8 hours ago, Matt Moon said:

I'm assuming you mean the html element <canvas>

Yep. It's definitely better for lots of things on a page at once. 

 

8 hours ago, Matt Moon said:

How do I reset a gsap animation where once it's finished, it resets to its original position?

If you want to clear the values, save use gsap.set(".a", {clearProps: "all"});. If you want to restart the exact same animation, just add a repeat value (like gsap.to('.a', {duration: 2.5, repeat: 3, physics2D: {velocity: 500, angle: -60, acceleration: 100, accelerationAngle: 180}}); or save it to a tween and later call tween.restart()). If you want the same animation with different value (like if you were using a function as a value) then you can use repeatRefresh: true. How do you want it to repeat?

Link to comment
Share on other sites

I'm looking for it to repeat when it's called again. I tried using gsap.set('.a', {clearProps: 'all'}), but it doesn't animate again on the button click. 

 

When the button is clicked it's calling a function: 

 

function fireHearts() {
  count = count + 1;
  let tl = gsap.timeline();
  if (count === 5) {
    count = 1;
  }

  if (count === 1 && windowWidth > 1000) {
    tl.fromTo('.b', {
      duration: 3.5,
      opacity: 1,
      physics2D: {velocity: 600, angle: -92, gravity: 300}
    }, {duration: 3.5, opacity: 0, physics2D: {velocity: 600, angle: -92, gravity: 300}});

When the count gets back to 1, it should animate the '.b' element again from its starting point. 

 

I tried using a callback to call a function that set it to .progress(0), then pause(0), but that didn't work either. 

 

Link to comment
Share on other sites

57 minutes ago, Matt Moon said:

As far as overwhelming the client with a lot of potential hearts at one time, I could try to do what Facebook does. They don't allow any rapid firing. they throttle that ability to about 1 per second. 

Even still, if you have 100k viewers and 10k like around the same time, that's an overwhelming amount of new messages. Gotta think about the best way to do things :) 

 

A few questions about your code:

  • Do you have multiple elements with the ".b" class? or are you animating the same element 5 different times (in the first 5 cases)?
  • It looks like the same animation happens every time - is that true? If so, you should probably just create a timeline at the start for the element(s) that you have and repeat it when necessary.
  • Why are you using a timeline for just one tween?
  • Is it okay if some elements are skipped initially? Theoretically the user could have their window width be less than 1000, fire the function a few times, then make it bigger and the count wouldn't be 1 to start.

It would be very helpful if you had a minimal demo of this so we could help out with the actual code setup instead of this abstract layer of discussion :) 

  • Like 1
Link to comment
Share on other sites

Quote

Even still, if you have 100k viewers and 10k like around the same time, that's an overwhelming amount of new messages. Gotta think about the best way to do things :)

Oh man I wish. The app I'm building is for a small business. I've been directly handling their live streams for the last 7 years and the most viewers I've seen at once is 62. Average in the 30s. With 100k viewers this animation would need to be handled on the broadcast side. 

 

Quote

Do you have multiple elements with the ".b" class? or are you animating the same element 5 different times (in the first 5 cases)?

Right now I'm just experimenting with 4 svg elements, with classes '.a', '.b', '.c', '.d'. Clicking once fires '.a', click again fires '.b', etc. 

 

Quote

It looks like the same animation happens every time - is that true? If so, you should probably just create a timeline at the start for the element(s) that you have and repeat it when necessary.

Apologies for my code above. The function above does look like that, but there's more to that function and has more conditions that start a different animation for each click. When the counter reaches 5, it resets to 1 to animate them again. Tries to anyway.

 

Quote

Why are you using a timeline for just one tween?

Looking through the docs to find a way to 'reset' the animation back to 0 so it would be ready to be used again, I had thought that a timeline was needed. Obviously my ignorance is in plain sight here. I had found a number of the methods that are used like pause(), progress(), etc. I tried them but couldn't get things to work the way I was expecting. 

 

Quote

Is it okay if some elements are skipped initially? Theoretically the user could have their window width be less than 1000, fire the function a few times, then make it bigger and the count wouldn't be 1 to start.

Yes, a user could do that, and it would throw the sequence off. Not sure if that would be detrimental or not. Probably harmless.

 

I was working on getting a simple Codepen up with React and gsap. I used the set up pen you guys have that loads all the plugins etc and is ready to go. I got everything to render OK, but nothing would animate. It was getting late last night, and bailed. I'll try it again when I have time. 

 

Thanks again for the time you put in to user posts. 

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...