移除 class 添加鼠标悬停和 animationend on mouseout

Remove class added with hover and animationend on mouseout

我已经尝试了 transitionendanimationendtransitionkeyframes 动画结束后更改我的 css。我用这两种变体做了一个例子,它们按预期工作:当 transition 或动画结束时,我可以 toggle a class。悬停时,我启动 transition/animation 并在 JavaScript 中切换 class,它会在 transition/animation 更改后更改 background-color

唯一的区别是,当我执行 mouseout 并且 div 返回到原始状态时,使用 transition 和 transitionend,class 将被删除并且原来 background-color 是可见的。对于 keyframes 动画和 animationend,class 和 background-color 保留,当我执行 mouseout 时也是如此。如何让 animationend 获得与 transition 相同的行为?

var boxTransition = document.getElementById("transition");
var boxAnimation = document.getElementById("animation");

/* add class after transition ends */
boxTransition.addEventListener("transitionend", changeBackground);

/* add class after keyframes animation ends */
boxAnimation.addEventListener("animationend", changeBackground);

function changeBackground() {
  this.classList.toggle("box--end");
}
.box {
  height: 100px;
  margin-bottom: 30px;
  width: 100px;
}

.box--transition {
  background-color: lightcoral;
  transition: width 0.5s ease-in-out;
}

.box--transition:hover {
  width: 300px;
}

.box--animation {
  background-color: lightblue;
}

.box--animation:hover {
  animation: animateWidth 0.5s ease-in-out;
  animation-fill-mode: forwards;
}

.box--end {
  background-color: gray;
}

@keyframes animateWidth {
  from {
    width: 100px;
  }
  to {
    width: 300px;
  }
}
<div id="transition" class="box box--transition"></div>
<div id="animation" class="box box--animation"></div>

你应该注意到动画和过渡是不一样的,因此这里的事件处理有点麻烦。

我将解释他们两人身上发生的事情。

过渡:它只是元素变化的动画部分属性。 例如,它可以是宽度或高度或颜色。通常在 :hover 上分配。 因此,如果用户在转换完成之前将鼠标移出元素,它不会等待动画。

另一方面,

Animation:是一套完整的过渡,不关心用户的mouseout事件,一旦开始,它自己结束。

那么,您可以执行以下操作。当您在 transitionend 上分配切换时,没关系,因为只要用户将鼠标移开,转换就会完成,然后事件就会触发,但是对于动画,您应该明确地处理它们。

我所做的是,(假设用户将鼠标放在元素上几秒钟)在动画结束后添加 class(如 transitionend),然后删除 class一旦用户将鼠标移出元素。

这不完全是你应该做的,但你现在可以知道做什么和什么时候做。

演示:

var boxTransition = document.getElementById("transition");
var boxAnimation = document.getElementById("animation");

/* add class after transition ends */
boxTransition.addEventListener("transitionend", changeBackground);

/* add class after keyframes animation ends */
boxAnimation.addEventListener("animationend", greyOnStart);
boxAnimation.addEventListener("mouseout", revertOnEnd);

function changeBackground() {
  this.classList.toggle("box--end");
}

function greyOnStart(){
  this.classList.add('box--end');
}

function revertOnEnd(){
  this.classList.remove('box--end');
}
.box {
  height: 100px;
  margin-bottom: 30px;
  width: 100px;
}

.box--transition {
  background-color: lightcoral;
  transition: width 0.5s ease-in-out;
}

.box--transition:hover {
  width: 300px;
}

.box--animation {
  background-color: lightblue;
}

.box--animation:hover {
  animation: animateWidth 0.5s ease-in-out;
  animation-fill-mode: forwards;
}

.box--end {
  background-color: gray;
}

@keyframes animateWidth {
  from {
    width: 100px;
  }
  to {
    width: 300px;
  }
}
<div id="transition" class="box box--transition"></div>
<div id="animation" class="box box--animation"></div>

我可以为您看到 2 个选项。 第一个是在 boxAnimation.onMouseOut():

上调用 changeBackground
boxAnimation.addEventListener("mouseout", changeBackground);

这将立即更改背景。 第二个是为 .box--animation 设置没有悬停的动画:

@keyframes animateWidth2 {
  from {
    width: 300px;
  }
  to {
    width: 100px;
  }
}
.box--animation {
  animation: animateWidth2 0.5s ease-in-out;
  animation-fill-mode: forwards;
}

这将像过渡一样工作,但也会在开始时发生。 为防止这种情况从一开始就发生,您可以将 .box--hovered class 添加到 changeBackground() 中的 .box,并将动画添加到 .box--animation.box--hovered 而不仅仅是 .box--animationExample 第二个变体。