【问题标题】:One Div animation after another using deferred object一个又一个使用延迟对象的 Div 动画
【发布时间】:2023-04-07 20:31:01
【问题描述】:

在上一个 Div 动画完成后使用 deferred object 对 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>

【问题讨论】:

  • 你能添加一个sn-p或bin来解决这个问题吗? console 中的任何错误?
  • 请参阅帖子中更新的 JSFiddle。控制台中没有错误。我希望 div 能够和谐地一个接一个地制作动画,但是正如您所见,函数 3 会导致动画序列出现混乱。取出 f3 允许 f1 和 f2 依次动画 - @MoshFeu
  • 查看下面的答案可能会有所帮助。 @jcoulston2

标签: javascript jquery jquery-deferred deferred


【解决方案1】:

你会发现它更简单:

  • animationAgent() 变成一个简单的、返回承诺的工作函数,它只知道它动画的元素,而不知道它的使用顺序(即省略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);

DEMO

或者,从函数引用数组中机械地构造 .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());

DEMO

或者,由于三个动画是相同的,您可以通过从元素选择器数组构造 .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());

DEMO

【讨论】:

    【解决方案2】:

    有没有想过在动画函数中使用回调?

    这是一个淡出的例子: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();
    }
    

    【讨论】:

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

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

    工作示例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]);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多