如何在元素不再悬停后制作 CSS 动画?

How to make a CSS animation last after an element is no longer hovered?

我的 CSS3 动画有问题。 我有一个 class 帮我制作 SVG 动画,这个 class 的名字是 'animateCircle'.

我希望当我将鼠标悬停在“输入”上时触发动画。

我创建了以下代码:

jQuery('form.newsletter input[type="submit"]').hover(function() {


    jQuery('svg').addClass('animateCircle')

})

问题是如果我将光标从“输入”元素上移开,动画会突然停止。

理想情况下,我希望动画结束(持续 2 秒)然后 class(触发动画)自行删除。我试图设置一个 setTimeOut,但问题仍然存在:当光标不再位于“输入”上时,动画突然被删除。

如果有人有任何想法,将不胜感激!

首先确保 CSS 中的动画 属性 没有设置为无限 运行。然后你需要添加一个事件监听器来等待动画结束移除class。类似于:

jQuery('form.newsletter input[type="submit"]').hover(function() {
    jQuery('svg').addClass('animateCircle')
})

$("svg").on("animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd", function() {
    $(this).removeClass('animateCircle')
})

您必须有一些代码未在问题中显示,以删除鼠标移出时的 class;使用给定的代码,动画不会停止。

可以使用 setTimeout 将其删除,如下所示:

jQuery('form.newsletter input[type="submit"]').hover(function() {
    jQuery('svg').addClass('animateCircle');
    window.setTimeout(() => {
        jQuery('svg').removeClass('animateCircle')
    },2000);
})

那行得通,或者足够接近——但这意味着您必须定义两次持续时间:一次在 CSS 中,一次在 javascript 中。很容易在没有意识到的情况下不小心打破它。 (这也意味着如果用户在动画期间多次将元素悬停在元素上,您可以轻松地同时叠加很多 setTimeouts。在这种特殊情况下,removeClass 触发次数超过预期是无害的,但这不一定如果你正在做一些具有累积效应的事情就是这种情况。而且,不必要地触发事件并不是真正的好习惯。)

下面是一个示例,说明如何在动画完成时专门删除 class,以便下次悬停输入时可以再次触发它:

// add the class on hover:
jQuery('button').hover(function() {
  jQuery('.animate').addClass('animateCircle')
})

// automatically remove the class when the animation ends:
jQuery('.animate').on('animationend', function() {
  jQuery(this).removeClass('animateCircle')
})
@keyframes example {
  0% {
    tranform: rotate(0deg)
  }
  100% {
    transform: rotate(360deg)
  }
}

.animate {
  width: 100px;
  height: 100px;
  background-color: red;
}

.animate.animateCircle {
  background-color: blue; /* <-- so you can see when the class is active */
  animation-name: example;
  animation-duration: 2s;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<button>Hover me</button>


<div class="animate">Animation</div>

(我稍微修改了你的 html 以使其更容易演示,但应该很容易看出如何将其应用到你的 html。)

为了完整起见(因为现在是 2021 年),以下是原版 Javascript,而不是 jQuery。

此方法将两个 EventListeners 附加到要设置动画的元素:

  • mouseover 添加启动动画的 class
  • animationend 删除启动动画的 class

工作示例:

const square = document.getElementsByClassName('square')[0];

const addAnimateSquare = (e) => {
  e.target.classList.add('animateSquare');
}

const removeAnimateSquare = (e) => {
  e.target.classList.remove('animateSquare');
}

square.addEventListener('mouseover', addAnimateSquare, false);
square.addEventListener('animationend', removeAnimateSquare, false);
div {
  width: 100px;
  height: 100px;
  line-height: 100px;
  text-align: center;
  color: rgb(255, 255, 255);
  background-color: rgb(255, 0, 0);
  cursor: pointer;
}

div.animateSquare {
  animation: rotateSquare 2s linear;
}

@keyframes rotateSquare {
  100% {transform: rotate(1080deg);}
}
<div class="square">Hover me</div>


进一步说明:

请注意,为了清楚起见,上面的 javascript 故意冗长。

行数:

const addAnimateSquare = (e) => {
  e.target.classList.add('animateSquare');
}

const removeAnimateSquare = (e) => {
  e.target.classList.remove('animateSquare');
}

square.addEventListener('mouseover', addAnimateSquare, false);
square.addEventListener('animationend', removeAnimateSquare, false);

可以直接改写为:

square.addEventListener('mouseover', (e) => e.target.classList.add('animateSquare'));
square.addEventListener('animationend', (e) => e.target.classList.remove('animateSquare'));