等待 CSS 动画完成

How*_*Gee 3 css jquery animation

我正在使用动画进行定向翻转。我以为我找到了使用以下绑定的解决方案,但我没有注意到以下问题...

bind( 'transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd', function() {
Run Code Online (Sandbox Code Playgroud)

问题是,如果您将鼠标悬停在左上方,则动画会沿对角线翻转或旋转 - 您可以快速悬停 div 的多个部分,它会做一些疯狂的事情。我想要发生的是动画完成或重置,而不是立即尝试处理下一个悬停动画。这个问题出现在所有现代浏览器中(IE Edge / 11、Chrome、Firefox。这些是我在 中测试过的)。

我会以错误的方式解决这个问题吗?如何让我的 javascript 等待翻转动画完成?


相关问题是有时动画会卡在从左到右或从上到下的动画,无论哪个方向,因为它没有等待完成所以它可以删除其他类。

bind( 'transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd', function() {
Run Code Online (Sandbox Code Playgroud)
jQuery(document).ready(function() {
  $('.galleryWrapper.bot .gallery-item').hover(
    function(e) {
      $(this).unbind('transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd');
      $(this).removeClass('rtl');
      var w = $(this).width();
      var h = $(this).height();
      var x = (e.pageX - this.offsetLeft - (w / 2)) * (w > h ? (h / w) : 1);
      var y = (e.pageY - this.offsetTop - (h / 2)) * (h > w ? (w / h) : 1);
      var direction = Math.round(Math.atan2(y, x) / 1.57079633 + 5) % 4;

      switch (direction) {
        case 0: // Top
          $(this).addClass('utd');
          break;

        case 1: // Right
          $(this).addClass('rtl');
          break;

        case 2: // Bottom
          $(this).addClass('dtu');
          break;

        case 3: // Left
          $(this).addClass('ltr');
          break;
      }
    },

    function(e) {
      $(this).on('transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd', function() {
        $(this).removeClass('utd rtl dtu ltr').addClass('rtl');
      });
    }
  );
});
Run Code Online (Sandbox Code Playgroud)
.galleryWrapper {
  display: -webkit-flex;
  display: flex;
  -webkit-flex-wrap: wrap;
  flex-wrap: wrap;
}
.galleryWrapper .gallery-item {
  margin: 10px;
  -webkit-perspective: 1000;
  -moz-perspective: 1000;
  -ms-perspective: 1000;
  perspective: 1000;
  -ms-transform: perspective(1000px);
  -moz-transform: perspective(1000px);
  -moz-transform-style: preserve-3d;
  -ms-transform-style: preserve-3d;
}
.galleryWrapper .gallery-item,
.galleryWrapper .gallery-item .item .side {
  width: 100px;
  height: 100px;
  box-sizing: border-box;
}
.galleryWrapper .gallery-item .item {
  position: relative;
  -webkit-transition: 0.6s;
  -webkit-transform-style: preserve-3d;
  -ms-transition: 0.6s;
  -moz-transition: 0.6s;
  -moz-transform: perspective(1000px);
  -moz-transform-style: preserve-3d;
  -ms-transform-style: preserve-3d;
  transition: 0.6s;
  transform-style: preserve-3d;
}
.galleryWrapper .gallery-item .item .side {
  position: absolute;
  top: 0;
  left: 0;
  -webkit-backface-visibility: hidden;
  -moz-backface-visibility: hidden;
  -ms-backface-visibility: hidden;
  backface-visibility: hidden;
}
.galleryWrapper .gallery-item .item-front {
  z-index: 2;
  background-color: red;
}
.galleryWrapper .gallery-item .item-back {
  background-color: blue;
}
.galleryWrapper .gallery-item.ltr .item-front {
  -webkit-transform: rotateY(0deg);
  -moz-transform: rotateY(0deg);
  -o-transform: rotateY(0deg);
  -ms-transform: rotateY(0deg);
  transform: rotateY(0deg);
}
.galleryWrapper .gallery-item.ltr .item-back {
  -webkit-transform: rotateY(180deg);
  -moz-transform: rotateY(180deg);
  -o-transform: rotateY(180deg);
  -ms-transform: rotateY(180deg);
  transform: rotateY(180deg);
}
.galleryWrapper .gallery-item.ltr:hover .item {
  -webkit-transform: rotateY(180deg);
  -moz-transform: rotateY(180deg);
  -o-transform: rotateY(180deg);
  -ms-transform: rotateY(180deg);
  transform: rotateY(180deg);
}
.galleryWrapper .gallery-item.rtl .item-front {
  -webkit-transform: rotateY(0deg);
  -moz-transform: rotateY(0deg);
  -o-transform: rotateY(0deg);
  -ms-transform: rotateY(0deg);
  transform: rotateY(0deg);
}
.galleryWrapper .gallery-item.rtl .item-back {
  -webkit-transform: rotateY(-180deg);
  -moz-transform: rotateY(-180deg);
  -o-transform: rotateY(-180deg);
  -ms-transform: rotateY(-180deg);
  transform: rotateY(-180deg);
}
.galleryWrapper .gallery-item.rtl:hover .item {
  -webkit-transform: rotateY(-180deg);
  -moz-transform: rotateY(-180deg);
  -o-transform: rotateY(-180deg);
  -ms-transform: rotateY(-180deg);
  transform: rotateY(-180deg);
}
.galleryWrapper .gallery-item.utd .item,
.galleryWrapper .gallery-item.dtu .item {
  transform-origin: 100% 50px;
}
.galleryWrapper .gallery-item.dtu .item-front {
  -webkit-transform: rotateX(0deg);
  -moz-transform: rotateX(0deg);
  -o-transform: rotateX(0deg);
  -ms-transform: rotateX(0deg);
  transform: rotateX(0deg);
}
.galleryWrapper .gallery-item.dtu .item-back {
  -webkit-transform: rotateX(180deg);
  -moz-transform: rotateX(180deg);
  -o-transform: rotateX(180deg);
  -ms-transform: rotateX(180deg);
  transform: rotateX(180deg);
}
.galleryWrapper .gallery-item.dtu:hover .item {
  -webkit-transform: rotateX(180deg);
  -moz-transform: rotateX(180deg);
  -o-transform: rotateX(180deg);
  -ms-transform: rotateX(180deg);
  transform: rotateX(180deg);
}
.galleryWrapper .gallery-item.utd .item-front {
  -webkit-transform: rotateX(0deg);
  -moz-transform: rotateX(0deg);
  -o-transform: rotateX(0deg);
  -ms-transform: rotateX(0deg);
  transform: rotateX(0deg);
}
.galleryWrapper .gallery-item.utd .item-back {
  -webkit-transform: rotateX(-180deg);
  -moz-transform: rotateX(-180deg);
  -o-transform: rotateX(-180deg);
  -ms-transform: rotateX(-180deg);
  transform: rotateX(-180deg);
}
.galleryWrapper .gallery-item.utd:hover .item {
  -webkit-transform: rotateX(-180deg);
  -moz-transform: rotateX(-180deg);
  -o-transform: rotateX(-180deg);
  -ms-transform: rotateX(-180deg);
  transform: rotateX(-180deg);
}
Run Code Online (Sandbox Code Playgroud)

在 JSFiddle 上查看

我的这个动画基于David WalshCSS Flip

cod*_*eaK 5

解决演示

快节奏运动的第二个演示

摆弄 .on() 方法而不是 .bind()

您的问题中给出的示例根据我的方式进行了简单的修改

[在 chrome 版本 50.0.2661.87 m(64 位)、opera 36.0.2130.65、Firefox 45.0.2 IE 版本 11.0.9600.17843 上测试]

我保持简单,使事情更容易引人注目我使用了延迟 3 秒的简单反弹动画,并且您的逻辑发生的问题是每次新悬停时您都开始新动画(计算每个时间位置并且 switch 语句添加班级)。我只是结束它,因此在每个过渡效果完成后,只会开始新的过渡,因此您正在谈论的关于右向左运动然后突然顶部导致两个过渡发生而没有完成另一个的问题永远不会发生

  1. 默认为div添加了一个成品类
  2. 然后我所做的是在 switch 内部检查它是否有那个类
  3. 然后在输入后将其删除,如果有的话
  4. Next 像你一样添加 css 类
  5. 接下来在绑定方法中删除动画类
  6. 最后添加完成的课程

$(".box").on("webkitAnimationEnd oAnimationEnd msAnimationEnd animationend", function(e) {

  $(this).removeClass("animated animatedL animatedR animatedT");
  $(this).addClass("finished");
})

$(".box").hover(function(e) {
  var $class = $(this).hasClass("finished");
  //$(this).addClass("animated");    
  /* */
  var w = $(this).width();
  var h = $(this).height();
  var x = (e.pageX - this.offsetLeft - (w / 2)) * (w > h ? (h / w) : 1);
  var y = (e.pageY - this.offsetTop - (h / 2)) * (h > w ? (w / h) : 1);
  var direction = Math.round(Math.atan2(y, x) / 1.57079633 + 5) % 4;

  switch (direction) {
    case 0: // Top
      if ($class) {
        $(this).removeClass("finished");
        $(this).addClass('animatedT');
      }
      break;

    case 1: // Right
      if ($class) {
        $(this).removeClass("finished");
        $(this).addClass('animatedR');
      }
      break;

    case 2: // Bottom
      if ($class) {
        $(this).removeClass("finished");
        $(this).addClass('animated');
      }
      break;

    case 3: // Left
      if ($class) {
        $(this).removeClass("finished");
        $(this).addClass('animatedL');
      }


  }
})
Run Code Online (Sandbox Code Playgroud)
@-webkit-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;
  }
}
@-moz-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;
  }
}
@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;
  }
  85% {
    top: 3px;
    animation-timing-function: ease-in;
  }
  100% {
    top: 0;
  }
}
@-webkit-keyframes bounceL {
  0% {
    left: 0;
    animation-timing-function: ease-out;
  }
  17% {
    left: 15px;
    animation-timing-function: ease-in;
  }
  34% {
    left: 0;
    animation-timing-function: ease-out;
  }
  51% {
    left: 8px;
    animation-timing-function: ease-in;
  }
  68% {
    left: 0px;
    animation-timing-function: ease-out;
  }
  85% {
    left: 3px;
    animation-timing-function: ease-in;
  }
  100% {
    left: 0;
  }
}
@-moz-keyframes bounceL {
  0% {
    left: 0;
    animation-timing-function: ease-out;
  }
  17% {
    left: 15px;
    animation-timing-function: ease-in;
  }
  34% {
    left: 0;
    animation-timing-function: ease-out;
  }
  51% {
    left: 8px;
    animation-timing-function: ease-in;
  }
  68% {
    left: 0px;
    animation-timing-function: ease-out;
  }
  85% {
    left: 3px;
    animation-timing-function: ease-in;
  }
  100% {
    left: 0;
  }
}
@keyframes bounceL {
  0% {
    left: 0;
    animation-timing-function: ease-out;
  }
  17% {
    left: 15px;
    animation-timing-function: ease-in;
  }
  34% {
    left: 0;
    animation-timing-function: ease-out;
  }
  51% {
    left: 8px;
    animation-timing-function: ease-in;
  }
  68% {
    left: 0px;
  }
  85% {
    left: 3px;
    animation-timing-function: ease-in;
  }
  100% {
    left: 0;
  }
}
@-webkit-keyframes bounceR {
  0% {
    right: 0;
    animation-timing-function: ease-out;
  }
  17% {
    right: 15px;
    animation-timing-function: ease-in;
  }
  34% {
    right: 0;
    animation-timing-function: ease-out;
  }
  51% {
    right: 8px;
    animation-timing-function: ease-in;
  }
  68% {
    right: 0px;
    animation-timing-function: ease-out;
  }
  85% {
    right: 3px;
    animation-timing-function: ease-in;
  }
  100% {
    right: 0;
  }
}
@-moz-keyframes bounceR {
  0% {
    right: 0;
    animation-timing-function: ease-out;
  }
  17% {
    right: 15px;
    animation-timing-function: ease-in;
  }
  34% {
    right: 0;
    animation-timing-function: ease-out;
  }
  51% {
    right: 8px;
    animation-timing-function: ease-in;
  }
  68% {
    right: 0px;
    animation-timing-function: ease-out;
  }
  85% {
    right: 3px;
    animation-timing-function: ease-in;
  }
  100% {
    right: 0;
  }
}
@keyframes bounceR {
  0% {
    right: 0;
    animation-timing-function: ease-out;
  }
  17% {
    right: 15px;
    animation-timing-function: ease-in;
  }
  34% {
    right: 0;
    animation-timing-function: ease-out;
  }
  51% {
    right: 8px;
    animation-timing-function: ease-in;
  }
  68% {
    right: 0px;
  }
  85% {
    right: 3px;
    animation-timing-function: ease-in;
  }
  100% {
    right: 0;
  }
}
@-webkit-keyframes bounceT {
  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;
  }
}
@-moz-keyframes bounceT {
  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;
  }
}
@keyframes bounceT {
  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;
  }
  85% {
    top: 3px;
    animation-timing-function: ease-in;
  }
  100% {
    top: 0;
  }
}
#container {
  position: relative;
}
.box {
  position: relative;
  float: left;
  background: #f00;
  width: 50px;
  height: 50px;
  margin-right: 5px;
  margin: 50px;
}
.box.animated {
  -moz-animation: bounce .5s;
  -webkit-animation: bounce .5s;
  animation: bounce .5s;
}
.box.animatedL {
  -moz-animation: bounceL .5s;
  -webkit-animation: bounceL .5s;
  animation: bounceL .5s;
}
.box.animatedR {
  -moz-animation: bounceR .5s;
  -webkit-animation: bounceR .5s;
  animation: bounceR .5s;
}
.box.animatedT {
  -moz-animation: bounceT .5s;
  -webkit-animation: bounceT .5s;
  animation: bounceT .5s;
}
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
<div id="container">
  <div class="box finished"></div>
  <div class="box finished"></div>
  <div class="box finished"></div>
  <div class="box finished"></div>
</div>
Run Code Online (Sandbox Code Playgroud)

编辑-

不推荐.bind()使用更改方法,.on()因为绑定已被弃用

$(".box").on("webkitAnimationEnd oAnimationEnd msAnimationEnd animationend", function (e){

 $(this).removeClass("animated animatedL animatedR animatedT");
  $(this).addClass("finished");  
  })
Run Code Online (Sandbox Code Playgroud)

在您的原始小提琴中,我刚刚做了一些更改,我刚刚添加了类名
.finished ,然后在 switch 案例中添加了一个if循环,以检查悬停的元素是否.finished在其类列表中具有类,.hasClass()如果使用它返回布尔值,则只有动画类是添加并在您的 .on() 函数中,我刚刚添加了.finished指示动画结束的类。此序列可防止动画重叠,然后再次安全起见,如果您愿意,可以在过渡结束后添加 100 毫秒的延迟