Dojo精解(三)
作者:Matthew Russell 原文链接
2008年3月18日,星期二,3:38PM
应用程序中的动画效果通常会具有额外的吸引力,而且特别适合需要给顾客、女士们、先生们,或者其他什么人留下美好印象的场合。为此,我想现在就给大家展示一些Dojo在动画方面的本领肯定会大受欢迎。
假如您刚刚从其他地方转到这个页面,可以单击我的头像或这个链接,在那里可以找到我正在连载的“Dojo精解”的另外两篇文章。“Dojo精解”系列文章是为介绍我的新书Dojo: The Definitive Guide而写的,读者朋友可以在Amazon或O’Reilly的书目中查到它。
要想使用Dojo开发动画,首先必须知道:Dojo将最常用的一些动画函数打包在了Base中,另外,Core的fx模块也提供了不少动画功能。记住这些动画功能所在的一种方法,就是记住它们的命名空间——Base中的所有动画函数都位于基础级的dojo命名空间中,而Core中的附加功能则要通过dojo.fx命名空间来访问。在即将展示的例子中,我们会用到fadeIn和fadeOut函数以及超级灵活的animateProperty函数,它们都包含在Base中。而在介绍dojo.fx时,我们会展示将多个动画连缀(chain)和组合(combine)起来的操作。
对于上面提到的这些函数,读者通过Dojo官方的API可以全面了解它们的功能和用法。但为简单起见,本文只介绍它们最基本的用法。对于褪色(fade)函数来说,只用两行短短的代码即可实现一个节点的淡入和淡出。正如下面代码片断所暗示的,Dojo的动画API一般都会返回一个对象,开发人员必须手工调用play()方法才能启动该动画。这样一来,我们不仅可以更好地控制动画,而且也会使连缀和组合动画效果变得更加简单(稍后就会看到)。最后,来看一看代码:
- //fade some nodes!
- dojo.fadeOut({node : 'someNodeId'}).play();
- //then sometime later...
- dojo.fadeIn({node : 'someNodeId'}).play();
顾名思义,animateProperty函数的用途就是动态变换任意CSS属性。在下面的例子中,我们将使用该函数动态修改一个方块元素的高度和宽度,以便在屏幕中呈现出内缩(implode)和外爆(explode)的效果——代码如下:
- //create an implode animation
- var implode = dojo.animateProperty({
- node : 'someNodeId',
- properties : {
- height : {end : 0},
- width : {end : 0}
- }
- });
- //create an explode animation (assumes width and height are both 0 when it is run)
- var explode = dojo.animateProperty({
- node : 'someNodeId',
- properties : {
- height : {end : 300}, //fill in whatever height/width you need...
- width : {end : 300}
- }
- });
不过,等等——这还不是全部。简单的动画效果的确很酷,但是,把它们连缀和组合起来则更加有趣;估计读者已经猜到了,要做到这一点也非常简单。以下代码展示的是连缀操作,除了把动画对象传递给dojo.fx.chain函数之外,一点也不复杂:
- //chain together two fade animations
- dojo.fx.chain([
- dojo.fadeOut({node : 'someNodeId'}),
- dojo.fadeIn({node : 'someNodeId'})
- ]).play();
组合的实现方式与此非常类似。假如要组合fadeOut和自定义的内缩动画,可以像下面这样:
- //combine two animations
- dojo.fx.combine([
- dojo.fadeOut({node : 'someNodeId'}),
- implode //the same one we created a few moments ago
- ]).play();
以上就是我们这一节要展示的动画。不过,为了让读者能够控制所有这些特效,我们还要使用几个dijit的Button部件,以便于执行JavaScript代码。在这个例子当中,我们要使用dojo/method SCRIPT标签来截取Button部件的onClick扩展点(extension point,疑为事件。——译者注),并完全通过标记来启动动画!通用的模式如下所示:
- <div dojoType="dijit.form.Button">Do Something!
- <script type="dojo/method" event="onClick" args="evt">
- //you can inspect the W3C standardized event object, evt, or do something else like...
- someAnimation.play();
- //other sweet JavaScript code goes here...
- </script>
- </div>
好,痛快一点吧,以下就是恰当地实现了上述所有功能的代码。这些代码会在屏幕中央(相对于浏览器的视口)创建一个蓝色的方块,并提供3个按钮来控制相应的动画效果。即使把这些代码直接复制粘贴到一个本地页面中,它们也能正常运行(读者如果想复制不带行号的代码,请到原文页面复制。——译者注)。
- <html>
- <head>
- <title>Animation Station!</title>
- <style type="text/css">
- @import "http://o.aolcdn.com/dojo/1.0/dojo/resources/dojo.css";
- @import "http://o.aolcdn.com/dojo/1.0/dijit/themes/tundra/tundra.css";
- </style>
- <script
- type="text/javascript"
- src="http://o.aolcdn.com/dojo/1.0/dojo/dojo.xd.js"
- djConfig="parseOnLoad:true">
- </script>
- <script type="text/javascript">
- dojo.require("dojo.fx"); //for dojo.fx.chain and dojo.fx.combine
- dojo.require("dojo.parser");
- dojo.require("dijit.form.Button");
- dojo.addOnLoad(function() {
- //get the dimensions of the current viewport
- var viewport = dijit.getViewport();
- var viewport_height = viewport.h;
- var viewport_width = viewport.w;
- //center a square in the viewport
- var square_dimension = 300;
- var e = document.createElement("div");
- e.id = "square";
- dojo.style(e, "width", square_dimension);
- dojo.style(e, "height", square_dimension);
- dojo.style(e, "background", "blue");
- dojo.style(e, "position", "relative");
- dojo.style(e, "left", (viewport_width-square_dimension)/2);
- dojo.style(e, "top", (viewport_height-square_dimension)/2);
- dojo.body().appendChild(e);
- //chain together two fade animations
- fadeAnim = dojo.fx.chain([
- dojo.fadeOut({node : 'square'}),
- dojo.fadeIn({node : 'square'})
- ]);
- //set up an implode animation
- var implode = dojo.animateProperty({node : 'square',
- properties : {
- height : {end : 0},
- width : {end : 0}
- }
- });
- //set up an explode animation
- var explode = dojo.animateProperty({node : 'square',
- properties : {
- height : {end : square_dimension},
- width : {end : square_dimension}
- }
- });
- //chain together the implode/explode
- implExplAnim = dojo.fx.chain([implode,explode]);
- //combine the chained fades and the implode/explode
- fadeImplExplAnim = dojo.fx.combine([fadeAnim, implExplAnim]);
- });
- </script>
- </head>
- <body class="tundra">
- <div dojoType="dijit.form.Button">Fade In/Out
- <script type="dojo/method" event="onClick" args="evt">
- fadeAnim.play();
- </script>
- </div>
- <div dojoType="dijit.form.Button">Implode/Explode
- <script type="dojo/method" event="onClick" args="evt">
- implExplAnim.play();
- </script>
- </div>
- <div dojoType="dijit.form.Button">Both!
- <script type="dojo/method" event="onClick" args="evt">
- fadeImplExplAnim.play();
- </script>
- </div>
- </body>
- </html>
最后,再说明一下:不久即将发布的Dojo 1.1(当前为Beta3)会包含一些针对1.0版的增强,届时完成相同的例子需要输入的代码量还会减少一些。假如读者想查看在线API,可别被这些增强搞晕喽,因为本页代码使用了1.0.x的bug修正版。
在Dojo: The Definitive Guide面市之前,别忘了每周来看一篇最新的Dojo精解系列文章哟!