简体   繁体   English

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

[英]CSS3 Smooth transition when dynamically changing animations

I have two keyframe animations "Bounce-In" and "Bounce-Out" the Bounce-In animation takes 1.2 seconds to complete, but if a user triggers the Bounce-Out function before it's finished it will jump to 100% scale and doesn't gracefully scale out from it's current animation position. 我有两个关键帧动画“Bounce-In”和“Bounce-Out”Bounce-In动画需要1.2秒才能完成,但如果用户在完成之前触发Bounce-Out功能,它将跳到100%比例并且不会优雅地从它的当前动画位置向外扩展。

Is this possible with keyframe animations? 关键帧动画可以实现吗? I've seen it done with transition property but not using scale(). 我已经看到它完成了转换属性但没有使用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) }
}

I have a demo on JSFiddle: http://jsfiddle.net/Vn3bM/98/ *if you click the "Games" circle before the animation is finished you will notice the other two jump to 100% and then animate out (that's what I'm trying to make smooth). 我在JSFiddle上有一个演示: http//jsfiddle.net/Vn3bM/98/ *如果你在动画结束前单击“游戏”圈子,你会注意到另外两个跳到100%,然后动画出来(这就是什么我试图顺利)。

I even tried removing the 0% keyframe from Bounce-Out and that didn't help... 我甚至尝试从Bounce-Out中移除0%关键帧,这没有帮助......

In your case, the "jump" you notice in your animation comes from the change of animations you have installed on onmouseup. 在您的情况下,您在动画中注意到的“跳跃”来自您在onmouseup上安装的动画的更改。 The "Bounce-Out" Animation has an initial scale of 1 (first Keyframe), and this is what the two circles immediately get set to when the animation is installed. “Bounce-Out”动画的初始比例为1(第一个Keyframe),这就是安装动画时两个圆圈立即设置的位置。

There are two solutions to this, which I can explain in some detail: 有两种解决方案,我可以详细解释一下:


The Easy Way 简单的方法

You could just wait for the initial animation to end via the 'webkitAnimationEnd' Event and install the onmouseup event with a recursive function waiting for the animation to finish: 您可以等待初始动画通过'webkitAnimationEnd'事件结束,并使用递归函数安装onmouseup事件,等待动画完成:

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

And here's the onmouseup handler: 这是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();
}


I installed a jsfiddle here so you can see it working. 在这里安装了一个jsfiddle ,你可以看到它正常工作。 The Bounce Out animation is only triggered after the animation finished, nothing unusual about that. Bounce Out动画仅在动画结束后触发,没有任何异常。


The Hard Way 困难的方式

You can pause the animation and parse the current values of the transformation, then install a temporary keyframe animation to bounce out. 您可以暂停动画并解析转换的当前值,然后安装临时关键帧动画以退出。 This gets much more verbose though: 这会变得更加冗长:

First, you have to stop the animations: 首先,你必须停止动画:

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

Then, you set up a helper to insert new css rules: 然后,您设置一个帮助程序来插入新的css规则:

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

Then create the css keyframe rules on the fly and insert them: 然后即时创建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(' '));

Then, you restart the animations with these rules: 然后,使用以下规则重新启动动画:

    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à. Etvoilà。 I made a jsfiddle here so you can play around with it. 我在这里做了一个jsfiddle所以你可以玩它。


More Sugar 更多的糖

  • In your example, the circles bounce out alternating in bounce . 在您的示例中,圆圈在反弹时交替弹跳 You can easily get this back to work with the second solution by using setTimeout for all sports circle animations. 通过对所有体育圈动画使用setTimeout,您可以轻松地恢复使用第二个解决方案。 I did not want to include it here because it would unnecessarily complicate the example code. 我不想在这里包含它,因为它会不必要地使示例代码复杂化。

  • I know the provided examples are not really DRY , you could for example make all the stuff for events and sports work with half the lines of code (with meta properties), but in terms of readability, I think this example serves well. 我知道提供的示例并不是真的DRY ,例如,您可以使用一半代码行(使用元属性)使事件和体育的所有内容工作,但就可读性而言,我认为这个示例很好。

  • To have this example working in all browsers with support for css3 animations , you need to normalize the transition properties. 要让此示例在支持css3动画的所有浏览器中运行 ,您需要规范化过渡属性。 To do this in javascript, have a look here The Example works for animations and other properties as well, just replace 'transition' with the property you want 要在javascript中执行此操作,请查看此处示例适用于动画和其他属性,只需将“transition”替换为您想要的属性

  • For a further read on modifying css3 animations on the fly , I found this post very useful, have a look at it as well. 有关动态修改css3动画的进一步阅读 ,我发现这篇文章非常有用,请看一下。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM