CSS3平滑过渡在动态更改动画时的应用

3

我有两个关键帧动画,分别是“Bounce-In”和“Bounce-Out”。Bounce-In动画需要1.2秒才能完成,但如果用户在它结束之前触发了Bounce-Out功能,它将跳到100%的比例,并且无法从当前动画位置平滑缩小。

使用关键帧动画是否可能实现这一效果?我已经看到可以使用transition属性实现,但没有使用scale()函数。

@-webkit-keyframes Bounce-In 
{
0% { -webkit-transform: scale(0) }
40% { -webkit-transform: scale(1.0) }
60% { -webkit-transform: scale(0.7) }
80% { -webkit-transform: scale(1.0) }
90% { -webkit-transform: scale(0.9) }
100% { -webkit-transform: scale(1.0) }
}

@-webkit-keyframes Bounce-Out 
{
0% { -webkit-transform: scale(1.0) }
40% { -webkit-transform: scale(0.1) }
60% { -webkit-transform: scale(0.4) }
80% { -webkit-transform: scale(0.1) }
90% { -webkit-transform: scale(0.2) }
100% { -webkit-transform: scale(0) }
}

我在JSFiddle上有一个演示:http://jsfiddle.net/Vn3bM/98/ *如果您在动画完成之前点击“游戏”圆圈,您会注意到另外两个圆圈跳到了100%,然后再消失(我正在尝试使其平滑)。

我甚至尝试删除Bounce-Out的0%关键帧,但这并没有帮助......

1个回答

12

在你的情况下,你注意到动画中的“跳跃”来自于你在onmouseup上安装的动画变化。 "Bounce-Out"动画具有初始缩放值1(第一个关键帧),这是安装动画时两个圆形立即设置的值。

有两种解决方法,我可以详细解释:


简单方法

你可以通过 'webkitAnimationEnd'事件等待初始动画结束,然后使用递归函数等待动画完成后再安装onmouseup事件:

var initAnimationEnded = false;
document.getElementById('sports').addEventListener('webkitAnimationEnd', function() {
 initAnimationEnded = true;
}, false);​

这里是 onmouseup 处理程序:

document.getElementById('games').onmouseup = function() {
  function bounceOut() {
    if (initAnimationEnded) {
        events.style.webkitAnimationName = "Bounce-Out";
        sports.style.webkitAnimationDelay = "0.2s";
        sports.style.webkitAnimationName = "Bounce-Out";
    } else {
        setTimeout(bounceOut, 20);
    }
  }
  bounceOut();
}


我在这里安装了一个 jsfiddle,这样你就可以看到它的工作原理。"Bounce Out" 动画只会在动画完成后触发,这没有什么异常。


较为麻烦的方法

你可以暂停动画并解析转换的当前值,然后安装一个临时的关键帧动画来反弹出去。但是这将变得更加冗长:

首先,你必须停止动画:

events.style.webkitAnimationPlayState = "paused";
sports.style.webkitAnimationPlayState = "paused";

然后,您设置一个帮助程序来插入新的CSS规则:

var addCssRule = function(rule) {
  var style = document.createElement('style');
  style.innerHTML = rule;
  document.head.appendChild(style);
}

然后动态创建CSS关键帧规则并插入它们:

    // get the current transform scale of sports and events

    function getCurrentScaleValue(elem) {
      return document.defaultView.
      getComputedStyle(elem, null).
      getPropertyValue('-webkit-transform').
      match(/matrix\(([\d.]+)/)[1];
    }

    var currentSportsScale = getCurrentScaleValue(sports);
    var currentEventsScale = getCurrentScaleValue(events);

     // set up the first string for the keyframes rule

    var sportsTempAnimation = ['@-webkit-keyframes Sports-Temp-Bounce-Out {'];
    var eventsTempAnimation = ['@-webkit-keyframes Events-Temp-Bounce-Out {'];

     // basic bounce out animation

    var bounceOutAnimationBase = {
        '0%': 1,
        '40%': 0.1,
        '60%': 0.4,
        '80%': 0.1,
        '90%': 0.2,
        '100%': 0
    };

     // scale the animation to the current values

    for (prop in bounceOutAnimationBase) {
        sportsTempAnimation.push([
          prop, ' 
          { -webkit-transform: scale(', 
          currentSportsScale * bounceOutAnimationBase[prop], 
          ') } '].join(''));
        eventsTempAnimation.push([
           prop, 
           ' { -webkit-transform: scale(', 
           currentEventsScale * bounceOutAnimationBase[prop], 
           ') } '
         ].join(''));
    }

     // add closing brackets

    sportsTempAnimation.push('}');
    eventsTempAnimation.push('}');

     // add the animations to the rules

    addCssRule([sportsTempAnimation.join(''), 
                eventsTempAnimation.join('')].join(' '));

然后,您可以按照以下规则重新启动动画:

    events.style.webkitAnimationName = "Events-Temp-Bounce-Out";
    events.style.webkitAnimationDelay = "0s";
    sports.style.webkitAnimationDelay = "0s";
    sports.style.webkitAnimationName = "Sports-Temp-Bounce-Out";
    events.style.webkitAnimationPlayState = "running";
    sports.style.webkitAnimationPlayState = "running";


Et voilà. 我做了一个 jsfiddle,您可以在其中进行尝试和操作。


更多语法糖

  • 在您的示例中,圆形以交替的方式弹出。 您可以通过为所有运动圆形动画使用setTimeout,轻松地将其恢复到第二个解决方案中。我不想在这里包含它,因为这会使示例代码变得过于复杂。

  • 我知道提供的示例并不是真正的DRY。 例如,您可以使用元属性使所有事件和运动的工作只需要一半的代码行数,但就可读性而言,我认为这个示例很好。

  • 要使此示例在支持css3动画的所有浏览器中工作,您需要规范化转换属性。要在JavaScript中执行此操作,请看这里。该示例也适用于动画和其他属性,只需将“transition”替换为所需的属性即可。

  • 如果要进一步阅读有关在代码中修改css3动画的信息,我发现这篇文章非常有用,请您也参考一下。


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