一个接一个地使用延迟对象实现的Div动画

8
使用延迟对象(deferred object)在前一个div动画完成后对另一个div进行动画。这种简单的方法适用于两个函数f1f2,但是当我引入f3时,它会失败。
是否有更好的方法可以使用延迟对象实现这一点?
JSFiddle:https://jsfiddle.net/j0bgzjvd/

var deferred = $.Deferred();

function animationAgent(element, prevElement) {
  $(prevElement).promise().done( function () {
    return $(element).css("display", "block").animate({width:360},2000, "linear")
  });
}

function f1() {
  animationAgent("#div1"); 
} 

function f2() {
  animationAgent("#div2", "#div1"); 
} 

function f3() {
  animationAgent("#div3", "#div2"); 
}

deferred.resolve();
deferred.done( [ f1, f2, f3 ] );
div {
  width: 200px; 
  height: 200px; 
  background-color: red; 
  margin-bottom: 10px; 
  display: none;  
}
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>

<div id="div1"></div>
<div id="div2"></div>
<div id="div3"></div>


你能添加一个代码片段或二进制文件来解决这个问题吗?控制台中有任何错误吗? - Mosh Feu
请查看帖子中更新的JSFiddle。控制台中没有错误。我希望div可以依次协调地进行动画,但是正如您所看到的,函数3会导致动画序列中的干扰。删除f3允许f1和f2按顺序进行动画。-@MoshFeu - jcoulston2
请查看下面的答案,可能会有所帮助。@jcoulston2 - Rajesh Jangid
3个回答

1
您会发现更简单的做法是:
  • animationAgent()转换为一个简单的、返回Promise的工作函数,只知道它要动画的元素,对于使用顺序一无所知(即省略prevElement),
  • 安排函数f1()f2()f3()返回由animationAgent()返回的Promise。
然后,您就有了构建可靠动画序列的基础。
function animationAgent(element) {
    return $(element).css("display", "block").animate({width:360}, 2000, "linear").promise();
}
function f1() {
    return animationAgent("#div1"); 
} 
function f2() {
    return animationAgent("#div2"); 
} 
function f3() {
    return animationAgent("#div3"); 
}

f1().then(f2).then(f3);

Alternatively,可以从一个函数引用数组中机械地构建.then链:

演示

function animationAgent(element) {
    return $(element).css("display", "block").animate({width:360}, 2000, "linear").promise();
}
function f1() {
    return animationAgent("#div1"); 
} 
function f2() {
    return animationAgent("#div2"); 
} 
function f3() {
    return animationAgent("#div3"); 
}

[f1, f2, f3].reduce(function(promise, fn) {
    return promise.then(function() {
        return fn();
    });
}, $.when());

演示

或者,由于这三个动画是相同的,您可以通过从元素选择器数组构建.then链并直接调用animationAgent()来避免需要单独的函数:

function animationAgent(element) {
    return $(element).css("display", "block").animate({width:360}, 2000, "linear").promise();
}

['#div1', '#div2', '#div3'].reduce(function(promise, selector) {
    return promise.then(function() {
        return animationAgent(selector);
    });
}, $.when());

{{链接1:演示}}


0

我不确定,但我认为这就是你想要的。

工作示例 fiddle

我觉得你希望deferred.done()会按顺序执行f1,f2,f3,它确实会这样做。 但是,在调用下一个函数之前,它不会等待在这些函数内调用的动画结束。

尝试使用console.log()在控制台上记录函数调用,你会知道。

以下是更新后的javascript代码 -

var deferred = $.Deferred();
var lock = 1;

function animationAgent(element, id, prevElement) {
  var interval;
  var flag = 0;
  if (id != lock) {
    interval = setInterval(function() {
      if (id == lock) {
        clearInterval(interval);
        animationAgent(element, id, prevElement);
      }
    }, 1000);
  }else{
    $(prevElement).promise().done(function() {
      lock++;
      return $(element).css("display", "block").animate({
        width: 360
      }, 2000, "linear");
    });
  }
}

function f1() {
  return animationAgent("#div1", 1);
}

function f2() {
  return animationAgent("#div2", 2, "#div1");
}

function f3() {
  return animationAgent("#div3", 3, "#div2");
}

deferred.resolve();
deferred.done([f1, f2, f3]);

0

你想过在动画函数中使用回调函数吗?

这里有一个使用fadeOut的例子:https://jsfiddle.net/0r7e2wco/

fadeOutInTurn([
    $("#div1"),
    $("#div2"),
    $("#div3"),
    $("#div4"),
]);

//Fades out elements one after another
function fadeOutInTurn(elements) {
    var x = 0;
    function animate() {
        $(elements[x]).fadeOut(3000, function() {
            if(x < elements.length - 1) {
                x++;
                animate();
            }
        });
    }
    animate();
}

有没有更好的方法可以实现这个?我认为他想知道如何更好地按顺序动画元素。 - seahorsepip
如果他想使用延迟对象,他应该使用notify()和progress()而不是resolve()和done(),这样延迟对象可以无限次地使用^^但我不明白为什么有人会使用延迟模式来逐个动画化一些元素... - seahorsepip
感谢您的回复。是的,更具体地说,我想使用延迟对象,我的逻辑是使用Promise方法允许函数序列一个接一个地启动。原因是,这个动画是更复杂过程的一部分,包括点击阶段,我想尝试这种方法以便在某些条件下实现优雅的解决方案。@seahorsepip - jcoulston2

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