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
    11
    12
    13
    14
    //指定第一張海報先顯示
    $(".item").eq(0).show();

    //計算有幾張海報
    let total=$(".btn").length

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

    //設定下一張為0
    let next=0;

    //設定計時器,每隔3秒執行一次slide函式
    let timer=setInterval(()=>{slide()},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
    49
    50
    51
    52
    53
    function slide(n){

    //取得目前顯示的海報的動畫效果
    let ani=$(".item").eq(now).data("ani");

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

    /* 如果是自動輪播,計算出目前海報的下一張海報位置
    * 如果下一張海報的位置超過全部海報的數量
    * 則將now設為0表示從第一張海報重新輪播 */
    next=now+1;
    if(next>=total){
    next=0;
    }
    }else{
    next=n;
    }

    //根據動畫類型來執行不同的轉場效果
    switch(ani){
    case 1:
    //淡入淡出
    //先執行淡出動畫讓目前顯示的海報圖淡出
    $(".item").eq(now).fadeOut(1000,function(){
    /****
    * 執行淡入動畫讓下一張海報圖淡入
    * 在回呼函式中執行的目的是要等淡出動畫都結束後才執行淡入
    * 避免兩張圖片因太像而讓轉場動畫不明顯
    ***/
    $(".item").eq(next).fadeIn(1000);
    });
    break;
    case 2:
    //縮放
    $(".item").eq(now).hide(1000,function(){
    $(".item").eq(next).show(1000);
    });
    break;
    case 3:
    //滑入滑出
    $(".item").eq(now).slideUp(1000,function(){
    $(".item").eq(next).slideDown(1000);
    });
    break;
    }

    //將下一張海報的位置設定給目前的海報
    now=next;

    }

按鈕左右移動動畫

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    //宣告一個變數來控制可以左右按的次數
    let p=0;

    //設定左右按鈕的點擊事件
    $(".left,.right").on("click",function(){
    //取得點擊的按鈕的class,判斷是向左按鈕還是向右按鈕
    let arrow=$(this).attr('class')
    switch(arrow){
    case "right":
    //如果是向右按鈕,則判斷p+1是否小於總海報數量-4
    if(p+1<=(total-4)){
    p=p+ 1;
    }
    break;
    case "left":
    //如果是向左按鈕,則判斷p-1是否大於等於0
    if(p-1>=0){
    p=p-1;
    }
    break;
    }
    //將p乘以每個按鈕的寬度,再加上單位px,設定給按鈕區塊的right屬性
    $(".btn").animate({right:90*p})
    })
  2. 建立點擊按鈕時,觸發轉場動畫變換的效果,原理是取得點擊的按鈕的位置值,然後傳給 ani() 函式做為下一張動畫的目標,這樣就可以觸發轉場效果

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

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

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