CSS3动画:在:hover状态下触发整个动画。

41

我创建了一个简单的反弹动画,将其应用于元素的:hover状态:

@keyframes bounce {
    0% {
      top: 0;
      animation-timing-function: ease-out;
    }
    17% {
      top: 15px;
      animation-timing-function: ease-in;
    }
    34% {
      top: 0;
      animation-timing-function: ease-out;
    }
    51% {
      top: 8px;
      animation-timing-function: ease-in;
    }
    68% {
      top: 0px;
      animation-timing-function: ease-out;
    }
    85% {
      top: 3px;
      animation-timing-function: ease-in;
    }
    100% {
      top: 0;
    }
}

.box:hover { 
    animation: bounce 1s;
}
动画效果很棒,唯一的问题是当鼠标离开元素时它会突然停止。是否有办法强制其继续执行预设的迭代次数,即使鼠标已经退出?基本上我在这里寻找的是通过:hover状态触发的动画效果,而不是javascript解决方案。我没有看到规范中任何可以实现这一点的方法,但也许我错过了一个显而易见的解决方案?
这里有一个可供尝试的示例:http://jsfiddle.net/dwick/vFtfF/
7个回答

38

很抱歉,唯一解决这个问题的方法是使用一些 JavaScript,您需要将动画作为类添加,然后在动画完成时将其删除。

$(".box").bind("webkitAnimationEnd mozAnimationEnd animationend", function(){
  $(this).removeClass("animated")  
})

$(".box").hover(function(){
  $(this).addClass("animated");        
})

http://jsfiddle.net/u7vXT/


本来希望避免使用JavaScript,但我发现这是唯一的方式。 - David Wick
1
动画结束事件的通用名称应全部小写:animationend - jackocnr

8
我在JsFiddle上创建了一个示例,使用纯JavaScript编写,链接指向同一篇帖子https://dev59.com/M2sz5IYBdhLWcg3wv6fu#7697786。如果有人想使用,可以参考此示例。
const elements = document.getElementsByClassName('box');

for (let i = 0; i <= elements.length; i++) {
  elements[i].addEventListener('animationend', function(e) {
    elements[i].classList.remove('animated');
  });

 elements[i].addEventListener('mouseover', function(e) {
   elements[i].classList.add('animated')
 })
}

4

和 @methodofaction 给出的答案一样,但是针对使用 React 的任何人:

import React, { useState } from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';

export default function Icon({ icon }) {
    const [animated, setAnimated] = useState(false);

    return (
        <div
            onMouseEnter={() => setAnimated(() => true)}
            onAnimationEnd={() => setAnimated(() => false)}
        >
            <FontAwesomeIcon icon={icon} className={animated ? 'animated' : ''} />
        </div>
    );
}

3

这种方法并不能在所有情况下都奏效,而且不做出一些妥协是无法为 OP 解决问题的,但我通过在 :not(:hover) 选择器中添加动画来解决了这个问题:

@keyframes stopBounce {
    0% {
         top: 15px;
    }
    100% {
        top: 0px;
    }
}

@keyframes bounce {
    ops: bounce code
}


.box{
    top: 0px;
    transition: top 250ms 1000ms ease-in-out,
}
.box:hover{
    animation-name: bounce;
    animation-fill-mode: both;
    animation-duration: 250ms;
}
.box:not(:hover){
    animation-name: stopBounce;
    animation-duration: 250ms;
    animation-delay: 1000ms;
    animation-fill-mode: both;
}

所以,这并不能让动画一直播放下去。据我所知,这是一个纯CSS解决方案无法实现的。它所做的是让动画平滑地过渡回其起始位置。诀窍在于有两个选择器,任何时候只能有一个选择器是活动的。
这使我们能够在用户悬停时播放动画,并在用户停止悬停时播放单独的动画。由于这两个动画都可以被控制,因此它允许我们确保它们之间的过渡是平滑的。
就像我说的那样,这并没有完全解决问题,但它不使用JavaScript并且会保持流畅性。

这是一个非常优雅的解决方案,没有涉及到JS。赞! - Randy Hall

3

为了改进Duopixel的答案,当运行无限动画时,我必须执行以下操作:

$(".box").css("animation-iteration-count", "1"); 
$(".box").bind("webkitAnimationEnd mozAnimationEnd animationEnd", function(){
  $(this).removeClass("animated")  
})
$(".box").hover(function(){
  $(".box").css("animation-iteration-count", "infinite"); 
  $(this).addClass("animated");        
})

这不仅可以突然结束动画。

如果我想在移除悬停时优雅地停止动画,然后再次在悬停时开始无限动画怎么办? - Vinay
您可以实现框的mouseleave事件,然后在那里添加此代码。 - Willy Cornejo
3
开发了一个解决方案 :D 如果有帮助的话,这里是 jsfiddle 的链接! http://jsfiddle.net/sSYYE/33/ - Vinay
谢谢@Vinay!你的解决方案真的很有帮助! - Thiago Rossener
能否确保动画结束时在反向面? - Webwoman

1
一个简单的技巧就可以完成这项工作:
-webkit-animation:swing 3600ms ease-in-out 6000s;
-webkit-transform-origin:top;

在元素上(而不是:hover)设置延迟时间的高值。

来源:Stackoverflow - Robert McKee


0

CSS在某些情况下可能有所帮助,但并非所有情况都适用。以下是代码,可以在悬停和悬停后动画字母间距。

h1
{
    -webkit-transition:all 0.3s ease;
}

h1:hover
{
    -webkit-transition:all 0.3s ease;
    letter-spacing:3px;
}
<body>
    <h1>Hello</h1>
</body>


3
那是一个转换,而不是动画。 - Andrew Magill

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接