CSS3:动画精灵+悬停过渡

Posted

技术标签:

【中文标题】CSS3:动画精灵+悬停过渡【英文标题】:CSS3: animated sprite + on hover transition 【发布时间】:2013-08-22 09:19:27 【问题描述】:

我正在进入 CSS3 动画和过渡的世界,所以请原谅我的无知。 这是我正在尝试做的简化版本:

我有一个通过 CSS3 关键帧无限“跳动”的球 我希望球变大并在我将鼠标悬停在它上面时保持这种状态 我希望当我将鼠标移开并保持脉动时球再次变小(当然,所有的过渡都需要平滑)。

这是我混合使用 CSS3 动画和过渡的尝试(目前在 Chrome 上对此进行了测试,因此使用了 webkit 前缀):

@-webkit-keyframes pulsate 
    from 
        -webkit-transform: scale(0.7);
        
    to 
        -webkit-transform: scale(0.8);
    


.ball 
    background: blue;
    width: 100px;
    height: 100px;
    border-radius: 50%;
    transition: all 1s;

    -webkit-transform: scale(0.7);
    -webkit-transform-origin: center center; 

    -webkit-animation-duration: 800ms;
    -webkit-animation-name: pulsate;
    -webkit-animation-iteration-count: infinite;
    -webkit-animation-direction: alternate;
    -webkit-animation-timing-function: ease-in-out;


.ball:hover 
    -webkit-transform: scale(2);
    -webkit-animation-play-state: paused; /* transition works but gets reset at the end*/
    /*-webkit-animation: 0;*/ /* transition works only one time, and no smooth transition on mouse out */

jsFiddle Demo

结果非常接近,但是当球在悬停时完成膨胀时,它突然又变小了(不明白为什么)。我还尝试通过-webkit-animation: 0; 禁用动画而不是暂停它,但它也不能正常工作。

我尝试了一种仅使用关键帧(无过渡)的不同方法,方法是尝试在悬停时调用不同的关键帧集:

@-webkit-keyframes pulsate 
    from 
        -webkit-transform: scale(0.7);
        
    to 
        -webkit-transform: scale(0.8);
    


@-webkit-keyframes expand 
    to 
        -webkit-transform: scale(2);
    


@-webkit-keyframes shrink 
    to 
        -webkit-transform: scale(0.7);
    


.ball 
    background: blue;
    width: 100px;
    height: 100px;
    border-radius: 50%;
    transition: all 2s;

    -webkit-transform: scale(0.7);
    -webkit-transform-origin: center center; 

    -webkit-animation-duration: 800ms, 800ms;
    -webkit-animation-name: shrink, pulsate;
    -webkit-animation-iteration-count: 1, infinite;
    -webkit-animation-direction: normal, alternate;
    -webkit-animation-timing-function: ease-in-out, ease-in-out;


.ball:hover 
    -webkit-animation-name: expand;
    -webkit-animation-iteration-count: 1;
    -webkit-animation-direction: normal;
    -webkit-animation-fill-mode: forwards;    

jsFiddle Demo

只要鼠标悬停在球上,球就会保持大,但当鼠标离开球时仍然没有平滑的过渡。我希望它播放 shrink 动画,但它没有。

我是否遗漏了什么,或者目前仅使用纯 CSS 无法实现?

// 相关线程但对我不起作用:Stop animation and start transition on hover

【问题讨论】:

在您的第一个小提琴中 - 如果您在过渡上添加一点延迟,它将始终在悬停时过渡(不仅在第一次):transition: all 1s 0.01; - jsfiddle.net/danield770/ntTUt/1 有趣!你能解释一下它为什么起作用吗?我仍然需要在跳动时从任意状态开始转换,而不是像现在这样从 scale(0.7) 开始,然后在鼠标移出时平滑地转换回来 【参考方案1】:

您需要添加动画延迟以允许过渡完成,因为它会在动画开始时恢复为 scale(.7)Updated jsFiddle

-webkit-animation-delay:1s;

编辑

我意识到我在这里发布的答案并不完全正确。确实,延迟动画了从大到小的过渡,但是如果你将鼠标悬停在脉动球上,当它展开时它会跳回到它的 0 值 0.7,然后再进行大规模动画。

Updated Demo

我想出了一个修复程序,它只使用一些基于this article 的javascript 来修复它。您确实必须稍微更改 CSS,但在结果中并不是很明显。这是更新的代码

/* CSS */
body margin: 100px;

@-webkit-keyframes pulsate 
    0% 
        -webkit-transform: scale(0.7);
        
    50% 
        -webkit-transform: scale(0.8);
    
    100% 
        -webkit-transform: scale(0.7);
    


.ball 
    background: blue;
    width: 100px;
    height: 100px;
    border-radius: 50%;    
    -webkit-transform: scale(0.7);
    -webkit-transform-origin: center center; 
    transition: all 1s;

.ball.animated 
  -webkit-animation-duration: 1600ms; 
  -webkit-animation-name: pulsate;
  -webkit-animation-iteration-count: infinite;
  -webkit-animation-direction: alternate;
  -webkit-animation-timing-function: ease-in-out;


/* Javascript */
var ball = document.getElementsByClassName('ball')[0],
    pfx = ["webkit", "moz", "MS", "o", ""],
    hovered = false;

function AnimationListener() 
    if(hovered)
     
      ball.classList.remove('animated');     
      ball.style.webkitTransform = 'scale(2)';
      ball.style.transform = 'scale(2)';
    


function TransitionListener() 
  if(!hovered)
  
    ball.classList.add('animated');
  


function PrefixedEvent(element, type, callback) 
    for (var p = 0; p < pfx.length; p++) 
        if (!pfx[p]) type = type.toLowerCase();
        element.addEventListener(pfx[p]+type, callback, false);
    


PrefixedEvent(ball, "AnimationIteration", AnimationListener);

ball.onmouseover = function() 
  hovered = true;

ball.onmouseout = function() 
  hovered = false;
  PrefixedEvent(ball, "TransitionEnd", TransitionListener);
  ball.style.webkitTransform = 'scale(.7)';
  ball.style.transform = 'scale(.7)';  

【讨论】:

太好了,我没有意识到,谢谢!只剩下一个小问题 - 当鼠标悬停在球上时(而不是从初始状态),是否可以让球从当前状态开始展开?设置 -webkit-animation-fill-mode: forwards; 无济于事,因为我禁用了悬停动画 理论上你可以让动画运行更长时间(在过渡期间),但由于它们影响相同的变量(比例)你不能。然后问题进入另一个问题,获取关键帧的当前百分比并近似结果。这是可能的,但您必须使用 javascript 来执行此操作。我问了一个问题并发布了一个解决方案,试图做到这一点(动画略有不同)here on SO 所以换句话说,在 CSS3 中没有办法在保留状态的同时从一个关键帧序列切换到另一个关键帧序列 不是没有javascript或者没有改变不同的值,没有 还有什么我可以回答的吗?【参考方案2】:

只要更新这个 CSS 规则,我在 Expand & Shrink 中添加了 From & To -:

@-webkit-keyframes expand 
    from 
        -webkit-transform: scale(1);
        
    to 
        -webkit-transform: scale(2);
    


@-webkit-keyframes shrink 
    from 
        -webkit-transform: scale(2);
        
    to 
        -webkit-transform: scale(1);
    

【讨论】:

谢谢,这看起来更好。但是,我不明白为什么我需要明确指定from。规范说如果from 被省略,浏览器使用当前计算的样式作为起点。这是理想的行为,因为我可以在球完全展开之前将鼠标移开,而且我不想在那里看到跳跃。

以上是关于CSS3:动画精灵+悬停过渡的主要内容,如果未能解决你的问题,请参考以下文章

使用 CSS3 过渡延迟鼠标悬停/悬停

使用 CSS3 使图像/div 淡化,而不使用悬停

如何在css精灵悬停上制作过渡效果

css3背景过渡在第一个时闪烁:悬停

CSS3:动画之间的平滑过渡:hover

CSS3 过渡/悬停效果在 Firefox 中不起作用; Firefox 错误?