http://dojotoolkit.org/documentation/tutorials/1.10/effects/index.html
In this tutorial, we will explore the effects that Dojo provides, which allow us to jazz up your page or application!
在本教程中,我们会探索dojo提供的特效功能,这可以使我们的Web页面或应用更加生动活泼。
Getting Started 开始
By this point, we're pretty comfortable manipulating the DOM and handling events from DOM nodes. However, as we take some of these actions, the transitions can be very abrupt: removing a node makes it disappear from the page, and that can potentially be disorienting for a user. Using some of the standard effects that Dojo provides, we can create smoother user experiences that really add an additional bit of polish and shine to our applications. Further, if we tap into Dojo's dojo/_base/fx
and dojo/fx
modules, we can chain and combine these effects to make some really dazzling, dynamic experiences.
我们已经可以很方便的操纵DOM以及DOM节点的事件。但是有些操作先的太突兀:例如我们删除一个节点,该节点会从页面上直接消失掉,这样会让用户感觉到很突兀。然后我们可以使用DOjo提供的一些标准特效来装饰我们的动作,例如在添加一个节点时,可以让添加的节点高亮显示一下。我们调用dojo的dojo/_base/fx和Dojo/fx模块,可以让我们的应用和页面可以让我们的用户有更好的使用体验。
Dojo 1.10 has two
fx
modules:dojo/_base/fx
anddojo/fx
.dojo1.10包含了两个fx模块,
dojo/_base/fx
anddojo/fx。
dojo/_base/fx
provides base effects methods that were found previously in Dojo base, including:animateProperty
,anim
,fadeIn
, andfadeOut
.dojo/fx
provides more advanced effects, including:chain
,combine
,wipeIn
,wipeOut
andslideTo
dojo/_base/fx
提供了老版本的dojo也提供的基础效果函数,例如动画、淡淡出等。
dojo/fx 提供了更加高级的特效,例如
chain
,combine
,wipeIn
,wipeOut
andslideTo
等。
Fading 淡入淡出
One animation you might have seen in applications you have used is a node fading in or out. This effect is so common and simple that it's included as a part of the core effects in dojo/_base/fx
. We can use it to hide or show elements on a page in a way that feels really smooth and polished. Here's an example:
在你的web应用中,最常见的动画之一就是节点的淡入和淡出效果。该功能是模块dojo/_base/fx的核心部分,使用起来简单方便。我们可以使用该模块使节点进行平滑和高亮的显示或隐藏。例如如下:
1 <button id="fadeOutButton">Fade block out</button> 2 <button id="fadeInButton">Fade block in</button> 3 4 <div id="fadeTarget" class="red-block"> 5 A red block 6 </div> 7 <script> 8 require(["dojo/_base/fx", "dojo/on", "dojo/dom", "dojo/domReady!"], function(fx, on, dom) { 9 var fadeOutButton = dom.byId("fadeOutButton"), 10 fadeInButton = dom.byId("fadeInButton"), 11 fadeTarget = dom.byId("fadeTarget"); 12 13 on(fadeOutButton, "click", function(evt){ 14 fx.fadeOut({ node: fadeTarget }).play(); 15 }); 16 on(fadeInButton, "click", function(evt){ 17 fx.fadeIn({ node: fadeTarget }).play(); 18 }); 19 }); 20 </script>
All animation functions take one argument: an object with properties. The most important property you will use is the node
property: a DOM node or string ID of a node to animate. Another property is duration
, which is how long the animation should last, specified in milliseconds. The duration
defaults to 350 milliseconds. There are other properties for other animations, but fading doesn't require them.
所有的动画函数有包含一个属性集合对象。这些属性主要包括以下几个:
node:值为DOM节点对象或标识该节点的ID字符串,我们定义的动画就执行对象就是该节点。
duration
:该属性定义了本动画执行的时间,单位是毫秒。该属性的默认值是350毫秒。
还有一些其他的而实行,但fading效果不需要他们,在此我们就不列出了。
Animation functions return a dojo/_base/fx::Animation
object with several methods: play, pause, stop, status, and gotoPercent. Animations are not started when they are created and must be manually started with the play method, as shown above.
动画函数执行后返回dojo/_base/fx::Animation对象,该对象包含了play、pause、stop、status和gotoPercent等函数。动画被创建之后,并不会立即执行,就像上面我们写的代码一样,必须调用play函数,动画才会执行。
Wiping 擦拭
Another effect you might have seen is wiping: changing the height of a node while leaving the content alone. This makes it look like someone is using a windshield wiper on the node. Often, wiping could be a useful effect to create something like a pulldown on a page, where you might have some sort of infrequently accessed content or settings, or perhaps you just prefer the shrinking to fading.
另外一个我们常见的效果就是wiping:不管节点里面的内容,改变节点的高度。这样看起来就想一个雨刷,把节点给擦除掉。这种效果在页面设计下拉的时候会经常用到,例如有些内容不是太重要,可以先隐藏不显示,想要查看的时候,可以通过点击执行wiping效果,展示出隐藏的内容。
下面是wiping的示例:
1 <button id="wipeOutButton">Wipe block out</button> 2 <button id="wipeInButton">Wipe block in</button> 3 4 <div id="wipeTarget" class="red-block wipe"> 5 A red block 6 </div> 7 <script> 8 require(["dojo/fx", "dojo/on", "dojo/dom", "dojo/domReady!"], function(fx, on, dom) { 9 var wipeOutButton = dom.byId("wipeOutButton"), 10 wipeInButton = dom.byId("wipeInButton"), 11 wipeTarget = dom.byId("wipeTarget"); 12 13 on(wipeOutButton, "click", function(evt){ 14 fx.wipeOut({ node: wipeTarget }).play(); 15 }); 16 on(wipeInButton, "click", function(evt){ 17 fx.wipeIn({ node: wipeTarget }).play(); 18 }); 19 }); 20 </script>
The wipe effect is in the dojo/fx
module. In this example, we have added the "wipe" class to our target node. Because the wipe functions operate on the height of the contents of a node rather than a definite height, our "wipe" class sets the target node's height to "auto".
wipe效果定义在dojo/fx模块中,在上面的例子中,我们就在目标节点上添加了wipe效果代码。因为wipe函数是操作节点内容的高度,而不是制定的高度,所以我们的wipeclass设置目标节点的高度为“auto”。
Sliding滑动
So far we've covered hiding nodes, but what if we're looking to move them around a bit? A fade or a wipe doesn't change the node's location. That's where fx.slideTo
comes into play. Shifting a node around could be useful to create an appearance of movement or progression on a page, and fx.slideTo
creates a smooth animation of the node in the page, moving it around by specifying the coordinates of the top and left position of the node in pixels.
到目前为止,我们已经知道了如何使用动画隐藏节点,但我们如何一点点移动节点,产生滑动效果呢?fade和wipe效果都没有改变节点的位置。但fx.slideTo函数可以做到这点,改变节点的位置。在页面上,在操作某个节点时,可以让节点按照像素点移动,产生动画效果是很有用的,fx.SlideTo函数就可以通过设置目标坐标的方式,让节点滑动,滑动后,目标坐标将成为节点的左上角坐标。
1 <button id="slideAwayButton">Slide block away</button> 2 <button id="slideBackButton">Slide block back</button> 3 4 <div id="slideTarget" class="red-block slide"> 5 A red block 6 </div> 7 <script> 8 require(["dojo/fx", "dojo/on", "dojo/dom", "dojo/domReady!"], function(fx, on, dom) { 9 var slideAwayButton = dom.byId("slideAwayButton"), 10 slideBackButton = dom.byId("slideBackButton"), 11 slideTarget = dom.byId("slideTarget"); 12 13 on(slideAwayButton, "click", function(evt){ 14 fx.slideTo({ node: slideTarget, left: "200", top: "200" }).play(); 15 }); 16 on(slideBackButton, "click", function(evt){ 17 fx.slideTo({ node: slideTarget, left: "0", top: "100" }).play(); 18 }); 19 }); 20 </script>
Animation Events 动画事件
As discussed previously, all of these animation methods return a dojo/_base/fx::Animation
object. These objects all provide not just controls to play or pause the animation, but they also provide a set of events that we can listen to, in order to perform some sorts of actions before, during, and after the animation. Two of the most important and commonly-used event handlers are beforeBegin
and onEnd
:
就如我们前面讨论的,所有的动画函数都返回dojo/_base/fx::Animation对象。这个对象不仅提供了控制play、或者pause动画的函数功能,而且还提供了动画事件监听接口,例如动作开始事件、动作执行事件以及动作执行完毕等事件。这些事件中,我们用的最多的就是beforeBegion和onEnd事件。
1 <button id="slideAwayButton">Slide block away</button> 2 <button id="slideBackButton">Slide block back</button> 3 4 <div id="slideTarget" class="red-block slide"> 5 A red block 6 </div> 7 <script> 8 require(["dojo/fx", "dojo/on", "dojo/dom-style", "dojo/dom", "dojo/domReady!"], function(fx, on, style, dom) { 9 10 var slideAwayButton = dom.byId("slideAwayButton"), 11 slideBackButton = dom.byId("slideBackButton"), 12 slideTarget = dom.byId("slideTarget"); 13 14 on(slideAwayButton, "click", function(evt){ 15 // Note that we're specifying the beforeBegin as a property of the animation 16 // rather than using connect. This ensures that our beforeBegin handler 17 // executes before any others. 18 var anim = fx.slideTo({ 19 node: slideTarget, 20 left: "200", 21 top: "200", 22 beforeBegin: function(){ 23 24 console.warn("slide target is: ", slideTarget); 25 26 style.set(slideTarget, { 27 left: "0px", 28 top: "100px" 29 }); 30 } 31 }); 32 33 // We could have also specified onEnd above alongside beforeBegin, 34 // but it's just as easy to connect like so 35 on(anim, "End", function(){ 36 style.set(slideTarget, { 37 backgroundColor: "blue" 38 }); 39 }, true); 40 41 // Don't forget to actually start the animation! 42 anim.play(); 43 }); 44 45 on(slideBackButton, "click", function(evt){ 46 var anim = fx.slideTo({ 47 node: slideTarget, 48 left: "0", 49 top: "100", 50 beforeBegin: function(){ 51 52 style.set(slideTarget, { 53 left: "200px", 54 top: "200px" 55 }); 56 } 57 }); 58 59 on(anim, "End", function(){ 60 style.set(slideTarget, { 61 backgroundColor: "red" 62 }); 63 }, true); 64 65 anim.play(); 66 }); 67 }); 68 </script>
You might have noticed that beforeBegin
is being passed as a property of the arguments object. The reason for passing it in more directly is that certain animations connect to beforeBegin
when they are created. Therefore, if you connect to beforeBegin
after the animation is created, your handler will be executed after the animation's beforeBegin
handler, which may not be what you want to happen. By passing your handler as a property of the arguments object, you guarantee that your handler will execute first.
你可能注意到了,beforeBegin已经作为一个参数属性传给了动画函数。这样做的话,当该动画对象创建,beforeBegin事件响应的函数就和动画关联到了一起。 Therefore, if you connect to beforeBegin
after the animation is created, your handler will be executed after the animation's beforeBegin
handler, which may not be what you want to happen. By passing your handler as a property of the arguments object, you guarantee that your handler will execute first.(因此,如果你在动画对象创建之后哦,在设置动画对象的beforeBegin事件,你可能会得不到你想要的结果。基于参数传递,把引用作为参数的一个属性传递的函数中,你可以在第一事件执行该函数)。这地方感觉说的有点不对。
Chaining 链接
What if we want to fire animations in sequence? We could use the End
event that we just talked about to set up the next effect, but that's not very convenient. This sort of pattern is common enough that the dojo/fx
module gives us a couple of great convenience methods to set up effects to run in sequence or in parallel, and each method returns a new dojo/_base/fx::Animation
object with its own set of events and methods that represent the entire sequence. Let's first take a look at fx.chain
to play animations one after another:
如果我们想按照顺序执行动画呢?我们可以监听第一个动画的End事件,得到后,我们在执行下一个动画,但这样使用起来太不方便了。这种需求很常见,所以dojo/fx模块也为我们提供了相应的API,建立一个动画列表,并可以按照顺序执行。每个动画函数依然会返回一个dojo/_base/fx::Animation对象,这些对象会把时间事件和下一个动画的函数结合在一起,形成一个顺序链。让我们看下fx.chain如何把多个动画函数一个一个按顺序执行的:
1 <button id="slideAwayButton">Slide block away</button> 2 <button id="slideBackButton">Slide block back</button> 3 4 <div id="slideTarget" class="red-block slide chain"> 5 A red block 6 </div> 7 <script> 8 require(["dojo/_base/fx", "dojo/fx", "dojo/on", "dojo/dom", "dojo/domReady!"], function(baseFx, fx, on, dom) { 9 10 var slideAwayButton = dom.byId("slideAwayButton"), 11 slideBackButton = dom.byId("slideBackButton"), 12 slideTarget = dom.byId("slideTarget"); 13 14 // Set up a couple of click handlers to run our chained animations 15 on(slideAwayButton, "click", function(evt){ 16 fx.chain([ 17 baseFx.fadeIn({ node: slideTarget }), 18 fx.slideTo({ node: slideTarget, left: "200", top: "200" }), 19 baseFx.fadeOut({ node: slideTarget }) 20 ]).play(); 21 }); 22 on(slideBackButton, "click", function(evt){ 23 fx.chain([ 24 baseFx.fadeIn({ node: slideTarget }), 25 fx.slideTo({ node: slideTarget, left: "0", top: "100" }), 26 baseFx.fadeOut({ node: slideTarget }) 27 ]).play(); 28 }); 29 }); 30 </script>
As you can see here, we create a few effects directly inline the call to fx.chain
, and immediately call play
on the returned dojo/_base/fx::Animation
to start the chained animation. We don't start playing each individual effect within the chain: fx.chain
handles that for us.
正如你看到的那样,我们创建了我们在fx.chain函数中创建几个效果,并且调用了该函数返回的dojo/_base/fx::Animation对象的play函数,开始执行chined的动画。在这里,我们并没有一个一个的去执行chain函数中包含的动画对象,而是fx.chain帮我们处理了这些。
Combining 结合
The second convenience method that dojo/fx
provides is the combine
method which will start multiple animations at the same time. The dojo/_base/fx::Animation
returned will fire its onEnd
event after the animation with the longest duration finishes. Let's look at another example:
dojo/fx模块提供的第二个方便的函数就是combine函数,该函数可以组织多个动画同事执行。该函数依然返回dojo/_base/fx::Animation对象,该对象可以监听整个动画的end事件。当执行事件最长的哪个动画执行完毕之后,该对象的End事件将会被触发。让我们看下例子:
1 <button id="slideAwayButton">Slide block away</button> 2 <button id="slideBackButton">Slide block back</button> 3 4 <div id="slideTarget" class="red-block slide chain"> 5 A red block 6 </div> 7 <script> 8 require(["dojo/_base/fx", "dojo/fx", "dojo/on", "dojo/dom", "dojo/domReady!"], function(baseFx, fx, on, dom) { 9 10 var slideAwayButton = dom.byId("slideAwayButton"), 11 slideBackButton = dom.byId("slideBackButton"), 12 slideTarget = dom.byId("slideTarget"); 13 14 // Set up a couple of click handlers to run our combined animations 15 on(slideAwayButton, "click", function(evt){ 16 fx.combine([ 17 baseFx.fadeIn({ node: slideTarget }), 18 fx.slideTo({ node: slideTarget, left: "200", top: "200" }) 19 ]).play(); 20 }); 21 on(slideBackButton, "click", function(evt){ 22 fx.combine([ 23 fx.slideTo({ node: slideTarget, left: "0", top: "100" }), 24 baseFx.fadeOut({ node: slideTarget }) 25 ]).play(); 26 }); 27 }); 28 </script>
In this case, rather than playing the fade and then the slideTo in sequence, they play simultaneously.
在这个例子中,不是先淡出,然后再移动目标节点,二是同时执行。
Using fx.chain
and fx.combine
, you can build up some fairly elaborate animation sequences. Also, given that both chain and combine return animation objects, the end results of those methods can also be chained and combined, allowing for you to build everything from very simple animations to very rich and detailed sequences.
使用fx.chain和fx.combine,你可以创建一些相对复杂的动画序列。并且,使用两个函数返回的动画对象依然可以组合成顺序执行的动画组或者同时执行的动画组。根据这个特性,你就可以一个个简单的动画,通过多种方式组合成一个相当负责的动画。
Conclusion 小结
Using Dojo, it's quite simple to add some flair to your pages. With the dojo/_base/fx
and dojo/fx
modules, you can easily fade DOM nodes in and out, and with a simple require, you can bring in a lot more powerful ways to simply and easily move your nodes about or wipe them in and out, and the ability to chain and combine animations means you can quickly and easily build up a rather advanced animation.
However, what if you want to do something more advanced, like adjusting a DOM node's height but not necessarily shrinking it to zero, or perhaps adjusting a background color via animation? There's the more generalized fx.animateProperty
, which we'll be covering in the next tutorial.
使用dojo,你可以快速简单的在你的页面上添加一些亮点。使用dojo/_base/fx和dojo/fx模块,你可以简便的淡入淡出DOM节点。可以使用简单的代码就可以让节点移动、擦除等。使用chain和combine动画组合,可以让你把一些简单的动画组合在一起,从而创建出高级复杂的动画。