4.4 创建自定义动画

除了预置的效果方法外,jQuery还提供了一个强大的.animate()方法,用于创建控制更加精细的自定义动画。.animate()方法有两种形式,第一种形式接收以下4个参数。

  • 一个包含样式属性及值的对象:与本章前面讨论的.css()方法中的参数类似。

  • 可选的时长参数:既可以是预置的字符串,也可以是毫秒数值。

  • 可选的缓动(easing)类型:现在我们先不介绍,这是第11章中将要讨论的一个高级选项。

  • 可选的回调函数:将在本章后面讨论。

把这4个参数放到一起,结果如下所示:

  1. .animate({property1: 'value1', property2: 'value2'},
  2. duration, easing, function() {
  3. alert('The animation is finished.');
  4. }
  5. );

第二种形式接受两个参数,一个属性对象和一个选项对象:

  1. .animate({properties}, {options})

实际上,这里的第二个参数是把第一种形式的第2~4个参数封装在了另一个对象中,同时又添加了两个选项。考虑到可读性并调整了换行之后,调用第二种形式的方法的代码如下:

  1. .animate({
  2. property1: 'value1',
  3. property2: 'value2'
  4. }, {
  5. duration: 'value',
  6. easing: 'value',
  7. specialEasing: {
  8. property1: 'easing1',
  9. property2: 'easing2'
  10. },
  11. complete: function() {
  12. alert('The animation is finished.');
  13. },
  14. queue: true,
  15. step: callback
  16. });

现在,我们使用第一种形式的.animate()方法,但在本章后面介绍排队效果时会使用其第二种形式。

4.4.1 手工创建效果

现在,我们已经介绍了几个用于显示和隐藏元素的预定义方法。为了讨论.animate()方法,有必要看一看怎么通过这个低级接口来实现与调用.slideToggle()相同的效果。在此,我们把前面例子中调用.slideToggle()方法的代码替换成了自定义动画代码,参见代码清单4-13。

代码清单4-13

  1. $(document).ready(function() {
  2. var $firstPara = $('p').eq(1);
  3. $firstPara.hide();
  4. $('a.more').click(function(event) {
  5. event.preventDefault();
  6. $firstPara.animate({height: 'toggle'}, 'slow');
  7. var $link = $(this);
  8. if ($link.text() == 'read more') {
  9. $link.text('read less');
  10. } else {
  11. $link.text('read more');
  12. }
  13. });
  14. });

 这对于.slideToggle()来说并不是一个非常恰当的例子。该方法实际也可以对元素的内外边距加以变换。

通过这个例子可以看出,.animate()方法针对CSS属性提供了方便简写值:'show''hide''toggle',以便在简写方法不适用时提供另一种简化.slideToggle()等内置效果方法的方式。

4.4.2 一次给多个属性添加动画效果

使用.animate()方法可以同时修改多个CSS属性。例如,要在切换第二个段落时,创建一个同时具有滑动和淡入淡出效果的动画,只需在.animate()方法的属性对象参数中添加一个height属性值—对即可,参见代码清单4-14。

代码清单4-14

  1. $(document).ready(function() {
  2. var $firstPara = $('p').eq(1);
  3. $firstPara.hide();
  4. $('a.more').click(function(event) {
  5. event.preventDefault();
  6. $firstPara.animate({
  7. opacity: 'toggle',
  8. height: 'toggle'
  9. }, 'slow');
  10. var $link = $(this);
  11. if ($link.text() == 'read more') {
  12. $link.text('read less');
  13. } else {
  14. $link.text('read more');
  15. }
  16. });
  17. });

此外,不仅可以在简写效果方法中使用样式属性,也可以使用其他CSS属性,如:lefttopfontSizemarginpaddingborderWidth。还记得改变演讲段落文本大小的脚本吗?要实现同样的文本大小变化动画,只要把.css()方法替换成.animate()方法即可,参见代码清单4-15。

代码清单4-15

  1. $(document).ready(function() {
  2. var $speech = $('div.speech');
  3. var defaultSize = $speech.css('fontSize');
  4. $('#switcher button').click(function() {
  5. var num = parseFloat($speech.css('fontSize'));
  6. switch (this.id) {
  7. case 'switcher-large':
  8. num *= 1.4;
  9. break;
  10. case 'switcher-small':
  11. num /= 1.4;
  12. break;
  13. default:
  14. num = parseFloat(defaultSize);
  15. }
  16. $speech.animate({fontSize: num + 'px'}, 'slow');
  17. });
  18. });

再使用其他属性,则可以创造出更复杂的效果。例如,可以在把某个项从页面左侧移动到右侧的同时,让该项的高度增加20像素并使其边框宽度增加到5像素。下面,我们就把这个效果应用于<div id="switcher">盒子。图4-8显示了应用效果之前的画面。

4.4 创建自定义动画 - 图1

图 4-8

在可变宽度的布局中,需要计算盒子在与页面右侧对齐之前应该移动的距离。假设段落宽度为100%,可以从段落宽度中减去Text Size盒子的宽度。我们使用jQuery的.outWidth()方法来计算宽度,包括内边距及边框宽度。我们还使用这个方法计算转换器新的left属性。对于这个例子而言,我们打算通过单击按钮上面的Text Size文本来触发动画,参见代码清单4-16。

代码清单4-16

  1. $(document).ready(function() {
  2. $('div.label').click(function() {
  3. var paraWidth = $('div.speech p').outerWidth();
  4. var $switcher = $(this).parent();
  5. var switcherWidth = $switcher.outerWidth();
  6. $switcher.animate({
  7. borderWidth: '5px',
  8. left: paraWidth - switcherWidth,
  9. height: '+=20px'
  10. }, 'slow');
  11. });
  12. });

在此,有必要详细解释一下这些动画属性。首先,borderWidth属性很明显,只要给它指定一个常量值加一个单位即可,就像在样式表中一样。其次,left属性是计算的数值。这些属性值的单位后缀是可选的,如果不指定,就会默认以px作为单位。最后,height属性使用我们以前没有遇到过的语法,其中属性值前面的+=操作符表示相对值。在这里表示的意思不是以动画方式变化到20像素,而是在原来基础上再以动画方式变化20像素。因为涉及特殊字符问题,所以必须以字符串形式指定相对值,也就是说必须把值放到一对括号内。

此时的代码虽然能够增加相应<div>的高度,并加宽其边框,但还不能改变其left位置属性。此时外观如图4-9所示。

4.4 创建自定义动画 - 图2

图 4-9

最终,还是需要通过修改CSS来支持对位置属性的修改。

通过CSS定位

在使用.animate()方法时,必须明确CSS对我们要改变的元素所施加的限制。例如,在元素的CSS定位没有设置成relativeabsolute的情况下,调整left属性对于匹配的元素毫无作用。所有块级元素默认的CSS定位属性都是static,这个值精确地表明:在改变元素的定位属性之前试图移动它们,它们只会保持静止不动。

 要了解与绝对(absolute)和相对(relative)定位有关的更多信息,请参考Joe Gillespie的文章“Absolutely Relative”(http://www.wpdfd.com/issues/78/absolutely_relative/)。

打开样式表,我们注意到其中已经为<div id="switcher">容器和个别的按钮设置了相对的定位:

  1. #switcher {
  2. position: relative;
  3. }

不过,我们要演示的还是使用JavaScript来根据需要修改这个属性,以便了解jQuery的功能,参见代码清单4-17。

代码清单4-17

  1. $(document).ready(function() {
  2. $('div.label').click(function() {
  3. var paraWidth = $('div.speech p').outerWidth();
  4. var $switcher = $(this).parent();
  5. var switcherWidth = $switcher.outerWidth();
  6. $switcher.css({
  7. position: 'relative'
  8. }).animate({
  9. borderWidth: '5px',
  10. left: paraWidth - switcherWidth,
  11. height: '+=20px'
  12. }, 'slow');
  13. });
  14. });

在有了CSS的定位支持之后,单击Text Size,最终完成的效果将如图4-10所示。

4.4 创建自定义动画 - 图3

图 4-10