人们很容易低估动画对于任何现代、精致的 web 应用程序的重要性。有时,浪费时间添加动画似乎很无聊,几乎是无缘无故的,因为它们似乎没有向应用程序添加任何内容。但是对于用户来说,动画有着巨大的不同。它们有助于简化从一个应用程序状态到下一个应用程序状态的转换。它们还有助于给用户一种位置感。当用户单击导致页面向左移动的按钮并单击另一个按钮导致页面向右移动时,用户从动画中获得位置感。在本章中,我们将学习如何使用 jQuery 动画和效果使我们的网站变得时髦。
我们将讨论以下主题:
- 动画的重要性
- 隐藏和显示元素
- 滑动元件
- 创建自定义效果
- 正确使用效果
作为开发人员,我们很容易忘记应用程序的抽象程度。主页的概念已经嵌入到我们的开发者头脑中,但与其他页面相比,我们网站的一个页面并没有什么真正的家。但是,如果所有其他页面都集中在一个页面上,甚至没有对其进行标记,那么在大多数用户眼中,这就是主页。
动画效果有助于从一个应用程序状态过渡到下一个应用程序状态。如果没有动画,在页面中添加或删除元素时很容易丢失。诀窍在于熟练使用动画。动画不应该让人觉得它们妨碍了用户实现目标。
让我们看一下 jQuery 中的两个最有用的动画:hide
和show
。jQuery 为我们提供了.hide()
和.show()
方法,它们完全按照它们的名称进行操作。开箱即用,这两种方法不会设置动画;它们充当简单的开关,立即隐藏或显示附加的元素集。然而,它们都有几种方法可以调用。首先,让我们看看 AUTT4 方法,然后看看它的同伴,AUTT5 方法。
在最基本的模式下,调用.hide()
方法时不带参数,如下所示:
$(elements).hide();
这样调用时,它会立即隐藏指定的元素集。在内部,jQuery 向属性为“display: none
”的元素添加了一个样式属性。这意味着元素是不可见的,并且在 DOM 中放弃了它的空间。.hide()
方法也接受可选参数:
$(elements).hide(duration, easing, complete);
第一个参数是持续时间。它可以是字符串或整数。如果它是整数,则是完成动画所需的毫秒数。如果是字符串,则必须是为持续时间提供的两个方便名称中的一个,即fast
或slow
。快相当于 200 毫秒,慢相当于 600 毫秒。
在其基本模式下,也调用了无参数的.show()
方法,如下所示:
$(elements).show();
这样调用时,它将立即显示指定的元素集。jQuery 将删除属性为“display: none;
”的 style 属性。.show()
方法接受与.hide()
方法相同的参数。
让我们更实际地看看使用这些方法:
<body>
<div>
<button id="hide">Hide Pics</button>
<button id="show">Show Pics</button>
</div>
<div id="allPictures">
<img id="picture1" src="http://lorempixel.com/160/100/nature/1" class="thumbnail"/>
<img id="picture2" src="http://lorempixel.com/160/100/nature/2" class="thumbnail"/>
<img id="picture3" src="http://lorempixel.com/160/100/nature/3" class="thumbnail"/>
<img id="picture4" src="http://lorempixel.com/160/100/nature/4" class="thumbnail"/>
</div>
<script type="text/javascript">
$(document).ready(function () {
var $hide = $('#hide'),
$show = $('#show'),
$allPictures = $('#allPictures');
$hide.click(function () {
$allPictures.hide();
});
$show.click(function () {
$allPictures.show();
});
});
</script>
在我们的示例应用程序中,我们有四个由超级有用的站点 lorempixel(提供的缩略图图像 http://lorempixel.com 。Lorem pixel 为 web 设计师提供占位符图像,用于构建网站。这些图像不应用于生产。
占位符 URL 由宿主站点组成,后跟所需图像的宽度和高度(以像素为单位)。其次是图像的类别;在我们的例子中,它是nature
,最后的数字表示一张特定的图片。关于如何为占位符图像创建自己的 URL,在 lorem pixel 网站上有详细信息。
图像上方是一组按钮,用于触发缩略图上的操作。按钮缓存在$hide
和$show
变量中。单击“隐藏”按钮时,我们隐藏图像。单击 show 按钮时,我们会执行相反的操作并显示图像。注意我们缓存 jQuery 对象的方式,将它们存储在 JavaScript 对象中,而不是再次查找它们。缓存它们可以提高再次使用它们时的速度。在这个小应用程序中,这没有什么区别,但它可以在更复杂的应用程序中显著提高速度。我们将在第 7 章与您的服务器交谈中对此进行更详细的讨论。
为了更容易地知道哪些变量包含 jQuery 对象,我们采用了以美元符号开始这些变量的标准,$
。一些开发人员不喜欢在变量名中使用助记符,但我发现这很有帮助,尤其是在阅读团队中其他开发人员编写的代码时。
hide
和show
是如此的密切相关,以至于 jQuery 有一个特殊的方法来执行这两者。.toggle()
方法将在显示元素时隐藏元素,并在隐藏元素时显示元素。这是一种更适合我们用例的方法,因此让我们修改代码:
$(document).ready(function () {
var $hide = $('#hide'),
$show = $('#show'),
$toggle = $('#toggle'),
$allPictures = $('#allPictures');
$hide.click(function () {
$allPictures.hide();
});
$show.click(function () {
$allPictures.show();
});
$toggle.click(function () {
$allPictures.toggle();
});
});
我们只需要修改几行代码。首先,我们需要一个变量来保持切换按钮。然后,我们添加代码来钩住切换按钮的点击,最后,我们调用了.toggle()
方法。切换按钮的一个优点是,我们可以连续单击它,它将继续切换图片的状态。
隐藏和展示这些图片很有趣,但并不令人激动。那么,让我们为代码添加持续时间。以下是对应用程序的修改:
$(document).ready(function () {
var $hide = $('#hide'),
$show = $('#show'),
$toggle = $('#toggle'),
$allPictures = $('#allPictures');
$hide.click(function () {
$allPictures.hide('slow');
});
$show.click(function () {
$allPictures.show('fast');
});
$toggle.click(function () {
$allPictures.toggle(1500);
});
});
这一次,我们只对三行进行了更改。每行调用一个 effect 方法。我们将slow
传递给.hide()
方法;fast
传递给.show()
方法;1500
传递给.toggle()
方法。记住,当一个整数被传递给一个 effect 方法时,它是以毫秒为单位的时间,所以 1500 表示 1.5 秒。
给我们目前的效果添加一些持续时间比简单地打开和关闭元素更吸引人,但是让图像淡入淡出而不是缩小和增长可能会更好。幸运的是,jQuery 为我们介绍了一些方法,它们可以做到这一点:淡出和淡入。
.fadeOut()
方法逐渐将 CSS 不透明属性降低到 0,使元素不再可见,然后将显示属性设置为none
。此方法的参数与.hide()
相同。
.fadeIn()
方法与.fadeOut()
方法相反。它首先将“显示”属性设置为将“不透明度”属性增加为 1,以便元素完全不透明。
与.toggle()
方法一样,.fadeToggle()
方法将淡出可见的元素,淡入不可见的元素。
对于更实际的示例,让我们分别用.fadeOut()
、.fadeIn()
和.fadeToggle()
替换.hide()
、.show()
和.toggle()
方法:
$(document).ready(function () {
var $hide = $('#hide'),
$show = $('#show'),
$toggle = $('#toggle'),
$allPictures = $('#allPictures');
$hide.click(function () {
$allPictures.fadeOut('slow');
});
$show.click(function () {
$allPictures.fadeIn('fast');
});
$toggle.click(function () {
$allPictures.fadeToggle(1500);
});
});
在前面的代码中,我们用它们的淡入淡出等价物替换了 hide/show 方法。代码仍然像以前一样工作,只是现在,我们有了一个新的动画效果:淡入淡出。
到目前为止,我们只使用了 duration 参数,但我们知道还有两个参数:easing
和complete
。我们先来看看complete
,因为它很容易理解。
complete 参数是动画完成后调用的函数。它不会显式地传递任何参数,但会隐式地传递指向动画元素的this
对象。通过对示例程序进行一个小的修改,我们可以看到这一点:
$toggle.click(function () {
$allPictures.fadeToggle(1500, function () {
alert("Hola: "+this.id);
});
});
在持续时间之后,我们添加一个内联匿名函数,该函数在动画完成后调用。this
对象指向动画元素,因此我们在警报消息框中显示其id
。每个动画元素调用一次完整的函数,这可能会让人惊讶。在我们当前的示例中,我们正在为保存图像的<div>
的内容设置动画。请考虑将代码更改为以下内容:
$toggle.click(function () {
$('img').fadeToggle(1500, function () {
alert("Hola: "+this.id);
});
});
通过将代码更改为指向单个<img>
标记而不是其父<div>
容器,现在为每个标记调用一次完整的函数,我们将看到警报逐个遍历<img>
标记。
easing 参数处理动画对象的移动方式。在现实世界中,对象很少以恒定速度移动。想象一列火车离开车站。当它离开时,它慢慢地加快速度。它慢慢地加速,直到达到它想要的速度,然后在某一点上,当它接近下一站时,它将开始减速。如果我们要画出火车的速度,它将是一条曲线,而不是一条直线。物体的加速和减速对我们来说似乎很自然,因为这是自然界事物的运动方式,无论是火车、猎豹追逐羚羊,还是我们从桌子上起来拿一杯水。
开箱即用的 jQuery 有两个度量:默认的一个名为 swing,另一个名为 linear。到目前为止,我们在所有示例中都使用了 swing,因为它是默认的。让我们也来看看 linear 并比较一下这两个:
<div>
<button id="hide">Hide Pics</button>
<button id="show">Show Pics</button>
<button id="toggleSwing">Toggle Swing Pics</button>
<button id="toggleLinear">Toggle Linear Pics</button>
</div>
<div id="allPictures">
<img id="picture1" src="http://lorempixel.com/160/100/nature/1" class="thumbnail"/>
<img id="picture2" src="http://lorempixel.com/160/100/nature/2" class="thumbnail"/>
<img id="picture3" src="http://lorempixel.com/160/100/nature/3" class="thumbnail"/>
<img id="picture4" src="http://lorempixel.com/160/100/nature/4" class="thumbnail"/>
</div>
<script type="text/javascript">
$(document).ready(function () {
var $hide = $('#hide'),
$show = $('#show'),
$toggleSwing = $('#toggleSwing'),
$toggleLinear = $('#toggleLinear'),
$allPictures = $('#allPictures');
$hide.click(function () {
$allPictures.fadeOut('slow');
});
$show.click(function () {
$allPictures.fadeIn('fast');
});
$toggleSwing.click(function () {
$allPictures.fadeToggle(1500, "swing");
});
$toggleLinear.click(function () {
$allPictures.fadeToggle(1500, "linear");
});
});
</script>
在前面的代码中,我们去掉了切换按钮,并将其替换为两个新的切换:一个使用"swing"
,另一个使用"linear"
。我们还创建了两个事件处理程序来实现适当的淡入和淡出。虽然这两种评价之间的差别很微妙,但确实存在。当对象四处移动时,它更为明显。因此,在下一节中,我们将介绍幻灯片动画,并看看我们的两个赛季是如何看待它的。
接下来的方法集的调用与前两个方法集一样。“幻灯片”方法与“显示”和“隐藏”方法非常相似,不同之处在于不缩小和增大集合元素的宽度和高度尺寸,只更改高度。
.slideUp()
方法将元素集的高度缩小为零,然后将显示属性设置为none
。该方法采用已经讨论过的三个可选参数:duration
、easing
和complete
:
$(elements).slideUp([duration],[easing], [complete]);
.slideDown()
方法将元素集的高度增加到 100%。它的调用如下所示:
$(elements).slideDown([duration],[easing], [complete]);
该集合的最后一个成员是.slideToggle()
方法,它将在显示和隐藏状态之间交替元素集合:
$(elements).slideDown([duration],[easing], [complete]);
我们已经修改了我们的代码,使用 slide 方法而不是 fade 方法。现在,宽松的方式明显不同了。以下是更改后的代码:
$hide.click(function () {
$allPictures.slideUp('slow');
});
$show.click(function () {
$allPictures.slideDown('fast');
});
$toggleSwing.click(function () {
$allPictures.slideToggle(1500, "swing");
});
$toggleLinear.click(function () {
$allPictures.slideToggle(1500, "linear");
});
由于 jQuery 动画方法的调用方式都是类似的,因此我们可以简单地将单词fadeOut
、fadeIn
和fadeToggle
替换为它们的幻灯片等价物。
我认为我们已经花了足够的时间研究基本的动画效果。真正有趣和图形化的魔兽世界在于定制效果。
jQuery 没有包含很多效果;开箱即用,只有隐藏和显示、淡入和淡出以及幻灯片方法。如果这些都是它所能包含的,它可能不值得把它们放在图书馆里。幸运的是,jQuery 允许我们创建自己的动画。
理解方法是理解如何创建自定义效果的关键。虽然其他方法很重要,但在动画方法工作之前,它们都不会做任何事情,幸运的是,这并不难,特别是如果您记住动画属性实际上是如何工作的。它通过操纵 CSS 属性的值来工作。大多数但并非所有属性都可以操纵。让我们快速查看一下,以便更好地解释如何使用 Ty1 T1 方法:
<div>
<button id="hide">Hide Pics</button>
<button id="show">Show Pics</button>
<button id="toggleSwing">Animate Swing Pics</button>
<button id="toggleLinear">Animate Linear Pics</button>
</div>
<div id="allPictures" style="position: relative;">
<img id="picture1" src="http://lorempixel.com/160/100/nature/1" class="thumbnail"/>
<img id="picture2" src="http://lorempixel.com/160/100/nature/2" class="thumbnail"/>
<img id="picture3" src="http://lorempixel.com/160/100/nature/3" class="thumbnail"/>
<img id="picture4" src="http://lorempixel.com/160/100/nature/4" class="thumbnail"/>
</div>
<script type="text/javascript">
$(document).ready(function () {
var $hide = $('#hide'),
$show = $('#show'),
$toggleSwing = $('#toggleSwing'),
$toggleLinear = $('#toggleLinear'),
$allPictures = $('#allPictures');
$hide.click(function () {
$allPictures.slideUp('slow');
});
$show.click(function () {
$allPictures.slideDown('fast');
});
$toggleSwing.click(function () {
$allPictures.animate({left: "+=200"}, 1500, "swing");
});
$toggleLinear.click(function () {
$allPictures.animate({left: "-=200"}, 1500, "linear");
});
我们对我们古老的例子又做了几处修改。我们已经更改了按钮的文本,添加了两种.animate()
方法,还必须添加一种相对于allPictures<div>
的位置样式。添加“相对位置”是至关重要的,它的缺失可能会导致大量动画失败。jQuery 的动画功能不会改变 CSS 的规则。为了移动<div>
,它必须是可移动的。缺少 position 属性的元素默认为 position static,这意味着它们是按照页面布局定位的,不能移动。因此,如果您尝试设置动画,将不会发生任何事情。将<div>
放置在相对位置意味着它可以相对于其布局位置移动。
.animate()
方法采用了我们已经熟悉的三个参数:持续时间、放松和完成,并添加了一个新参数:属性,其中包括我们希望设置动画的一个或多个 CSS 属性。属性的值可以是绝对值,也可以是相对值。如果您只是在属性中输入一个值,它就是绝对值。jQuery 将根据该值设置动画。如果第二次尝试运行绝对动画,则不会发生任何事情,因为该属性将已包含所需的值。另一方面,相对值更具方向性。在前面的示例应用程序中,我们使用了两个不同的相对属性值。第一个命令告诉 jQuery 在右侧设置 200 像素的动画。第二个按钮连接到 toggle linear 按钮,告诉 jQuery 向左移动<div>
200 像素。要使用相对值,只需将该值用引号括起来,并在其前面加上+=xx
或-=xx
,其中xx
是更改属性的金额。
一次可以修改多个属性。添加更多属性时,jQuery 将根据其值设置每个属性的动画:
$toggleSwing.click(function () {
$allPictures.animate({
left: "+=200",
top: "+=200",
opacity: "-=1"
}, 1500, "swing");
});
$toggleLinear.click(function () {
$allPictures.animate({
left: "-=200",
top: "-=200",
opacity: "+=1"
}, 1500, "linear");
});
在前面的示例中,我们为每个.animate()
方法添加了两个属性:top 和 opacity,这两个属性与 left 属性类似。关于 animate 方法,需要注意的一点是,与 show/hide、fade 或 slide 方法不同,它从不向元素添加"display: none"
样式。即使不透明度为 0,元素仍会占用页面上的所有空间。
通过将动画方法链接在一起,动画可以依次运行。您还可以使用.delay()
方法在动画中引入延迟。它有两个参数:持续时间和队列名称。Duration
告诉您应该暂停动画引擎多长时间(毫秒),queueName
是要延迟的队列的名称。本书中我们不会使用命名队列,因此我们不会讨论队列名称:
$toggleSwing.click(function () {
$allPictures
.animate({
left: "+=200"
}, 1500, "swing")
.delay(1000)
.animate({
top: "+=200",
opacity: "-=1"
}, 1500, "swing");
});
$toggleLinear.click(function () {
$allPictures
.animate({
top: "-=200",
opacity: "+=1"
}, 1500, "linear")
.delay(1000)
.animate({
left: "-=200"
}, 1500, "linear");
});
在本例中,我们将两个单独的动画链接在一起,它们之间有 1 秒的延迟。请注意,如果您快速按下任一按钮,很快,<div>
将从页面上消失,并且可能不再可见。这个问题是由 jQuery 将每个新的动画请求添加到队列中这一事实引起的。将项目添加到队列中的速度比 jQuery 执行它们的速度要快得多。我们将在下一节中研究这个问题。
队列方法允许我们访问 jQuery 用于运行动画的动画队列。jQuery 允许我们有多个队列,但很少需要多个队列。.queue()
方法可用于获取和设置标准动画队列或自定义动画队列。我们可以使用 queue 方法查看当前队列中有多少项,并且可以向其传递一个回调函数,该函数在队列为空时调用。
当队列停止并添加新项目时,.dequeue()
方法非常方便。为了让队列再次运行,必须调用.dequeue()
方法。.clearQueue()
方法从队列中删除所有尚未执行的排队项目。
.stop()
方法停止当前动画。如果存在与正在运行的动画相关联的回调,则不会调用它们。.finish()
方法与此非常相似,只是它无所不能。它停止正在运行的动画,清除队列,并完成匹配集的所有动画。
这是 jQuery 中的两个全局变量。jQuery.fx.interval
方法设置动画速率。该值越小,动画速度越快,可能也越平滑。一般来说,您可能不想混淆这个值。它是全局动画计时器。更改它会更改所有动画的计时,而不仅仅是您的动画。jQuery.fx.off
方法设置为 true 时,将杀死所有动画。
当 jQuery 遇到需要执行的新动画时,它会将新动画放在动画队列的末尾。虽然这通常是处理事情的一种很好的方式,但也有可能因为将项目放入队列的速度快于它们被拉出的速度而使队列被淹没。一般来说,在向队列中添加更多项目时应小心。在向队列中添加更多项目之前,可能需要清除该队列。
虽然 jQuery 的动画功能非常方便,但它们并不完全是最先进的,它们开始显示出它们的年龄。可以在 jQuery 源代码中看到一个示例。以下代码来自 jQuery 版本 2.1.1 的源代码:
jQuery.fx.start = function() {
if ( !timerId ) {
timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
}
};
运行动画时,jQuery 使用setInterval()
方法对每个动画帧计时;实际上,jQuery.fx.interval
全局值用作计时器值。虽然这在几年前还很酷,但大多数现代浏览器都使用了window.requestAnimationFrame()
方法,而对于缺乏这种方法的浏览器,可以使用 polyfill。使用setInterval
方法而不是requestAnimationFramework
的最终效果是,即使在最快的硬件上的最新浏览器中,jQuery 的动画也总是有点闪烁,因为帧的渲染和setInterval
方法之间没有协调,就像requestAnimationFrame
一样。
本章我们介绍了很多代码。动画似乎很容易编写,但如果编写得好,它们可以向应用程序添加大量内容,并帮助用户了解应用程序状态的变化。我们首先学习了如何使用 jQuery 易于使用的内置动画方法。一旦我们理解了它们,我们就开始使用.animate()
和.delay()
方法,它们允许我们创建自己的自定义动画。
在本章的结尾,我们介绍了 jQuery 执行动画的方式。虽然在所示的简单示例中这很好,但它实际上有点过时。如果您希望执行更复杂的动画,您可能希望查看更复杂的库,例如Velocity.js
、GSAP
或其他库。
在下一章中,我们将研究使用 jQuery 通过表单提交数据。特别是,我们将研究如何在向服务器发送数据之前验证表单。