【问题标题】:Continue for loop after the animation has finished动画结束后继续for循环
【发布时间】:2016-06-29 21:53:18
【问题描述】:

我正在尝试可视化 shellsort 算法。

  function shellSort (a) {

  for (var h = a.length; h = parseInt(h / 2);) {
      for (var i = h; i < a.length; i++) {
          var k = getInt(a[i].id);
          var helper = a[i];
          for (var j = i; j >= h && k < getInt(a[j - h].id); j -= h){

            var idA = a[j].id;
            var idB = a[j - h].id;

            setTimeout(function(){
              animatTthis($('#' + idA), 500);
              animatTthis($('#' + idB), 500);
              console.log('animate!');
            },250);

            a[j] = a[j - h];
          }
          a[j] = helper;
      }
  }
  return a;  
}

首先,我创建随机数并将它们作为 p-tag 添加到 div 中。之后,我将所有具有拟合类的 div 推送到一个数组中,该数组提供给上面的 shellsort 函数。 这工作正常,但我无法让动画正常工作。

  function animatTthis(targetElement, speed) {
  $(targetElement).animate({ top: "50px"},
  {
      duration: speed,
      complete: function ()
      {
          setTimeout(function(){
            $(targetElement).animate({ top: "0px" },{
              duration: speed,
              complete: function (){
                  console.log('animate!');
              }
            });
        },500);
      }
  });
};

它只为循环中的最后两个 Div 设置动画。

我的意图是交换的两个 Div 再次向下滑动。 shellsort 应该在那之后继续。

我尝试了许多不同的解决方案,但我无法让它按照我想要的方式工作。

完成的版本应该在视觉上交换两个 div。所以如果你有一个快速的解决方案或链接给我,那就太棒了。

提前致谢。

编辑:

使用的 HTML 和 CSS:

    <!DOCTYPE html>
<html>
<head>
<script src="jquery-3.0.0.js"></script>
<script src="script.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript" src="http://code.jquery.com/color/jquery.color-2.1.2.js"></script>

<link rel="stylesheet" href="stylesheet.css">

<title>Shell Sort</title>
</head>
<body>
<h1 >Shell- sort</h1>
<button id='randomNumbers'>Numbers!</button> // creeates random numbers
<button id='okay'>Okay!</button>  //starts the shellsort
<div id='container'>
  <div id="element1" class="test"><p class='value' id='e1ID'></p></div>
  <div id="element2" class="test"><p class='value' id='e2ID'></p></div>
  <div id="element3" class="test"><p class='value' id='e3ID'></p></div>
  <div id="element4" class="test"><p class='value' id='e4ID'></p></div>
  <div id="element5" class="test"><p class='value' id='e5ID'></p></div>
  <div id="element6" class="test"><p class='value' id='e6ID'></p></div>
</div>


</body>
</html>

CSS:

h1{
    color:red;
}
.value{
    margin: 0;
    text-align: center;
    line-height:75px;
    font-size: 30px;
    font-weight: bold;
}
.test{
        background-color: red;
        height: 75px;
        width: 75px;
        position: relative;
        float:left;
        margin: 10px;
        border-radius: 50%;
}

这里没有任何功能,但也许有帮助.. :)

jquery 代码:

   $(document).ready(function(){

//#############---giveRandomNumbers----#############
  $("#randomNumbers").click(function(){
    var numbers = [];
    for(var i = 0; i < 6; i++){
      var $random = Math.floor((Math.random() * 100) + 1);
      numbers.push($random);
    }

      for(var int = 0; int < numbers.length; int++){
          $('#e'+(int + 1)+'ID').text(numbers[int]);
      }
    });

  $('#okay').click(function(){
      var $ids = $('.test');
      shellSort($ids);

      for(var int = 0; int < $ids.length; int++){
        console.log(getInt($ids[int].id));
        $("#container").append($ids[int]);
      }
    });

    //#############---getIntegerOfDiv----#############
  function getInt(id) {
    var $number = parseInt($('#'+ id).find("p").text());
    return $number;
  };
  //#############---animationCarry----#############
  function createAnimation(a, b) {
      return function() {
          animatTthis($('#' + a), 500);
          animatTthis($('#' + b), 500);
      };
  }
//#############---animation----#############
  function animatTthis(targetElement, speed) {
  $(targetElement).animate({ top: "50px"},
  {
      duration: speed,
      complete: function (){
          setTimeout(function(){
            $(targetElement).animate({ top: "0px" },{
              duration: speed,
              complete: function (){
                  console.log('animate!');
              }
            });
        },500);
      }
  });
};
//#############---shellSort----#############
  function shellSort (a) {

      for (var h = a.length; h = parseInt(h / 2);) {
          for (var i = h; i < a.length; i++) {
              var k = getInt(a[i].id);
              var helper = a[i];
              for (var j = i; j >= h && k < getInt(a[j - h].id); j -= h){
                a[j] = a[j - h];
                var idA = a[j].id;
                var idB = a[j - h].id;
                setTimeout(createAnimation(idA, idB), 250);

              }
              a[j] = helper;
          }
      }
      return a;
  }
});

【问题讨论】:

  • 可以在这里添加相关的HTML和CSS吗?
  • 感谢分享 HTML 和 CSS。我正在检查您的代码,但无法找到在创建随机按钮和函数getInt 上调用的代码。因此,请分享您的script.js 文件中的代码。一旦我们可以在这里重现代码,就很容易修复代码。谢谢。
  • 我在帖子中添加了 jquery 代码!感谢您的关注:)
  • 我会尽快检查的。谢谢..!

标签: jquery loops animation


【解决方案1】:

看起来,超时中使用的变量只是被引用 - 所以对于每个循环,为当前 val 设置一个新的超时(= 预期)+ 之前创建的超时函数的函数中的值也被修改(= 出乎意料,我猜)。

一个可能的解决方案是不异步地制作动画。 也许它也可以通过“currying”-function ala 创建一个函数

function createAnimation(a, b) {
    return function() {
        animatTthis($('#' + a), 500);
        animatTthis($('#' + b), 500);
    };
}

在我们的类别中:

setTimeout(createAnimation(idA, idB), 250);

希望对你有帮助

编辑:同时动画是您要求的另一个问题。 无论如何:问题是,迭代比 250 毫秒快得多,所以所有动画几乎同时开始。

您需要通过动画回调一个接一个地对动画进行排队。我的建议是首先进行排序并收集有关如何制作动画的信息。之后,您可以创建一个链式函数以根据需要进行动画处理。

我创建了一个示例,该示例将您的一些原始方法替换为“动画师”,它能够收集所需的信息并在之后执行动画:

var Animator = {

 toAnimate: [],

 add: function(a, b) {
    Animator.toAnimate.push({
        a: '#' + a,
        b: '#' + b
    });
 },

 execute: function() {

     var lastCallback = function() {
         Animator.toAnimate = [];
     };

     for (var idx = 0; idx<Animator.toAnimate.length; idx++) {
         var elem = Animator.toAnimate[idx];
         var animateB = Animator.createAnimation(elem.b, 500, lastCallback);
         var animateA = Animator.createAnimation(elem.a, 500, animateB);

         lastCallback = animateA;
     }

     lastCallback();
 },

 createAnimation: function(id, speed, cb) {
     console.log('creating animation for ' + id);
     return function() {
        $(id).animate({top: '50px'}, speed, function() {
           $(id).animate({top: '0px'}, speed, function() {
              if (typeof(cb) === 'function') {
                 cb();
              }
           });
        });
     }
 }
}

从动画的角度来看,这似乎可行,请查看这个小提琴:https://jsfiddle.net/91Lp7k90/

除此之外,elemt id 似乎不正确,这就是为什么我还添加了一些控制台输出...

【讨论】:

  • 遗憾的是,这似乎无法解决问题:/
  • 感谢您的努力!!!我将在今天晚些时候仔细研究并报告:)
  • 抱歉让您久等了。这不完全是我的想法。我希望被比较的两个对象同时移动。在这里,每个 div 都在来回切换它被交换到最终位置的次数。尽管如此,再次非常感谢您为此付出的努力!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-03
  • 2019-10-17
  • 1970-01-01
  • 1970-01-01
  • 2017-08-12
相关资源
最近更新 更多