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
. Options
Effect.*
方法的第二个参数是一个
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
. Callbacks
option
选项的
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
. Transitions
transition
选项决定特效线性变化的方式,逐步加速,或者其他方式。总共有八个标准的
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帮我们写:)