如何在加载远程 HTML 时正确延迟 jQuery 动画?
How do I properly delay jQuery animations when loading a remote HTML?
编辑:这个软件包是我在这里尝试修复的完整且未经修改的版本。问题出在 /data/renderpage.js 脚本中。在继续之前,请随意检查一下。
https://github.com/Tricorne-Games/HyperBook
非常感谢大家的帮助!
=
我正在完善 jQuery 脚本以按严格的顺序执行以下操作...
- 淡出文本。
- 缩小容器的大小div。
- 预加载遥控器 HTML /// 尚未显示!///
- 打开容器的大小div。
- 淡入新遥控器 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 false
与 e.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
,因此传递的第一个参数将是 $.get
的 data
承诺。
使用大家在这里发布的一堆代码,我重写了原本必须效仿的部分。这是我现在的工作成果。
$(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;
});
});
编辑:这个软件包是我在这里尝试修复的完整且未经修改的版本。问题出在 /data/renderpage.js 脚本中。在继续之前,请随意检查一下。
https://github.com/Tricorne-Games/HyperBook
非常感谢大家的帮助!
=
我正在完善 jQuery 脚本以按严格的顺序执行以下操作...
- 淡出文本。
- 缩小容器的大小div。
- 预加载遥控器 HTML /// 尚未显示!///
- 打开容器的大小div。
- 淡入新遥控器 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 false
与e.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
,因此传递的第一个参数将是 $.get
的 data
承诺。
使用大家在这里发布的一堆代码,我重写了原本必须效仿的部分。这是我现在的工作成果。
$(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;
});
});