4.1. Visual Effects
Script.aculo.us最突出的组成部分就是它为用户界面事件提供多样的视觉效果。使用script.aculo.us效果,可以实现平滑生动的动画效果,这种效果可以和Falsh相媲美。完成这种视觉效果不需要使用额外的插件。而且某种程度上保留了HTML的优点。
那么跨平台的兼容性怎么样呢?通常,script.aculo.us的视觉效果在不同的浏览器(Windows IE6, Firefox, Safari, Konqeror, Camino, Opera等等)都能稳定的工作。而且因为这种动画效果是基于时间的(而不是基于帧的),所以即使系统的速度不同它始终能够运行一致。你可能很好奇:就因为视觉效果的简单性,就能说它好么?是不是只是用来吸引眼球的?那么它怎么样为Ajax工作呢?所有这些问题你可以在第六章找到答案,但是这里只简单的提及一下。这种视觉效果不仅仅是一种点缀,而是提供一种更好的用户体验,特别是与Ajax的结合。在过去的十几年里,用户掌握了怎么使用web的方法,Ajax的出现破坏了很多他们期望的事情。例如,他们期望web页面是静态的,只有当他们加载的时候页面才会改变。但是在上一章中,所有的Ajax示例都是在没有重新加载的情况下改变了页面,这就潜在了发生混乱的可能性。为了应付这种情况,使用视觉效果可以给出用户提示使得用户界面更加自然更加醒目。
一句话警示:就像电影里的特技一样,script.aculo.us特技通常也是很棒的,当你不太过分留意它们,它们出来的效果是非常精妙的,这些特技会在某些区域显示出来。还记得80年代刚刚有了桌面系统,每个相似的通讯系统一下子使用了10种不同的字体,因为它们可以做到?如果可能,不要尝试让script.aculo.us也拥有这些能力。 |
script.aculo.us的Effect对象就是魔法之所在,让我们look look..首先,我们需要一个元素来做小白鼠,所以在chapter4/index.rhtml加上:
<div id="target" class="green box"><div>Here's a DIV with some text.</div>
</div>
现在用link_to_function来在这个新的元素上调用特效吧!,在div下面加入:<%= link_to_function "Fade", "new Effect.Fade('target')" %>还记得么,link_to_function有两个参数,第一个是link显示的文本,第二个是要执行的javascript表达式。这个例子中,Javascript表达式是一个调用script.aculo.us的Effect.Fade方法。现在刷新页面点击链接,你就会看到div里面的内容慢慢的淡化直至消失。在这行代码中,第一个参数Fade是传递元素的ID,将其传递到Prototype的$()功能中。
还有另外一种方式触发特效,这要归功于Prototype在每个元素上都有Element 方法,通过$()可以直接在DOM元素上调用visualEffect。$('target').visualEffect('fade')Script.aculo.us有5个核心的视觉效果来处理元素:Opacity, Scale, Move, Highlight 和 Parallel.来感受一下每种特效吧:<%= link_to_function "Opacity",
"new Effect.Opacity('target', {to:0.5})" %>
<%= link_to_function "Scale",
"new Effect.Scale('target', 200)" %>
<%= link_to_function "Move",
"new Effect.Move('target', {x:50,y:10})" %>
<%= link_to_function "Highlight",
"new Effect.Highlight('target')" %>
<%= link_to_function "Parallel",
"new Effect.Parallel([
new Effect.Move('target', {x:50,y:10}),
new Effect.Opacity('target', {to:0.5})
])" %>
在你的应用中,你可以使用复合效果,用Effect.parallel将集中核心效果组合起来使用。Script.aculo.us包括16种标准的组合效果,但是你也可以自己组合他们来定义一种新的效果。下面是这些标准效果列表:
Fade Appear | 渐变色出现或消失 | 逐渐减弱或增强元素的不透明性。消失(元素从显示到消失):逐渐褪色,当褪色结束后,元素的显示属性被设置为 none,即元素从页面中消失。显示(从无到显示):与消失过程相反。 |
BlindUp BlindDown | 放下收起
| 效果就像百叶窗一样:逐渐改变元素的高度,最后变成适合元素内容的高度 |
SlideUp SlideDown | 平滑下落平滑收起 | 类似于上面的放下收起效果,但是不同在于元素及其内容一起会平滑的下落或收起。注意这个效果用法和其他组合特效的不同,平滑效果需要在目标div的内容外面加一个div包装 |
Shrink Grow | 缩放效果 | 从中心点调整整个元素及其内容的大小。 |
Highlight | 高亮效果 | 改变元素背景的颜色(默认是浅黄色的),渐变到原来的颜色。一般用来在页面上吸引用户的注意力 |
Shake | 摆动效果 | 使元素平滑的左右摆动几次,一般用来指示元素不正常 |
Pulsate | 跳动效果 | 几次快速的元素闪烁,一个用在<blink>标签上时髦的手法 |
DropOut | 退出效果 | 逐渐褪色并且向下移动,最后消失在页面上 |
SwitchOff | 切断效果 | 模拟老电视关机的效果:一个迅速的闪烁,最后元素变成一道水平线 |
Puff | 张开效果 | 元素尺寸逐渐增大,透明度变高,最后像云一样散开 |
Squish | 压扁效果 | 跟缩放效果差不多,但是元素的左上方角落固定不动 |
Fold | 折叠效果 | 首先减小元素的高度成为一条线,然后减小其宽度,最后消失 |
为了尝试一下各种不同的标准组合效果,你需要为每种效果写一个链接。但是为了符合DRY原则,我们用数组迭代的方法来实现吧:
<div id="target" class="green box"><div>Here's a DIV with some text.</div>
</div>
<% %w( Fade Appear Highlight Fold Pulsate SlideUp SlideDown
Shrink Grow Squish Shake DropOut SwitchOff Puff BlindUp
BlindDown ).each do |name| %>
<%= link_to_function name, "new Effect.#{name}('target')" %>
<% end %>
4.1.1. Toggling许多特效都是成对出现的(Fade/Appear, BlindUp/BlindDown , SlideUp/SlideDown)。 Script.aculo.us提供了一个简便的方法把这成对的效果绑在一起, Effect.toggle:Effect.toggle('target') /* 使用Fade/Appear*/
Effect.toggle('target', 'blind')
Effect.toggle('target', 'slide')
4.1.2. OptionsEffect.*方法的第二个参数是一个hash选项,一些是特殊的效果选项,但是我们现在来看看适应于每个特效的选项。
duration以秒为单位,指明特性持续的时间。例如:<%= link_to_function "Fade",
"new Effect.Fade('target', { duration:5 })" %>
fps决定每秒运行多少帧,默认情况是25帧/秒,可调,但是不能超过100,例如:<%= link_to_function "Choppy Fade",
"new Effect.Fade('target', { duration:10, fps:2 })" %>
from和to定义开始和结束点(开始为0,结束为1),例如你可以直接从中间点开始渐变到25%,然后结束:<%= link_to_function "Fade with from",
"new Effect.Fade('target', { from:0.5, to:0.25 })" %>
4.1.3. Queues有时候,你可能希望将这些特效发生连锁反应。你可能首先会尝试一个接一个的调用特效:<%= link_to_function "Blind Up/Down",
"new Effect.BlindUp('target');
new Effect.BlindDown('target')" %>
不幸的是,这样达不到你预期的效果,当创建新特效后,script.aculo.us将它们加入到全局队列中。默认情况下,这些特效是并行执行的,这也意味着他们之间会产生冲突。为了指明一个效果在队列中的位置,要用queue选项:<%= link_to_function "Blind Up/Down",
"new Effect.BlindUp('target');
new Effect.BlindDown('target', { queue: 'end' })" %>
这样两个特效就会排成队列执行而不会发生冲突,如果你希望在队列中加入两个以上的特效,只要继续使用queue:’end’选项添加特效进去就可以了。queue选项还有一个设置是front,这个设置会让特效在队列特效执行之前执行。
script.aculo.us也支持多队列,你可以为了队列特效独立运行建立指定的范围。关于建立队列范围的更多信息,参考第十一章。
4.1.4. Callbacksoption选项的hash也可以有callback作为参数,在特效的生命周期中执行。beforeStart是指定当主特效开始时运行的内容。beforeUpdate在特效呈递的每次迭代循环重绘发生之前调用。afterFinish在特效最后重绘之后调用。callback传递一个与特效对象相关的参数。例如:<%= link_to_function "Fade with callback",
"new Effect.Fade('target', { afterUpdate: function(effect) {
effect.element.innerHTML = effect.currentFrame;
}})" %>
特效callback的更多详细内容参见第十一章。4.1.5. Transitionstransition选项决定特效线性变化的方式,逐步加速,或者其他方式。总共有八个标准的transition,你也可以很轻易的定义一个新的transition. 为了控制默认的特效转变方式,可以这样使用transition选项:<%= link_to_function "Fade with wobble",
"new Effect.Fade('target',
{ transition: Effect.Transitions.wobble })" %>
8个标准的transition可供使用: linear, reverse, none, full, sinoidal, pulse, wobble, 和 flicker。第十一章有其细节描述和创建自定义转变方式的内容。为了感受这些转变的方式,看看下面的实例:
4.1.6. Visual Effect Helper前面,我们是直接使用了script.aculo.us的Effect对象,而脱离了Rails的helper,事实上Rails已经提供了helper方法来生成视觉特效,允许你可以不通过编写javascript来生成视觉特效。这个helper就是visual_effect,你可以这么使用:
visual_effect(:fade, :target)第一个参数是script.aculo.us 的特效名字(前面已经说过),第二个参数是DOM元素的ID, visual_effect这个helper会输出一段Javascript代码,所以你也可以与其他helper配合使用,像link_to_function:<li><%= link_to_function "Fade", visual_effect(:fade, :target) %></li>绑定效果也可以在helper中使用:<%= link_to_function "Toggle Blind",
visual_effect(:toggle_blind, :target) %>
Tip:ruby的风格是使用下划线来分割变量或方法中的单词。而Script.aculo.us特效方法,遵照JavaScript命名规则“驼峰表示法(CamelCase)”.所以,当你使用visual_effect helper的时候,要记住用ruby风格的写法来使用名字;例如:BlindUp应该写成blind_up. |
visual_effect helper在与Ajax helper混合使用的时候特别有用,譬如link_to_remote.举个例子:你可能需要用Highlight效果来吸引用户的注意页面中已经通过Ajax更新过的部分。为了说明白这个过程,首先在chapter4_controller.rb中添加:def get_time
render :text => Time.now.to_s
end
然后,在views/chapter4/index.rhtml中添加一个Ajax链接:<%= link_to_remote "Get Time",
:update => "current_time",
:url => { :controller => "chapter3", :action => "get_time" },
:complete => visual_effect(:highlight, :current_time) %>
<div id="current_time"></div>
注意到了吧,跟前一章的例子中不一样的是,你不用自己写:complete的内容,我们让visual_effect help帮我们写:)