4.5.2 处理多组元素
4.5.2 处理多组元素
与一组元素的情况不同,当为不同组的元素应用效果时,这些效果几乎会同时发生。为了示范这种并发的效果,我们可以在向上滑出一个段落时,向下滑入另一个段落。首先,要用到示例文档中的如下三、四段文本:
接着,为了更清楚地看到效果发生期间的变化,我们为第三段和第四段分别添加1像素宽的边框和灰色的背景。同时,在DOM
就绪时立即隐藏第4段,参见代码清单4-23。
1 | $(document).ready(function() { |
这样,示例文档会显示开始的段落,然后是read more
链接和带边框的段落,如图4-11所示。
最后,为第三段添加click
处理程序,以便单击它时会将第3段向上滑(最终滑出视图) ,同时将第4段向下滑(最终滑入视图),参见代码清单4-24。
通过截取到的这两个滑动效果变化过程中的屏幕截图,如图4-12所示,可以证实,它们确实是同时发生的。
原来可见的第三个段落,正处于向上滑到一半的状态;与此同时,原来隐藏的第四个段落,正处于向下滑到一半的状态。
排队回调函数
为了对不同元素上的效果实现排队,jQuery
为每个效果方法都提供了回调函数。同我们在事件处理程序和.queue()
方法中看到的一样,回调函数就是作为方法的参数传递的一个普通函数。在效果方法中,它们是方法的最后一个参数。
当使用回调函数排队两个滑动效果时,可以在第3个段落滑上之前,先将第4个段落滑下。首先,我们看一看怎样通过回调函数设置.slideDown()
方法,如代码清单4-25所示。
1 | $(document).ready(function() { |
不过,这里我们需要注意的是,必须搞清楚要滑上的到底是哪个段落。因为回调函数位于.slideDown()
方法中,所以$(this)
的环境已经发生了改变。现在,$(this)
已经不再是指向.click()
的第三个段落了——由于.slideDown()
方法是通过$(this).next()
调用的,所以该方法中的一切现在都将$(this)
视为下一个同辈元素,即第四个段落。因而,如果在回调函数中放入$(this).slideUp('slow')
, 那么我们最终还会把刚刚显示出来的段落给隐藏起来。
可靠地引用$(this)
的一种简单方法,就是在.click()
方法内部把它保存到一个变量中,比如var
$ clickedItem
= $(this)
。
这样,无论是在回调函数的外部还是内部,$clickedItem
引用的都是第三个段落。使用了新变量之后的代码,参见代码清单4-26。
1 | $(document).ready(function() { |
这次效果中途的屏幕截图如图4-13所示,第三段和第四段同时都是可见的,而且,第四段已经完成下滑,第三段刚要开始上滑。
既然讨论了回调函数,那么就可以回过头来基于代码清单4-22解决在接近一系列效果结束时改变背景颜色的问题了。这次,我们不像前面那样使用.queue()
方法,而是使用回调函数,如代码清单4-27所示。
1 | $(document).ready(function() { |
同前面一样,<div id="switcher">
的背景颜色在它滑上之后滑下之前,变成了红色。注意,在使用交互的完成回调函数而不是.queue()
时,不必在回调中调用next()
。
4.5 并发与排队效果 4.5.1 处理一组元素
4.5 并发与排队效果
通过刚才的例子,可以看出.animate()
方法在为一组特定的元素创建并发效果时非常有用。然而,有的时候我们需要的则是排队效果,即让效果一个接一个地发生。
4.5.1 处理一组元素
当为同一组元素应用多重效果时,可以通过连缀这些效果轻易地实现排队。为了示范排队效果,我们仍以代码清单4-17为例,移动Text Size
盒子、增加其高度、加宽其边框。不过,这次我们相继地执行这三个效果——很简单,只要把它们分别放在.animate()
方法中并连缀起来即可,参见代码清单4-18。
1 | $(document).ready(function() { |
虽然连缀允许我们把这两个.animate()
方法放在同一行,但为了更好的可读性,这里故意将它们分开放在了各自的一行中。
通过使用连缀,可以对其他任何jQuery
效果进行排队,而并不限于.animate()
方法。比如说,我们可以按照下列顺序对<div id="switcher">
上的效果进行排队。
(1) 通过.fadeTo()
将其不透明度减退为0.5。
(2) 通过.animate()
将其移动到右侧。
(3) 通过.fadeTo()
将其渐增回完全不透明。
(4) 通过.slideUp()
隐藏它。
(5) 通过.slideDown()
再将其显示出来。
我们所要做的,就是在代码中按照相同的顺序连缀这些效果,如代码清单4-19所示。
1 | $(document).ready(function () { |
1. 越过队列
不过,要是想在这个<div>
不透明度减退至一半的同时,把它移动到右侧应该怎么办呢?如果两个动画以相同速度执行,则可以简单地把它们组合到一个.animate()
方法中。但这个例子中的.fadeTo()
使用的速度字符串是’fast'
,而向右移动的动画使用的速度字符串是’slow'
。在这种情况下,第二种形式的.animate()
方法又可以派上用场了,参见代码清单4-20。
1 | $(document).ready(function() { |
第二个参数(即选项对象)包含了queue
选项,把该选项设置为false
即可让当前动画与前一个动画同时开始。
2. 手工队列
有关为一组元素应用排队效果的最后一个需要注意的问题,就是排队不能自动应用到其他的非效果方法,如.css()
。下面,假设我们想在.slideUp()
执行后但在.slideDown()
执行前,把<div id="switcher">
的背景颜色修改为红色,可以尝试像代码清单4-21这样来做。
然而,即使把修改背景颜色的代码放在连缀序列中正确的位置上,它也会在单击后立即执行。把非效果方法添加到队列中的一种方式,就是使用.queue()
方法。代码清单4-22就是在这个例子中使用.queue()
方法的代码片段。
1 | $(document).ready(function () { |
像这样传递一个回调函数,.queue()
方法就可以把该函数添加到相应元素的效果队列中。在这个函数内部,我们把背景颜色设置为红色,然后又调用了next()
方法,其返回的结果将作为参数传给回调函数。添加的这个next
()方法可以让队列在中断的地方再接续起来,然后再与后续的.slideDown('slow')
连缀在一起。如果在此不使用next()
方法,动画就会中断。
在下面讨论多组元素的效果之后,我们会介绍另一种向队列中添加非效果方法的方式。
4.4 创建自定义动画
4.4 创建自定义动画
除了预置的效果方法外,jQuery
还提供了一个强大的.animate()
方法,用于创建控制更加精细的自定义动画。
animate方法类型
.animate()
方法有两种形式,第一种形式接收以下4个参数。
- 一个包含样式属性及值的
对象
:与本章前面讨论的.css()
方法中的参数类似。 - 可选的
时长
参数:既可以是预置的字符串,也可以是毫秒数值。 - 可选的
缓动
(easing
)类型:现在我们先不介绍,这是第11章中将要讨论的一个高级选项。 - 可选的
回调函数
:将在本章后面讨论。把这4个参数放到一起,结果如下所示:1
2
3
4
5.animate({property1: 'value1', property2: 'value2'},
duration, easing, function() {
alert('The animation is finished.');
}
);类型2
第二种形式接受两个参数,一个属性对象
和一个选项对象
:实际上,这里的第二个参数是把第一种形式的第2~4个参数封装在了另一个对象中,同时又添加了两个选项。考虑到可读性并调整了换行之后,调用第二种形式的方法的代码如下:1
.animate({properties}, {options})
现在,我们使用第一种形式的1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21.animate(
{
property1: 'value1',
property2: 'value2'
},
{
duration: 'value',
easing: 'value',
specialEasing:
{
property1: 'easing1',
property2: 'easing2'
},
complete: function ()
{
alert('The animation is finished.');
},
queue: true,
step: callback
}
);.animate()
方法,但在本章后面介绍排队效果时会使用其第二种形式。4.4.1 手工创建效果
现在,我们已经介绍了几个用于显示和隐藏元素的预定义方法。为了讨论.animate()
方法,有必要看一看怎么通过这个低级接口来实现与调用.slideToggle()
相同的效果。在此,我们把前面例子中调用.slideToggle()
方法的代码替换成了自定义动画代码,参见代码清单4-13。通过这个例子可以看出,1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33$(document).ready(function() {
var $speech = $('div.speech');
var defaultSize = $speech.css('fontSize');
$('#switcher button').click(function() {
var num = parseFloat($speech.css('fontSize'));
switch (this.id) {
case 'switcher-large':
num *= 1.4;
break;
case 'switcher-small':
num /= 1.4;
break;
default:
num = parseFloat(defaultSize);
}
$speech.css('fontSize', num + 'px');
});
var $firstPara = $('p').eq(1);
$firstPara.hide();
$('a.more').click(function(event) {
event.preventDefault();
// 自定义动画
$firstPara.animate({height: 'toggle'}, 'slow');
var $link = $(this);
if ($link.text() == 'read more') {
$link.text('read less');
} else {
$link.text('read more');
}
});
});.animate()
方法针对CSS
属性提供了方便简写值:'show'
、'hide'
和'toggle'
, 以便在简写方法不适用时提供另一种简化.slideToggle()
等内置效果方法的方式。4.4.2 一次给多个属性添加动画效果
使用.animate()
方法可以同时修改多个CSS
属性。例如,要在切换第二个段落时,创建一个同时具有滑动和淡入淡出效果的动画,只需在.animate()
方法的属性对象参数中添加一个opacity
属性值对即可,参见代码清单4-14。此外,不仅可以在简写效果方法中使用样式属性,也可以使用其他1
2
3
4
5
6
7
8
9
10
11
12
13
14
15var $firstPara = $('p').eq(1);
$firstPara.hide();
$('a.more').click(function (event) {
event.preventDefault();
$firstPara.animate({
opacity: 'toggle',
height: 'toggle'
}, 'slow');
var $link = $(this);
if ($link.text() == 'read more') {
$link.text('read less');
} else {
$link.text('read more');
}
});CSS
属性,如:left
、top
、fontSize
、margin
、padding
和borderWidth
。还记得改变演讲段落文本大小的脚本吗?要实现同样的文本大小变化动画,只要把.css()
方法替换成.animate()
方法即可,参见代码清单4-15。再使用其他属性,则可以创造出更复杂的效果。例如,可以在把某个项从页面左侧移动到右侧的同时,让该项的高度增加20像素并使其边框宽度增加到5像素。下面,我们就把这个效果应用于1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18$(document).ready(function() {
var $speech = $('div.speech');
var defaultSize = $speech.css('fontSize');
$('#switcher button').click(function() {
var num = parseFloat($speech.css('fontSize'));
switch (this.id) {
case 'switcher-large':
num *= 1.4;
break;
case 'switcher-small':
num /= 1.4;
break;
default:
num = parseFloat(defaultSize);
}
$speech.animate({fontSize: num + 'px'}, 'slow');
});
});<div id="switcher">
盒子。图4-8显示了应用效果之前的画面。
在可变宽度的布局中,需要计算盒子在与页面右侧对齐之前应该移动的距离。假设段落宽度为100%,可以从段落宽度中减去Text Size
盒子的宽度。我们使用jQuery
的.outWidth()
方法来计算宽度,包括内边距及边框宽度。我们还使用这个方法计算转换器新的left
属性。对于这个例子而言,我们打算通过单击按钮上面的Text Size
文本来触发动画,参见代码清单4-16。在此,有必要详细解释一下这些动画属性。首先,1
2
3
4
5
6
7
8
9
10
11
12$(document).ready(function() {
$('div.label').click(function() {
var paraWidth = $('div.speech p').outerWidth();
var $switcher = $(this).parent();
var switcherWidth = $switcher.outerWidth();
$switcher.animate({
borderWidth: '5px',
left: paraWidth - switcherWidth,
height: '+=20px'
}, 'slow');
});
});borderWidth
属性很明显,只要给它指定一个常量值加一个单位即可,就像在样式表中一样。其次,left
属性是计算的数值。这些属性值的单位后缀是可选的,如果不指定,就会默认以px作为单位。最后,height
属性使用我们以前没有遇到过的语法,其中属性值前面的+=
操作符表示相对值。在这里表示的意思不是以动画方式变化到20像素,而是在原来基础上再以动画方式变化20像素。因为涉及特殊字符问题,所以必须以字符串形式指定相对值,也就是说必须把值放到一对括号内。
4.3.4 切换可见性
4.3.4 切换可见性
有时候,我们需要切换某些元素的可见性,而不像前面例子中那样只把它们显示出来。要实现切换,可以先检查匹配元素的可见性,然后再添加适当的方法。在此,仍然以淡入淡出效果为例,可以把示例脚本修改为如代码清单4-11所示。
1 | $(document).ready(function() { |
与我们在本章前面所做的一样,首先缓存选择符以避免重复遍历DOM
。而且,这里也不再隐藏被单击的链接,而是修改它的文本。
使用if else
语句切换元素的可见性是非常自然的方式。但通过jQuery
复合效果方法,却不一定非要使用这个条件语句(尽管在这个例子中,需要条件语句来修改链接的文本) 。
jQuery
提供了一个.toggle()
方法,该方法的作用类似于.show()
和.hide()
方法,而且与它们一样的是,.toggle()
方法时长参数也是可选的。
另一个复合方法是.slideToggle()
,该方法通过逐渐增加或减少元素高度来显示或隐藏元素。代码清单4-12是使用.slideToggle()
方法的脚本。
如何切换可见性
1.使用if else
语句判断可见性,然后在调用显示,或隐藏方法实现
2.使用jQuery
事项的方法实现,如下所示:
.toggle()
方法可以可以切换显示/隐藏
效果,可以理解为:交替执行.show()
和.hide()
这两个方法..slideToggle()
方法可以切换滑上/滑下
效果,可以理解为:交替执行:.slideDown()
和.slideUp()
这两个方法.fadeToggle()
方法可以切换淡入/淡出
效果,可以理解为交替执行.fadeIn(),.fadeOut()
这两个方法
4.3.3 滑上和滑下
4.3.3 滑上和滑下
文档流之外的元素适合淡入淡出
对于本来就处于文档流之外的元素,比较适合使用淡入和淡出动画。例如,对于那些覆盖在页面之上的”亮盒”元素来说,采用淡入和淡出就显得很自然。
不过,假如某个元素本来就处在文档流中,那再调用.fadeIn()
就会导致文档”跳一下”,以便为新元素腾出地方来。但这种跳跃感在用户眼里就不总是那么美观了。
滑上滑下
,假如某个元素本来就处在文档流中,使用jQuery
的.slideDown()
和.slideUp()
方法通常是正确的选择。这两个动画方法仅改变元素的高度。要让段落以垂直滑入的效果出现,可以像代码清单4-10这样调用.slideDown('slow')
。
1 | $(document).ready(function() { |
要实现相反的动画效果,应该调用.slideUp()
。
两个方法的效果
.slideDown()
向下滑动,最终的效果是显示..slideUp()
向上滑动,最终的效果是隐藏
4.3.2 淡入和淡出
4.3.2 淡入和淡出
虽然使用.show()
和.hide()
方法在某种程度上可以创造漂亮的效果,但其效果有时候也可能会显得过于花哨。考虑到这一点,jQuery
也提供了两个更为精细的内置动画方法。
逐渐地增大不透明度
如果想在显示整个段落时,只是逐渐地增大其不透明度,那么可以使用.fadeIn('slow')
方法,.fadeIn()
方法会在一开始设置段落的尺寸,以便内容能够逐渐显示出来。
逐渐减少不透明度
类似地,要逐渐减少不透明度,可以使用.fadeOut()
方法。
两个方法的效果
.fadeIn()
方法淡入,表示慢慢的进入显示器,也就是显示的意思.fadeOut()
方法表示淡出,表示慢慢的移出显示器,也就是隐藏的意思