0%

[技能檢定]題組三 步驟15 前台預告片展示 - javascript 動畫

動畫的部份我們主要是使用jquery內建的fadeIn()slideDown()show()等簡單的動畫方式,較複雜的動畫可以參考jQuery animate()函式的使用說明。

這邊的js中有多加了幾段額外的程式,用來做按鈕的控制或是避免錯誤,但檢定時,可視作答時間來決定要不要多寫這些內容。

預告片海報自動輪播

  1. 先撰寫海報自動輪播的功能,原理和題組一的輪播類似,使用 setInterval() 函式來設定定時執行。
    /view/front/main.php

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    //指定第一張海報先顯示
    $(".poster").eq(0).show();

    let now=0; //設定從0開始

    //取得目前的按鈕數量,也等於是目前的海報數量
    let icons=$(".icon").length;

    //建立自動定時執行機制,每隔三秒執行一次動畫函式ani
    let counter=setInterval(()=>{ ani(); },3000);
  2. 接著我們來撰寫轉場動畫函式 ani()

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    function ani(next){

    //取得目前顯示中的海報,同時間只會有一張海報是顯示的,其它都是隱藏
    now=$(".poster:visible").index();

    //判斷next這個參數是否存在
    //如果next有值表示是點擊按鈕要轉場的海報
    //如果next沒有值表示是是自動輪播下一張海報
    if(typeof(next)=='undefined'){

    //如果是自動輪播,計算出目前海報的下一張海報位置
    //如果下一張海報的位置超過全部海報的數量
    //則將now設為0表示從第一張海報重新輪播
    next=(now+1 < $(".poster").length)?now+1:0;
    }

    //取得下一張海報的轉場動畫類型
    let anicode=$('.poster').eq(next).data('ani');

    //根據動畫類型來執行不同的轉場效果
    switch(anicode){
    case 1:
    //淡入淡出
    //先執行淡出動畫讓目前顯示的海報圖淡出
    $(".poster").eq(now).fadeOut(1000,()=>{

    /****
    * 執行淡入動畫讓下一張海報圖淡入
    * 在回呼函式中執行的目的是要等淡出動畫都結束後才執行淡入
    * 避免兩張圖片因太像而讓轉場動畫不明顯
    ***/
    $(".poster").eq(next).fadeIn(1000);
    });
    break;
    case 2:
    //滑入滑出
    $(".poster").eq(now).slideUp(1000,()=>{
    $(".poster").eq(next).slideDown(1000);
    });
    break;
    case 3:
    //縮放
    $(".poster").eq(now).hide(1000,()=>{
    $(".poster").eq(next).show(1000);
    });
    break;
    }
    }

按鈕左右移動動畫

  1. 撰寫控制中間按鈕區塊可以左右移動的動畫控制程式
    /view/front/main.php

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18

    //宣告一個變數來控制可以左右按的次數
    let p=0;

    //左右按鈕控制
    $(".right,.left").on("click",function(){

    //使用jquery的hasClass來判斷按下的是向左還是向右
    if($(this).hasClass('left')){
    //使用三元運算式來判斷是否有前一個項目
    p=(p - 1 >= 0)? p-1 : p;
    }else{
    //使用三元運算式來判斷是否有下一個項目
    p=(p + 1 <= icons - 4)? p+1 : p;
    }
    //使用p來計算所有按鈕的位移量
    $(".icon").animate({right:80*p});
    })
  2. 建立點擊按鈕時,觸發轉場動畫變換的效果,原理是取得點擊的按鈕的位置值,然後傳給 ani() 函式做為下一張動畫的目標,這樣就可以觸發轉場效果

    1
    2
    3
    4
    5
    6
    7
    8
    //按鈕點擊切換轉場
    $(".icon").on("click",function(){
    //取得目前點擊的按鈕在按鈕列中的位置
    let idx=$(this).index();

    //將按鈕的位置帶入動畫函式中,執行轉場動畫
    ani(idx);
    })
  3. 由於自動輪播的執行是一個非同步的事件,如果在轉場動畫進行中又觸發別的轉場動畫時,可能會讓畫面上同時出現兩個轉場動畫的進行,因此這裏增加一個預防措施,當滑鼠移進 icons 區時,讓執行中的自動輪播先停止,當滑鼠離開 icons 區時,再恢復自動輪播。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    /**
    * 防止在自動輪播時,因為點擊切換動畫造成兩個轉場同時執行的情形
    * 所以在按鈕區增加一個監測機制,當滑鼠移入按鈕區時,
    * 先中斷自動輪播的執行,等滑鼠移出按鈕區時,再重新自動輪播
    */
    $(".icons").hover(
    //第一個function是指滑鼠移入時要做的動作
    function(){
    clearInterval(counter)
    },
    //第二個function是指滑鼠移出時要做的動作
    function(){
    counter=setInterval(()=>{
    ani();
    },3000);
    }
    )

animate()動畫函式應用

因為解題時間的考量,不是很建議使用animate()這個動畫函式來製作轉場動畫,但是animate()是一個好用的動畫控制函式,因此做為補充說明在此解釋;
使用animate()函式時要注意在動畫執行完畢後,還原dom的狀態,並且適當的安排動畫執行的順序是要同時執行還是有先後關係。
在此僅做為補充教材,提供使用animate()函式製作轉場動的方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
function ani(next){
now=$(".poster:visible").index();

if(typeof(next)=='undefined'){
next=(now+1<=$(".poster").length-1)?now+1:0;
}

let anicode=$('.poster').eq(next).data('ani');

switch(anicode){
case 1:
//淡入淡出
$(".poster").eq(now).fadeOut(2000);
$(".poster").eq(next).fadeIn(2000);
break;
case 2:
//滑入滑出
$(".poster").eq(next).css({left:210,top:0,width:210,height:280});
$(".poster").eq(next).show();
$(".poster").eq(now).animate({left:-210,top:0,width:210,height:280},2000,()=>{
$(".poster").eq(now).hide();
$(".poster").eq(now).css({left:0,top:0,width:210,height:280});
});

$(".poster").eq(next).animate({left:0,top:0,width:210,height:280},2000);
break;
case 3:
//縮放
$(".poster").eq(next).css({left:105,top:140,width:0,height:0});
$(".poster").eq(now).animate({left:105,top:140,width:0,height:0},1000,()=>{
$(".poster").eq(now).hide();
$(".poster").eq(now).css({left:0,top:0,width:210,height:280});
$(".poster").eq(next).show();
$(".poster").eq(next).animate({left:0,top:0,width:210,height:280},1000)
});
break;
}
}