How to trigger a stylesheet animation on click

Good morning everyone,

I’m experimenting with stylesheets and I’d like to ask what’s the best solution to manage an animation that runs only for a specific amount of time once I click on an icon.

For example, at the moment I’ve managed the rotation of an icon ("material/loop") using this code:

@keyframes spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

.psc-icon-spin {
  animation: spin 3s linear forwards;
}

And to trigger it, when I click on the icon (and execute all the other scripts it normally does), I also set the class like this:

self.props.style.classes = "icon-spin"

The obvious problem is that I don’t know how to reset the class so that I can trigger it again the next time.

I’m pretty sure if you remove the class then re-add it, it will restart the animation. If not you have to modify something to force a redraw.

Yes, if I remove it and add it again, it works, but the problem is that there is no event that could clear it.

I mean, it should happen “automatically” in some way, but right now there’s just a button that can be pressed at any time to refresh it. So I wonder if there’s a way to handle the reset of the property without using something like a delay.

I tried using the onMouseLeave event, and it could work, but of course if the style is being applied at that moment, it stops immediately, which isn’t ideal.

I’m testing this to make it “works” but actually I don’t like it very much.
When I click the icon I save the timestamp click in a custom property of the icon and the I bind the classes property of the icon with this expression structure.

I know that the animation takes 2 second to works and so after 2000ms I clear the class property.

Do you have other suggestion to how improve this kind of job?

import threading

def delayed_function():
    self.props.style.classes = ""

self.props.style.classes = "icon-spin"
# Set the timer
timer = threading.Timer(5.0, delayed_function)
timer.start()

Essentially you make a thread that will be executed in the future that removes the class, and you set the animation to run, then the thread will later remove the class when the thread runs.

The thread is async, so there are a few different ways to deal with the way it runs, but essentially its pretty safe and doesn pause any code.

1 Like

It works very good. I add the check before running the script to optimise it:

`if self.props.style.classes == "":
    import threading
    
    def delayed_function():
        self.props.style.classes = ""
    
    self.props.style.classes = "icon-spin"
    # Set the timer
    timer = threading.Timer(2.0, delayed_function)
    timer.start()`

I think about how to implement it in a general function so to reuse it.

Thanks for your time, I appreciate it.

1 Like

Mark it as a solution if it answers the question, it may help others in the same boat.