如何在加载远程 HTML 时正确延迟 jQuery 动画?

How do I properly delay jQuery animations when loading a remote HTML?

编辑:这个软件包是我在这里尝试修复的完整且未经修改的版本。问题出在 /data/renderpage.js 脚本中。在继续之前,请随意检查一下。

https://github.com/Tricorne-Games/HyperBook

非常感谢大家的帮助!

=

我正在完善 jQuery 脚本以按严格的顺序执行以下操作...

  1. 淡出文本。
  2. 缩小容器的大小div。
  3. 预加载遥控器 HTML /// 尚未显示!///
  4. 打开容器的大小div。
  5. 淡入新遥控器 HTML。

我不介意第 1 步和第 2 步、第 4 步和第 5 步合并为一个完整步骤(同时fade/resize)。它是在加载新的 HTML 时中断整个动画,甚至从一开始就中断。

我的想法是我不希望我的遥控器 HTML 在动画正确呈现之前显示。我希望原始文本淡出并关闭容器 div,然后在幕后准备好新 HTML 的文本,然后打开容器 div 并淡入新文本。

似乎当我调用 load(url) 函数时,它会立即加载页面,动画仍然是 运行(就像新的 HTML 最终淡出出,只会淡入,而不是原来的文本出来,然后新的文本出现)。要么,要么整个函数同时调用每一行,打乱了我想要的翻页效果。

这是我当前的脚本设置...

$(document).ready(function() {

// Start-Up Page Load (Cover, ToC, etc.)
$('#content').load('pages/page1.htm');

// Navigating Pages
$(document).on('click', 'a', function(e) {

    e.preventDefault();

    var ahref = $(this).attr('href');

    $('#content_container').animate({height: 'hide'}, 500);

    $('#content').fadeTo('slow', 0.25);

    $('#content').load(ahref);
    $('#content').css({opacity: 0.0});

    $('#content').fadeTo('slow', 1.0);

    $('#content_container').animate({height: 'show'}, 500);

    return false;

});
});

我在这里做错了什么?我在每个步骤中都使用了 delay() 函数,但它没有解决阻止新文本的问题。

问题是因为您没有在加载内容之前等待隐藏动画完成,也没有在开始显示动画之前等待内容加载。您需要使用相关方法的回调参数。试试这个:

$(document).on('click', 'a', function(e) {
    e.preventDefault();
    var ahref = $(this).attr('href'),
        $content = $('#content'),
        $contentContainer = $('#content_container');

    $contentContainer.animate({ height: 'hide'}, 500);
    $content.fadeTo('slow', 0.25, function() {
        // animation completed, load content: 
        $content.load(ahref, function() {
            // load completed, show content:
            $content.css({ opacity: 0.0 }).fadeTo('slow', 1.0);
            $contentContainer.animate({ height: 'show' }, 500);
        });
    });
});

请注意,要使效果在 UI 上最有效地工作,您需要在完成时间最长的动画完成后执行 load()

您可以使用 get() function and its callback paramater to save the HTML into a variable before actually putting it into the element with html().

而不是使用 load() 函数

在完成所有淡出和关闭旧框的动画后(可能在动画完成的回调函数中),您需要使用如下内容:

$.get(ahref, function(data) {
    // JQuery animation before we want to see the text.
    $('#content').html(data); // actually inserts HTML into element.
    // JQuery animation to fade the text in.
});

您可以使用延迟或回调函数 $(文档).on('click', 'a', 函数(e) {

    e.preventDefault();

    var ahref = $(this).attr('href');
    var dfd1 =  $.Deferred();
    var dfd2 =  $.Deferred();
    var dfd3 =  $.Deferred();
    var dfd4 =  $.Deferred();

    $('#content_container').animate({height: 'hide'}, 500, function(){
        dfd1.resolve();
    });

    dfd1.done(function() {
       $('#content').fadeTo('slow', 0.25, function() {
            dfd2.resolve();
       });
    });

    dfd2.done(function() {
        $('#content').load(ahref, function() {
            $('#content').css({opacity: 0.0});
            dfd3.resolve();
        });
    });

    dfd3.done(function() {
        $('#content').fadeTo('slow', 1.0, function() {
            dfd4.resolve();
        });
    });

    dfd4.done(function() {
        $('#content_container').animate({height: 'show'}, 500);
    });


    return false;

});

jQuery 对象可以通过在 jQuery 元素上调用 .promise 为其动画队列提供 promise

您可以使用 $.when() 等待其中一项或多项完成,然后执行其他操作。

下面做一个淡出和加载平行向上滑动,然后(只有当动画完成),向下滑动然后淡入(顺序):

$(document).on('click', 'a', function (e) {
    e.preventDefault();
    var ahref = $(this).attr('href')
    var $container = $('#content_container');
    var $content = $('#content');

    // Slide up and fadeout at the same time
    $container.animate({
        height: 'hide'
    }, 500);
    $content.fadeOut();

    // Load the content while fading out
    $('#content').load(ahref, function () {
        // Wait for the fade and slide to complete
        $.when($container.promise(), $content.promise()).then(function () {
            // Slide down and fadein (in sequence)
            $container.animate({
                height: 'show'
            }, 500, function () {
                $content.fadeTo('slow', 1.0);
            });
        });
    });
});

JSFiddle: http://jsfiddle.net/TrueBlueAussie/pffm1tnb/3/

此版本的唯一问题是 load 可能比 fadeout/slideup 完成得更快,并且过早显示新数据。在这种情况下,您不想使用 load,而是使用 get(这样您就可以控制何时插入新内容):

// Load the content while fading out
$.get(ahref, function (data) {
    // Wait for the fade and slide to complete
    $.when($container.promise(), $content.promise()).then(function () {
        $content.html(data);
        // Slide down and fadein (in sequence)
        $container.animate({
            height: 'show'
        }, 500, function () {
            $content.fadeTo('slow', 1.0);
        });
    });
});

JSFiddle: http://jsfiddle.net/TrueBlueAussie/pffm1tnb/4/

备注:

    单击处理程序中的
  • return falsee.stopPropagation() e.preventDefault() 的作用相同,因此您通常只需要其中之一。
  • 我从 @Pete 的 JSFiddle 开始,因为没有其他样本方便。谢谢皮特。

更新:

根据现在发布的完整代码,您将返回完整页面(包括页眉和正文标签)。如果您将代码更改为 .load(ahref + " #content" ),它将只提取您想要的部分。这与我提供的第二个(更好的)示例冲突,该示例需要返回的页面是部分页面(或仅提取所需的部分)。

补充更新:

作为$.get也returns一个jQuerypromise,你可以进一步简化为:

$.when($.get(ahref), $container.promise(), $content.promise()).then(function (data) {
    $content.html(data);
    // Slide down and fadein (in sequence)
    $container.animate({
        height: 'show'
    }, 500, function () {
        $content.fadeTo('slow', 1.0);
    });
});

传递给 $.when 的每个承诺的解析值按顺序传递给 then,因此传递的第一个参数将是 $.getdata承诺。

JSFiddle: http://jsfiddle.net/TrueBlueAussie/pffm1tnb/11/

使用大家在这里发布的一堆代码,我重写了原本必须效仿的部分。这是我现在的工作成果。

$(document).ready(function() {

// Start-Up Page Load (Cover, ToC, etc.)
$('#content').load('pages/page1.htm');

// Navigating Pages
$(document).on('click', 'a', function(e) {

    e.preventDefault();

    var ahref = $(this).attr('href');
    $('#content').fadeTo('slow', 0.0)
    $('#content_container').animate({height: 'hide'}, 500, function(){
        $('#content').load(ahref + '#content', function(){

            $('#content_container').animate({height: 'show'}, 500, function(){
                $('#content').fadeTo('slow', 1.0);
            });
        });
    });

    return false;

});

});