原文地址:http://dojotoolkit.org/documentation/tutorials/1.7/animation/
难度:初级
版本:1.7
?
最终的完成效果
?
?
开始
像所有的图形用户界面一样,Web用户界面,也是利用像素来描绘真实世界的影像,我们可以操纵像素让其快速变化而让人认为其正在运动中。通过变化的时间控制,可以使动画显示的更直观的,运动表现的更平滑。
?
在本教程中,我们将学习Dojo提供的动画工具,允许你调整和建立自定义动画,以满足您的特定的用户界面要求
?
?
?
回顾效果功能
在以前的教程中,我们已经讨论过一些常用的内置效果功能。 我们可以使用的方法有dojo/_base/fx模块中的baseFx.fadeIn和baseFx.fadeOut方法,dojo/fx模块中的fx.slideTo和fx.wipeIn方法。我们已经了解了如何可以传递一个参数对象来控制我们想要的动画:
?
require(["dojo/fx", "dojo/dom", "domReady!"], function(fx, dom) { fx.wipeIn({ node: dom.byId("wipeTarget") }).play(); });?
?
但这些元素只有部分的参数可以设置。我们可能会想要更多更复杂的动画,假设我们想要闪烁的背景,或在屏幕上移动节点。为此,我们需要Dojo的通用的动画工具, baseFx.animateProperty?
?
?
?
动画属性
如果你看了fx.wipeIn的源代码,你会发现节点style.height的属性被改为从0到其自动或自然高度。同理,看看我们如何创建任意属性的动画,我们将创建一个边界变化的动画。我们开始:
?
<button id="startButton">Grow Borders</button> <button id="reverseButton">Shrink Borders</button> <div id="anim8target" class="box" style="border-style:outset"> <div class="innerBox">A box</div> </div>?
?
animateProperty方法遵循我们已经使用过的相同的模式。它有着我们想要的动画的border-width属性,所以我们到的animateProperty调用看起来像这样
?
require(["dojo/_base/fx", "dojo/dom", "domReady!"], function(baseFx, dom) { baseFx.animateProperty({ node: dom.byId("anim8target"), properties: { borderWidth: 100 } }).play(); });?
?
请注意,我们使用的JavaScript低驼峰属性名borderWidth ,而不是CSS的border-width属性的名称。 我们是通过一个节点的属性,使用一个新的' properties '键来指定我们要进行动画。
运行示例
?
?
?
同样的,还有很多可以设置的属性,我们可以指定任何我们喜欢的属性。在这个例子中,我们再加上一些效果。将在同一时间运动到顶部,到左侧并且改变透明度,还有消失的效果。通过提供具体的start和end 属性,我们可以做出非常具体的,可重复的动画。
?
baseFx.animateProperty({ node: anim8target, properties: { top: : { start: 25, end: 150 }, left: 0, opacity: { start: 1, end: 0 } }, duration: 800 }).play();
?
请注意,我们还提供了一个duration属性。这是整个动画所花费的毫秒数。
运行示例
?
?
?
灵活地移动
如果使用自动生成的动画,我们将看到一个从一开始就随着时间的固定变画的运动。 这条曲线的形状被称为“宽松”。最简单的“曲线”,是一条直线,例如,从X移动,匀速运动。但如果让动作看起来更自然的话,应该是让当他们开始慢,然后加速,然后再次放慢。 有多种方法来实现这一效果,但Dojo提供了广泛的灵活的移动功能,以得到正确的效果和感觉。dojo/fx/easing模块有几个方法:
?
require(["dojo/_base/fx", "dojo/dom", "dojo/fx/easing", "dojo/window", "dojo/on", "dojo/domReady!"], function(baseFx, dom, easing, win, on) { var dropButton = dom.byId("dropButton"), ariseSirButton = dom.byId("ariseSirButton"), anim8target = dom.byId("anim8target"); // Set up a couple of click handlers to run our animations on(dropButton, "click", function(evt){ // get the dimensions of our viewport var viewport = win.getBox(win.doc); baseFx.animateProperty({ // use the bounceOut easing routine to have the box accelerate // and then bounce back a little before stopping easing: easing.bounceOut, duration: 500, node: anim8target, properties: { // calculate the 'floor' // and subtract the height of the node to get the distance from top we need top: { start: 0, end:viewport.h - anim8target.offsetHeight } } }).play(); }); on(ariseSirButton, "click", function(evt){ baseFx.animateProperty({ node: anim8target, properties: { top: 0 } }).play(); }); });
?运行示例
?
?
在这个例子中,我们计算视窗的高度,这样我们就可以定位框底部出现坐标。使用的bounceOut缓和方法,先快后慢,最后才停止。还要注意的是top属性是一个对象,这让我们可以特定一个范围值,我们可以为每个样式属性动画都给出start和end属性。
?
几乎所有的easings都有“in”或“out”或“INOUT”的名子。这些方法都是在动画中一定的时间触发的beginning(In),ending(Out),ends(InOut)。
?
?
?
将其组合在一起
传统的动画制作软件通常使用模型的时间线来确定动画的效果,动作为一前一后。 正如我们已经看到在本教程前面的效果,Dojo提供了一个重合机制: fx.combine和fx.chain 。让我们来看看如何把拼在一起。
?
对于这个演示,开始时我们有两个框的内容,我们要交换,要突出变化,我们也将淡出背后的背景颜色。?
?
<button id="swapButton">Swap</button> <div class="container" id="container"> <div id="content1" class="contentBox" style="top: 0; left: 0"> <div class="innerBox">1: Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident.</div> </div> <div id="content2" class="contentBox" style="top: 0; left: 250px"> <div class="innerBox">2: Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</div> </div> </div>?
?
像以前一样,我们加载dojo,要求加载所需的模块,我们传递给一个函数给require,并在里面做初始化 。
?
<script src="http://ajax.googleapis.com/ajax/libs/dojo/1.7.1/dojo/dojo.js" data-dojo-config="isDebug: true, async: true"> <script> require(["dojo/_base/fx", "dojo/fx", "dojo/fx/easing", "dojo/dom-style", "dojo/dom", "dojo/on", "dojo/aspect", "dojo/domReady!"], function(baseFx, fx, easing, domStyle, dom, on, aspect) { function swapAnim(node1, node2) { // create & return animation which swaps the positions of 2 nodes } var originalOrder = true; // track which order our content nodes are in var swapButton = dom.byId("swapButton"), c1 = originalOrder ? dom.byId("content1") : dom.byId("content2"), c2 = originalOrder ? dom.byId("content2") : dom.byId("content1"), container = dom.byId("container"); // Set up a click handler to run our animations on(swapButton, "click", function(evt){ // pass the content nodes into swapAnim to create the node-swapping effect // and chain it with a background-color fade on the container // ensure the originalOrder bool gets togged properly for next time }); }); </script>?
?
能够把不同的动画部分组合成一个复杂的动画是非常有用的。 在这里我们已经打破了动画的单独运动,我们可以使代码可重复使用。swapAnim函数看起来像这样:
?
function swapAnim(node1, node2) { var posn1 = parseInt(domStyle.get(node1, "left")), posn2 = parseInt(domStyle.get(node2, "left")); return moveNodes = fx.combine([ fx.slideTo({ duration: 1200, node: node2, left: posn1 }), fx.slideTo({ duration: 1200, node: node1, left: posn2 }) ]); }?
?
slideTo作用于每个节点使用left样式属性。我们也可以使用animateProperty类似的效果。两个独立的动画同时运行,fx.combine方法完成两个节点移动一次的两个动画。 请注意,我们返回动画对象animateProperty和其他Dojo方法一样。 它是需要的时候调用代码play()
?
// Set up a click handlers to run our animations on(swapButton, "click", function(evt){ // chain the swap nodes animation // with another to fade out a background color in our container var anim = fx.chain([ swapAnim(c1, c2), baseFx.animateProperty({ node: container, properties: { backgroundColor: "#fff" } }), ]); // before the animation begins, set initial container background aspect.before(anim, "beforeBegin", function(){ domStyle.set(container, "backgroundColor", "#eee"); }); // when the animation ends, toggle the originalOrder on(anim, "End", function(n1, n2){ originalOrder = !originalOrder; }); anim.play(); });?
?
上面是调用代码。 数组传递给fx.combine之前,fx.chain有两个单独的动画。我们要运行这些系列:交换节点,然后背景色动画。 容器的初始背景颜色设置连接的beforeBegin事件,并在onEnd我们有一个处理,以确保当我们点击下一步,节点被扭转。
?
运行示例
?
生成的代码是灵活的,其逻辑很容易地扩展。
?
结论
Dojo的动画方便简??单,但所有的控制,你需要具体的定制过渡和其它效果。动画可以从简单的一小片开始建立,并提供有用的生命周期事件,以帮助更改同步功能。 在现实世界中,没有直接从一个状态马上变成另一个状态,控制运动和视觉的变化,可以创造非常好的用户体验。
?