20110719

Dojo 基本動畫效果( effects )

本篇將說明如何利用 Dojo 內含的效果( effects ) 使應用程式或網頁的呈現更加流暢。

以" Fading "、" Wiping "、" Sliding "、""


Fading 淡入淡出效果

這個淡入與淡出的效果,由於經常被使用到,現在已經被包含在 Dojo base 當中,換句話說,想要使用這個效果時,不需要引入其他 Dojo 模組。而使用 Fading 在應用程式或網頁中的好處是,但畫面中有元件需要出現或消失時,看起來會比較順暢,較不會讓使用者產生突兀的感覺。

以下為一 Fading 範例的 Html 部分:

<button id="fadeOutButton">Fade block out</button>
<button id="fadeInButton">Fade block in</button>
 
<div id="fadeTarget" class="red-block">
    A red block
</div>

接下來是 JavaScript 部分:

dojo.ready(function(){
        var fadeOutButton = dojo.byId("fadeOutButton"),
            fadeInButton = dojo.byId("fadeInButton"),
            fadeTarget = dojo.byId("fadeTarget");
 
        dojo.connect(fadeOutButton, "onclick", function(evt){
            dojo.fadeOut({ node: fadeTarget }).play();
        });
        dojo.connect(fadeInButton, "onclick", function(evt){
            dojo.fadeIn({ node: fadeTarget }).play();
        });
    });

所有的動畫函式( animation functions ) 都需要一個變數:一個包含屬性( properties )的物件。我們所需要的最重要的屬性為 node 屬性:要產生動畫效果的 DOM node 或是 該 node 的 id (string) ;另一個屬性是動畫的持續時間 ( duration ) ,以毫秒為單位(1/1000 秒),若未指定則預設為 350 毫秒。其他的動畫函式也可能需要其他的屬性作為變數,不過 Fading 效果僅需要這兩項。

動畫函式將會回傳一個 dojo.Animation 物件,這個物件有以下幾個方法( method ):play、 pause、 stop、 status 和 gotoPercent。如上例所示,動畫被建立出來之後不會自己啟動,必須手動使用 play 方法。




Wiping 雨刷效果

另一個大家可能也看過的效果 Wiping ,是改變某個節點的高度,讓該節點消失或出現的效果。由於呈現的效果類似擋風玻璃上的雨刷( windshield wiper ) 故名之。通常 Wiping 被使用在畫面上某些不經常使用的內容區塊,透過 Wiping 收摺或張開的效果來隱藏或顯示內容。

以下為一 Wiping 範例的 Html 部分:

<button id="wipeOutButton">Wipe block out</button>
<button id="wipeInButton">Wipe block in</button>
 
<div id="wipeTarget" class="red-block wipe">
    A red block
</div>

接下來是 JavaScript 部分:

// 載入 dojo.fx module
    dojo.require("dojo.fx");
 
    // 別忘了有載入module 的時候要使用dojo.ready 
    // 以確保程式都已正確載入
    dojo.ready(function(){
        var wipeOutButton = dojo.byId("wipeOutButton"),
            wipeInButton = dojo.byId("wipeInButton"),
            wipeTarget = dojo.byId("wipeTarget");
 
        dojo.connect(wipeOutButton, "onclick", function(evt){
            dojo.fx.wipeOut({ node: wipeTarget }).play();
        });
        dojo.connect(wipeInButton, "onclick", function(evt){
            dojo.fx.wipeIn({ node: wipeTarget }).play();
        });
    });

由於 wipe 效果是被包含在 dojo.fx module 中的,我們必須透過 Dojo 的 package system 載入這個模組。在這個範例中,我們加入了 " wipe " class 到目標節點。因為 wipe 函式處理的高度是節點內容的高度,而不是被定義的高度,所以我們將 " wipe " class 將目標節點的高度設為 " auto "。

註:將目標節點的高度設為 auto 的具體方法為,使用 CSS 如下

.wipe {
    font-size: 28px;
    height: auto;
    width: auto;
}


Sliding 滑動效果

到目前為止我們介紹的都是將節點隱藏起來的效果,如果我們需要的是將節點移動位置的話呢? Fade 和 Wipe 都不會移動節點的位置,所以這時候我們要用到 dojo.fx.slideTo 。 dojo.fx.slideTo 可以藉由目標節點左方和上方的位置的協作,並指定以 pixels 為單位的距離,產生平順的移動效果。

以下為一 Sliding 範例的 Html 部分:

<button id="slideAwayButton">Slide block away</button>
<button id="slideBackButton">Slide block back</button>
 
<div id="slideTarget" class="red-block slide">
    A red block
</div>

接下來是 JavaScript 部分:

dojo.require("dojo.fx");
 
    dojo.ready(function(){
        var slideAwayButton = dojo.byId("slideAwayButton"),
            slideBackButton = dojo.byId("slideBackButton"),
            slideTarget = dojo.byId("slideTarget");
 
        dojo.connect(slideAwayButton, "onclick", function(evt){
            dojo.fx.slideTo({ node: slideTarget, left: "200", top: "200" }).play();
        });
        dojo.connect(slideBackButton, "onclick", function(evt){
            dojo.fx.slideTo({ node: slideTarget, left: "0", top: "100" }).play();
        });
    });


Animation Events 動畫事件

如同前幾段所提到的,所有的 animation methods 都匯回傳一個 dojo.Animation 物件。這些物件不只可以用來控制動畫的播放或暫停,還提供一套事件讓我們可以指定動畫執行 " 之前 "、" 期間 "、" 之後 "的動作。其中最常使用的兩個事件是 beforeBegin 和 onEnd:

<button id="slideAwayButton">Slide block away</button>
<button id="slideBackButton">Slide block back</button>
 
<div id="slideTarget" class="red-block slide">
    A red block
</div>

JavaScript 部分:

dojo.require("dojo.fx");
 
    dojo.ready(function(){
        var slideAwayButton = dojo.byId("slideAwayButton"),
            slideBackButton = dojo.byId("slideBackButton"),
            slideTarget = dojo.byId("slideTarget");
 
        dojo.connect(slideAwayButton, "onclick", function(evt){
            var anim = dojo.fx.slideTo({
                node: slideTarget,
                left: "200",
                top: "200",
                beforeBegin: function(){
                    dojo.style(slideTarget, {
                        left: "0px",
                        top: "100px"
                    });
                }
            });
 
            dojo.connect(anim, "onEnd", function(){
                dojo.style(slideTarget, {
                    backgroundColor: "blue"
                });
            });
 
            anim.play();
        });
        dojo.connect(slideBackButton, "onclick", function(evt){
            var anim = dojo.fx.slideTo({
                node: slideTarget,
                left: "0",
                top: "100",
                beforeBegin: function(){
                    dojo.style(slideTarget, {
                        left: "200px",
                        top: "200px"
                    });
                }
            });
 
            dojo.connect(anim, "onEnd", function(){
                dojo.style(slideTarget, {
                    backgroundColor: "red"
                });
            });
 
            anim.play();
        });
    });

我們可以看到 beforeBegin 作為變數物件的一個屬性傳遞進去,這是因為要讓動畫在被建立的當下就跟 beforeBegin 作連結。這麼做可以確保我們指定的動作會在動畫開始之前建立完成。



Chaining 鏈結效果

如果我們想要讓多個動作照順序執行又該怎麼做呢?由於這個功能也是經常需要用到的, dojo.fx 提供了幾個便利的方法來將數個效果設定成依照某個順序執行或者同時進行,每個方法都將回傳一個新的 dojo.Animation 物件(每個物件包含自己的事件和方法)。

首先我們先看使用 dojo.fx.chain 讓某個動畫在另外一個動畫之後執行:

//html 部分
<button id="slideAwayButton">Slide block away</button>
<button id="slideBackButton">Slide block back</button>
 
<div id="slideTarget" class="red-block slide chain">
    A red block
</div>
//JavaScript 部分
dojo.require("dojo.fx");
 
    dojo.ready(function(){
        var slideAwayButton = dojo.byId("slideAwayButton"),
            slideBackButton = dojo.byId("slideBackButton"),
            slideTarget = dojo.byId("slideTarget");
 
        dojo.connect(slideAwayButton, "onclick", function(evt){
            dojo.fx.chain([
                dojo.fadeIn({ node: slideTarget }),
                dojo.fx.slideTo({ node: slideTarget, left: "200", top: "200" }),
                dojo.fadeOut({ node: slideTarget })
            ]).play();
        });
        dojo.connect(slideBackButton, "onclick", function(evt){
            dojo.fx.chain([
                dojo.fadeIn({ node: slideTarget }),
                dojo.fx.slideTo({ node: slideTarget, left: "0", top: "100" }),
                dojo.fadeOut({ node: slideTarget })
            ]).play();
        });
    });

直接 dojo.fx.chain 之中建立數個效果,然後以回傳的 dojo.Animation 物件使用 play 方法播放效果,而不需要一一對所有效果執行 play,dojo.fx.chain 會幫我們自動執行。



Combining 結合效果

接下來另一個 dojo.fx 提供的方法是 dojo.fx.combine ,可以讓多個動畫在同時執行。dojo.fx.combine 方法回傳的 dojo.Animation 物件的 onEnd 事件會在所有動畫之中持續時間最長的動畫結束時啟動。

以下是範例的html 和 JavaScript:

<button id="slideAwayButton">Slide block away</button>
<button id="slideBackButton">Slide block back</button>
 
<div id="slideTarget" class="red-block slide chain">
    A red block
</div>
dojo.require("dojo.fx");
 
    dojo.ready(function(){
        var slideAwayButton = dojo.byId("slideAwayButton"),
            slideBackButton = dojo.byId("slideBackButton"),
            slideTarget = dojo.byId("slideTarget");
 
        dojo.connect(slideAwayButton, "onclick", function(evt){
            dojo.fx.combine([
                dojo.fadeIn({ node: slideTarget }),
                dojo.fx.slideTo({ node: slideTarget, left: "200", top: "200" })
            ]).play();
        });
        dojo.connect(slideBackButton, "onclick", function(evt){
            dojo.fx.combine([
                dojo.fx.slideTo({ node: slideTarget, left: "0", top: "100" }),
                dojo.fadeOut({ node: slideTarget })
            ]).play();
        });
    });

利用 dojo.fx.chain 和 dojo.fx.combine 就可以將簡單的動畫組合成精緻的效果。不過如果想要做出更進階的動畫呢?例如把一個 node 的高度縮小,像 Wiping effect 但不想要高度縮到 0 而消失?

dojo.animateProperty 就是答案!下一篇將會有解答。

沒有留言:

張貼留言