使用 CSS 动画,如果我们需要再次动画,是否必须删除 class 并重新添加?

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

请查看下面的演示,或在 https://jsfiddle.net/ut7y93hv/

我正在从 Peter、Paul 和 Mary 中随机取一个名字,如果名字与以前不同,则有“模糊”效果,更改名称,然后使其“模糊” (再次变尖锐)。

所以现在我必须做

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

也就是动画完成后去掉class名字。否则,如果我下次只添加 class 名称,就好像什么都没发生一样——它不会再进行动画处理。我也仔细检查过:我不能删除 class 名称然后立即将其添加回去,因为它也好像什么都没有发生一样。

问题是:有没有办法使用 CSS 动画更优雅地做到这一点?不知何故只是告诉动画重新启动自己,而不需要删除 class 并添加 class 回来?当它在 ReactJS 中完成时也很混乱,因为我们还需要做 setTimeout() 来“在幕后”做低级的事情来实现它。

我也许可以让它成为一个不断重复的动画,但是使用 setTimeout() 2 秒后“暂停”,然后下次重新启动它,但如果 [=16] 可能会更糟=] 延迟 16 毫秒或 33 毫秒,然后动画移动越来越多,并且在一段时间后不同步。

需要启动动画然后设置计时器来更改文本也有些混乱。我想我可以先模糊文本,然后使用事件 animationend 更改文本,然后 kickstart 使其再次清晰,然后使用事件 animationend 删除 class,但是这个也有点乱

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>

不,您当时不需要将其删除,您只需在再次打开之前将其删除即可,trigger a reflow 其间:

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>

请注意,您还可以查看 Web Animations API,它提供了以编程方式控制动画的方法。

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>

就像我评论的一样, animation 是指使用一次或连续动画,我们确实有自己的做事风格,但我建议使用 transition 以便在特定事件和时间灵活地设置动画。

由于您的动画设置为 2 秒,因此您可以像这样设置 css 过渡:

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

然后利用 Javascript:

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

每次你想要动画时调用 blur_and_back()

编辑:

基于 developer.mozilla.organimation 的一个组成部分是 animation 是:

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

通过startendfromto0%100%实际上是一次性使用动画,或使用 infinite 使其连续动画化。

他们还补充说:

you can create them without even having to know JavaScript.

同时 transition 再次基于 developer.mozilla.org

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, e.g. linearly or quick at the beginning, slow at the end).

这就是我所说的灵活性。

我想这有点明显,即使是他们的字面英文定义。

不过,我再说一遍,我们确实有自己的做事风格,这只是一个建议。