如何中断当前的 CSS 动画并开始另一个?

问题描述 投票:0回答:3

我有以下示例代码,它创建从屏幕顶部飞出的吐司,停留几秒钟,然后飞走:

function createToast() {
  const elem = document.createElement("div");
  elem.classList.add("toast");
  elem.innerText = "hello";

  document.body.appendChild(elem);

  setTimeout(() => elem.remove(), 3000);
}

setInterval(createToast, 3000);
body {
  background-color: #d7d7d7;
}

.toast {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 5px 10px;
  max-width: 200px;
  transform: translate(0, 0);
  background-color: #fff;
  border-radius: 50px;

  animation-name: toastin, toastout;
  animation-duration: 0.3s, 0.5s;
  animation-iteration-count: 1, 1;
  animation-delay: 0s, 2.5s;
  animation-fill-mode: forwards, forwards;
}

@keyframes toastin {
  from {
    opacity: 0;
    transform: translate(0, -40px);
  }
  to {
    opacity: 1;
    transform: translate(0, 20px);
  }
}

@keyframes toastout {
  from {
    opacity: 1;
    transform: translate(0, 20px);
  }
  to {
    opacity: 0;
    transform: translate(50vw, 20px);
  }
}
<body><body>

这很好用,但有时在我的应用程序中,会在当前的 toast 消失之前创建另一个 toast。在那种情况下,我希望当前的吐司在新吐司创建后立即飞走,而不是等待 2.5 秒。

对于我的生活,我无法弄清楚这一点。是否可以?看起来很简单,但我尝试的任何东西似乎都没有任何效果。

首先,我尝试抓住现有的 toast 元素并将

animation-delay
设置为
0s
,但这没有效果。然后我尝试用一个全新的动画替换它,尝试使用
!important
等。在所有情况下,吐司就像消失一样,没有动画发生。

有没有办法让 toast 在创建新 toast 时立即在 0.4 秒内完成其当前动画?以便它在与传入的吐司碰撞之前飞走?

javascript css css-animations toast
3个回答
0
投票

你会认为这是可能的,对吧?也许您需要添加一个变量来检查是否显示了吐司。如果正在显示 toast,您可以立即应用 elem.remove() 以仅显示新的 toast。在下面查看是否适合您。

let isToastDisplayed = false;

function createToast() {
  const elem = document.createElement("div");
  elem.classList.add("toast");
  elem.innerText = "hello";

  document.body.appendChild(elem);

  if (isToastDisplayed) {
    const currentToast = document.querySelector(".toast");
    currentToast.remove();
  }

  isToastDisplayed = true;

  setTimeout(() => {
    elem.remove();
    isToastDisplayed = false;
  }, 3000);
}

setInterval(createToast, 3000);
body {
  background-color: #d7d7d7;
}

.toast {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 5px 10px;
  max-width: 200px;
  transform: translate(0, 0);
  background-color: #fff;
  border-radius: 50px;

  animation-name: toastin, toastout;
  animation-duration: 0.3s, 0.5s;
  animation-iteration-count: 1, 1;
  animation-delay: 0s, 2.5s;
  animation-fill-mode: forwards, forwards;
}

@keyframes toastin {
  from {
    opacity: 0;
    transform: translate(0, -40px);
  }
  to {
    opacity: 1;
    transform: translate(0, 20px);
  }
}

@keyframes toastout {
  from {
    opacity: 1;
    transform: translate(0, 20px);
  }
  to {
    opacity: 0;
    transform: translate(50vw, 20px);
  }
}
<body><body>


0
投票

不确定这是否直接回答了你的问题,但你可以将动画分离到一个单独的类中......然后使用 js 你可以检查现有的动画并添加类!

检查一下

function createToast() {
const existing = document.querySelectorAll('.toast')
if(existing.length > 0) {
existing.forEach(e => {
e.classList.add('toast-out')
})
}
  const elem = document.createElement("div");
  elem.classList.add("toast");
  elem.innerText = "hello";

  document.body.appendChild(elem);

  setTimeout(() => elem.remove(), 3000);
}

setInterval(createToast, 2000);
body {
  background-color: #d7d7d7;
}

.toast {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 5px 10px;
  max-width: 200px;
  transform: translate(0, 0);
  background-color: #fff;
  border-radius: 50px;

  animation-name: toastin;
  animation-duration: 0.3s;
  animation-iteration-count: 1;
  animation-delay: 0s;
  animation-fill-mode: forwards;
}

.toast-out {
animation-name: toastout;
  animation-duration: 0.5s;
  animation-iteration-count: 1;
  animation-delay: 0s;
  animation-fill-mode: forwards;
}

@keyframes toastin {
  from {
    opacity: 0;
    transform: translate(0, -40px);
  }
  to {
    opacity: 1;
    transform: translate(0, 20px);
  }
}

@keyframes toastout {
  from {
    opacity: 1;
    transform: translate(0, 20px);
  }
  to {
    opacity: 0;
    transform: translate(50vw, 20px);
  }
}
<body><body>


0
投票

您需要保留对 elem 的引用,并在再次调用该函数时将其删除。也许是这样的:

let activeToast;

function clearToast() {
  if(!activeToast){
     return;
  }
  activeToast.remove();
  activeToast = null;
}

function createToast() {
  clearToast();
  const elem = document.createElement("div");
  elem.classList.add("toast");
  elem.innerText = "hello";
  activeToast = elem;
  document.body.appendChild(elem);

  setTimeout(() => clearToast(), 3000);
}

setInterval(createToast, 3000);

但是如果您想跟踪动画,则可能需要使用一些动画事件。

https://medium.com/front-end-weekly/css-animation-events-in-javascript-d2bfe702636d

© www.soinside.com 2019 - 2024. All rights reserved.