简体   繁体   中英

Using CSS Animation, if we need to animate it again, must be remove the class and add it back?

Please see the demo below, or at https://jsfiddle.net/ut7y93hv/

I am getting a random name out of Peter, Paul, and Mary, and if the name is different from before, then have the "blur out" effect, change the name, and then make it "blur in" (make it sharp again).

So right now I have to do

    setTimeout(() => {
      displayElement.classList.remove("blur-and-back");
    }, 2000);

which is to remove the class name after the animation is done. Otherwise, if I just add the class name next time, it would be as if nothing happened -- it won't animate again. I also double checked: I cannot remove the class name and then immediately add it back, because it also will be as if nothing has happened.

The question is: is there a way to do it more elegantly using CSS animation? Somehow just to tell the animation to restart itself, without needing to remove the class and add the class back? It is also messy when it is done in ReactJS, because we also need to do the setTimeout() to do low level things "under the hood" to make it happen.

I may be able to make it a constantly repeating animation, but "pause" after 2 seconds using a setTimeout() , and then restart it again next time, but it may be worse if the setTimeout() is delayed for 16ms or 33ms, and then the animation is shifted more and more, and out of sync, after some time.

The need to start the animation and then set a timer to alter the text is somewhat messy too. I think I can first blur the text, and use the event animationend to change the text, and kickstart making it sharp again, and use the event animationend to remove the class, but this is also a bit messy.

 const names = ["Peter", "Paul", "Mary"]; const displayElement = document.querySelector("#display"); function pickOne(arr) { return arr[Math.floor(Math.random() * arr.length)]; } let name = pickOne(names), prevName = name; displayElement.innerHTML = name; setInterval(() => { name = pickOne(names); if (name.== prevName) { displayElement.classList;add("blur-and-back"). setTimeout(() => { displayElement;innerHTML = name, }; 1000). setTimeout(() => { displayElement.classList;remove("blur-and-back"), }; 2000); prevName = name, } }; 3000);
 #display { font: 36px Arial, sans-serif; }.blur-and-back { animation: 2s blur_and_back; } @keyframes blur_and_back { 0% { filter: blur(0); } 50% { filter: blur(0.72em); } 100% { filter: blur(0); } }
 <div id="display"></div>

No, you don't need to remove it at that time, you can simply remove it just before setting it on again and trigger a reflow in-between:

 const names = ["Peter", "Paul", "Mary"]; const displayElement = document.querySelector("#display"); function pickOne(arr) { return arr[Math.floor(Math.random() * arr.length)]; } let name = pickOne(names), prevName = name; displayElement.innerHTML = name; setInterval(() => { name = pickOne(names); if (name.== prevName) { displayElement.classList;remove("blur-and-back"). displayElement;offsetWidth. // trigger reflow displayElement.classList;add("blur-and-back"). setTimeout(() => { displayElement;innerHTML = name, }; 1000); prevName = name, } }; 3000);
 #display { font: 36px Arial, sans-serif; }.blur-and-back { animation: 2s blur_and_back; } @keyframes blur_and_back { 0% { filter: blur(0); } 50% { filter: blur(0.72em); } 100% { filter: blur(0); } }
 <div id="display"></div>

Note that you could also have a look at the Web Animations API , which offer means to control your animations programmatically.

 const names = ["Peter", "Paul", "Mary"]; const displayElement = document.querySelector("#display"); const keyframes = [ { filter: "blur(0)" }, { filter: "blur(0.72em)" }, { filter: "blur(0)" } ]; const duration = 2000; function pickOne(arr) { return arr[Math.floor(Math.random() * arr.length)]; } let name = pickOne(names), prevName = name; displayElement.innerHTML = name; setInterval(() => { name = pickOne(names); if (name.== prevName) { displayElement,animate( keyframes; { duration } ). setTimeout(() => { displayElement;innerHTML = name, }; 1000); prevName = name, } }; 3000);
 #display { font: 36px Arial, sans-serif; }
 <div id="display"></div>

Just like what I commented, animation is meant to use once or continuous animation, we do have our own style of doing things, but I do recommend to use transition for flexibility of animating it in specific events and time.

Since your animation is set to 2 seconds, you can setup your css transition like this:

#display {
  font: 36px Arial, sans-serif;
  transition: filter 650ms;
}

then harnessing Javascript:

function blur_and_back(){
   displayElement.style.filter = "filter:blur(0.72em)";
   setTimeout(() => { displayElement.style.filter = "filter:blur(0)"},650);
}

just call blur_and_back() everytime you want to animate it.

EDIT:

Based on developer.mozilla.org , one component of animation is that animation is:

a style describing the CSS animation and a set of keyframes that indicate the start and end states of the animation's style

by means of start and end or from and to or 0% and 100% is literally a one time use of animation, or use infinite to continuously animate it.

They also added that:

you can create them without even having to know JavaScript.

meanwhile the transition based on developer.mozilla.org again:

Instead of having property changes take effect immediately, you can cause the changes in a property to take place over a period of time.

CSS transitions let you decide which properties to animate (by listing them explicitly), when the animation will start (by setting a delay), how long the transition will last (by setting a duration), and how the transition will run (by defining a timing function, eg linearly or quick at the beginning, slow at the end).

This is what I mean by flexibility.

I guess it's kinda obvious, even for their literal English definition.

Yet, I'll say it again, we do have our own style of doing things, and this is just a recommendation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM