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

时间:2015-03-11 09:58:41

标签: javascript jquery html css animation

编辑:这个软件包是我试图解决的完整和未完整版本。问题出在/data/renderpage.js脚本中。在继续之前,请随意检查。

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

我非常感谢所有帮助人员!

=

我正在抛出一个jQuery脚本,以严格的顺序执行以下操作......

  1. 淡出文字。
  2. 缩小容器div的大小。
  3. 预加载远程HTML ///而不显示它!///
  4. 打开容器div的大小。
  5. 淡入新的远程HTML。
  6. 我不介意步骤1和2,4和5是否合并为一整步(同时淡化/调整大小)。加载新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()函数,但它并没有解决阻止新文本的问题。

5 个答案:

答案 0 :(得分:2)

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可能比淡出/滑动更快完成,并且过早显示新数据。在这种情况下,您不想使用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也会返回jQuery promise,您可以将其进一步简化为:

$.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,因此传递的第一个参数将是data承诺中的$.get

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

答案 1 :(得分:0)

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

$(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()

答案 2 :(得分:0)

您可以使用get()函数及其回调参数将HTML保存到变量中,然后将其实际放入具有html()的元素中,而不是使用load()函数。 / p>

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

$.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.
});

答案 3 :(得分:0)

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

$(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;

});

});

答案 4 :(得分:-1)

您可以使用延迟或回调功能     $(document).on('click','a',function(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;

});