如何中断当前CSS动画并触发新动画?Toast场景实现
解决Toast重叠时立即触发退场动画的问题
要实现新Toast创建时旧Toast立即播放退场动画,核心是强制重启旧Toast的退场动画——直接修改animation-delay无效,因为CSS动画一旦启动就不会因属性变化重启,得通过类切换来触发新的动画规则。
修改后的完整代码
CSS 部分
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; /* 默认动画:入场0.3s,2.5s延迟后执行0.5s退场 */ animation: toastin 0.3s forwards, toastout 0.5s 2.5s forwards; } /* 立即退场类:覆盖默认动画,无延迟执行0.4s快速退场 */ .toast.toast-exit-immediately { animation: toastin 0.3s forwards, toastout-quick 0.4s 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); } } /* 快速退场动画(可根据需求调整时长) */ @keyframes toastout-quick { from { opacity: 1; transform: translate(0, 20px); } to { opacity: 0; transform: translate(50vw, 20px); } }
JavaScript 部分
function createToast() { // 处理所有已存在的Toast,触发立即退场 const existingToasts = document.querySelectorAll('.toast'); existingToasts.forEach(toast => { // 清除原有的自动移除定时器,避免冲突 clearTimeout(toast.removeTimer); // 添加立即退场类,触发新动画 toast.classList.add('toast-exit-immediately'); // 监听动画结束事件,完成后移除元素 toast.addEventListener('animationend', function handleEnd() { toast.remove(); toast.removeEventListener('animationend', handleEnd); }); }); // 创建新Toast const elem = document.createElement("div"); elem.classList.add("toast"); elem.innerText = "hello"; document.body.appendChild(elem); // 保存移除定时器,方便后续清除 elem.removeTimer = setTimeout(() => elem.remove(), 3000); } setInterval(createToast, 3000);
关键逻辑说明
- 类切换触发动画:通过新增
.toast-exit-immediately类重写animation属性,替换原有的延迟退场动画为无延迟的快速退场,强制重启动画流程。 - 清除定时器:每个Toast保存自己的移除定时器,创建新Toast时清除旧Toast的定时器,避免动画结束后重复执行移除操作。
- 动画结束后移除:监听
animationend事件确保元素在退场动画完成后才被移除,不会出现直接消失的突兀效果。
内容的提问来源于stack exchange,提问作者Ryan Peschel
相关产品推荐
相关产品推荐

