讓我們來快速寫個漂浮感的輪播吧!(直播筆記)動態網頁程式教學

漂浮感輪播教學成果

相信大家對於輪播一定不陌生吧,在各大官網、購物網站的重點區域常常可以看到輪播的蹤跡。除了增加與使用者的互動性以外,對於尺寸日漸縮小的行動裝置來說,輪播很重要的一點是可以在有限版面中增加傳遞的資訊量。今天我們就來實作如何透過Vue.js簡化座標計算跟更新資料,快速打造漂浮效果的輪播功能吧!

我們將以Code Pen做為本次實作的平台,這是一個可以在創作的同時即時看到程式碼運作狀況的線上程式碼編輯器,只要簡單註冊就可以使用囉!

如果想搭配直播影片一起實作,請往這邊走 👉🏻 https://www.youtube.com/watch?v=GFMnJKy_910

首先在Code Pen上開一個新的pen,將HTML的預處理器設定成Pug、CSS的預處理器設定成Sass、JS的CDN掛入Vue。

輪播中不可缺少的靈魂角色──圖片,這邊介紹一個可供個人也可商用的圖片網站Lorem Picsum(註一),他的特點是圖片是一個個的URL,使用時可直接嵌入網站。除了隨機圖片以外也可以透過/id/{image}指定特定圖片,尺寸大小的部分只要在URL後面加上寬和高就可以囉!另外也有像灰階、模糊等等的參數,可說是練習切版時的必備良藥。

*註一:直播影片中所提的Unsplash it目前已更新成Lorem Picsum,另有一個圖片平台Unsplash提供類似服務,但圖片取得方式為下載。

準備動態網頁的圖片與文案

在JS準備一個陣列works把輪播的材料塞進去,每個輪播分別有標題、敘述和圖片這些素材,在陣列中利用{}區隔。大家可以自由選擇喜歡的圖片跟文案,記得文案跟URL要用雙引號包起來。

套入輪播的材料:標題、敘述和圖片這些素材
套入輪播的材料:標題、敘述和圖片這些素材

接下來用Vue把資料套進來,首先在HTML建立#app,在JS建立一個新的Vue物件,指定Vue的作用範圍為#app並指定data的陣列來源為之前在外定義的works(為了讓Vue能夠使用所以在內部再定義一次)。輪播的原理很像幻燈片,透過指定每一組物件編號、計算他的寬度來達成輪播的效果。既然需要輪流,我們就必須設定起始點為陣列中的第0張now_index:0然後設定每張幻燈片的寬span為930px。

漂浮感輪播教學-設定Vue
設定Vue指定每一組物件編號、計算寬度

動態網頁內幻燈片的輪播是怎麼運作的呢?

把資料都套進來之後接下來要做重複與更新,這邊用以下三個畫面階層來解釋輪播的運作:

  1. Postarea:把元素固定在畫面的中央,有點像是逐格動畫中固定的畫框。
  2. Posts:多個靜態畫面組成的長條畫面。
  3. Postbox:長條畫面中的每一張靜態畫面。

在HTML裡建立上述三個階層的畫面,其中postbox中又包含了cover(圖片)、h1(標題)、h5(敘述)這三個元素。我們直接先用任一張圖片和文案做代表,使用語法v-for迭代陣列中的元素渲染六次模擬效果,之後再把文字和圖片替代進去成變數即可。

使用語法v-for迭代陣列中的元素渲染六次模擬效果,之後再把文字和圖片替代進去成變數即可
#app
  .postarea
    .posts
      .postbox(v-for="index in 6")
        .cover(:style="background-image:url('https://picsum.photos/id/1084/800/600')")
          h1 海象樂園
          h5 趴在冰層上的懶惰動物

有了基礎骨架後來準備拉皮,準備兩組Sass的mixin如下:

  1. flex_center:將物件保持在畫面的垂直水平正中央。
  2. size:快速設定物件的寬和高,考慮到時常會製作正方形的物件,設定成如果沒有額外填寫$h時,自動帶入$w的值。
@mixin flex_center
  display: flex
  justify-content: center
  align-items: center
  
@mixin size($w,$h: $w)
  width: $w
  height: $h

為了不讓畫面隨著播放整個一起移動(scroll),把畫面撐到跟視窗一樣100%大,然後設定overflow:hidden,再把背景設定成深色#1c1c1c。

小心網頁中繼承設定

接下來要設定app、postarea、posts、postbox這四者之間的位置和尺寸,要注意的是CSS觀念中子層如何繼承父層的設定,這樣才會知道在設定這麼多height:100%時到底是吃到誰的高度。先把最外層的#app size撐到100%,然後把現在為div形態的.postbox用語法display:inline-block變成水平(橫向),因為子層寬度大於父層時會自動往下折,所以.postarea需要用語法white-space:nowrap處理,其他寬高設定可以參考以下。

製作幻燈片

先前有說過輪播是透過幻燈片的推移來完成,剛開始我們在Vue有設定過每一張的幻燈片的寬度為930px span:930cover的尺寸為330px,做個小小的數學運算後,可知幻燈片之間的距離應為600px,左右各300px,用語法background-size:cover讓海象完整呈現。

把標題和敘述包在infos中,我們可以觀察到其實文案和圖片只有小部分的重疊,比較偷呷步的做法是把infos包在cover內,用translateX製造偏移。在瀏覽器中h1、h5有預設的margin記得取消,其他參數設定附上詳細的sass給大家參考,這樣單張的幻燈片就做好囉!

sass
.cover
    +size(330px, 100%)
    margin-left: 300px //930px-330px
    margin-right: 300px
    background-size: cover
    +flex_center
    
  .infos
    color: white
    transform: translateX(-200px) //運用X軸偏移製造部份重疊
    text-shadow: 0px 0px 30px rgba(0,0,0,0.3) //避免文案與圖片重疊辨識不清
    *
      margin: 0 //取消預設的h1、h5 margin
    
    h1
      margin-bottom: 10px
      font-size: 50px
      font-weight: 400
      
    h5
      background-color: #fff
      color: #000
      padding: 4px 12px
      font-size: 20px
      font-weight: 300
      box-shadow: 0px 0px 30px rgba(0,0,0,0.3)

準備好幻燈片後,接下來要計算如何播放,在Vue裡面定義一個新的計算屬性computed,內部再包一個會回傳一組CSS動態地套進去的functioncomputed_left。那要如何計算呢?既然.postarea是一個固定的畫框,我們想像.posts這個長條每偏移一次now_index都向左移一個span的寬度,在HTML加上:style ="computed_left",在CSS裡面的.posts加上position: relative才能吃到位置的資訊哦!最剛開始的時候還不用偏移,所以now_index值從0開始。用console.log可以看到偏移的計算結果,記得再return結果。

computed:{
    computed_left(){
      var result={
        "left": (-this.now_index * this.span) + "px"
      };
      console.log(result);
      return result;
    }
  }

動起來了是不是很感動!但你有沒有發現輪播跟已發車的火車一樣一去不回頭,通常我們希望輪播是會循環的,當在最後一張按下下一張的按鈕時,就會自動跳回第一張從頭開始。讓我們稍微思考一下變換的pattern,可以運用餘數和總長度的關係來呈現。

methods: {
    delta(d){
      // 0 1 2 3 4 
      // (-1 + 5) = 4
      // (5 % 5)=0
      // ((id +5) % 5) = 0
      // -1 => ((-1+5) % 5) = 4
      // 1 => ((1+5) % 5) = 1
      // 5 => ((5+5) % 5) = 0
      this.now_index =
        (this.now_index + d +this.works.length) % this.works.length
    }
  }

會循環的輪播才叫輪播

完成了左右切換循環連播的功能,現在來把先前的資料換成變數,原先寫成固定CSS style的cover改寫成Vue的functionbg_css,這樣資料就抽換完成了。

JavaScript

bg_css(url){
      return {
        "background-image": "url("+url+")"
      };
    }

HTML

#app
  .postarea
    .posts(:style="computed_left")
      .postbox(v-for="w in works")
        .cover(:style="bg_css(w.cover)")
          .infos
            h1 {{w.title}}
            h5 {{w.description}}

再加上互動按鈕

有了輪播的圖片,少不了左右切換的按鈕和使用者互動,把font-awesome(一個提供很多icon的免費平台)掛入CSS的CDN。

在font-awesome上選好左右icon後加在HTML內,在CSS設定按鈕的參數。

這邊大家可以根據自己的美感調整,通常在執行動作時都會加上transition讓互動不會那麼生硬,這時可以新增transition的mixin來統一整個網站的互動參數。

@mixin trans($t:0.5s, $td:0s)
  transition: $t $td
//t為變化持續的時間,td為延遲變化的時間

在HTML裡再用click把剛剛寫的function delta綁定在按鈕上,往左往右分別設定成1和-1,可用按鈕操作的輪播就大功告成啦!

最後起鍋前再加點鹽 最後再加一些微互動提升質感,通常互動可以以滑鼠事件為主,當使用者的滑鼠進入到特定區塊時,透過放大或偏移來增加點擊的機率。這邊提供老闆的做法讓大家參考,也可以想想還有什麼其他有趣的互動唷!

SASS

.cover
    +size(330px, 100%)
    margin-left: 300px //930px-330px
    margin-right: 300px
    background-size: cover
    background-position: center center
    +flex_center
    +trans
    cursor: pointer
    
    &:hover
      +size(340px,110%)
      .infos
        transform: translateX(-220px) translateY(-10px)

另外我們也可以透過Vue,在物件符合特定條件下時,才加入指定的動畫。這邊呈現的效果是當幻燈片切入的瞬間,從淺到深的透明度轉換效果。

HTML

當現在呈現的物件的id=now_index時,就會帶入cur_item的效果

.postbox(v-for="(w,id) in works", :class="{cur_item: id==now_index}")

CSS

針對cover設定一組名為fadeIn的keyframe,切換的瞬間會從透明度0變成透明度1,x軸也會稍微偏移,整組動畫的時間為1秒,動態為ease。infos也加上一些x軸偏移的效果增加速度感。

@keyframes fadeIn
  0%
    opacity: 0
    transform: translateX(30px) 
    filter: saturate(0%)
  100% 
    opacity: 1
    transform: translateX(0px) 
    filter: saturate(100%) 
 
@keyframes sliceIn
  0%
    transform: translateX(-50px) 
  100%
    transform: translateX(0px) 

.cur_item
  .cover
    animation: fadeIn 1s ease both
  .infos
    h5
      animation: sliceIn 1s 0.1s ease
```

以上就是這次如何用Vue.js快速做出輪播效果,從最一開始的資料處理、計算輪播距離和計算delta變化量轉換成座標,最後再加上一些玩轉的細節動畫。

希望大家還喜歡這次的小範例,如果對類似的網頁效果有興趣,歡迎來看看我們在Hahow所開設的動畫互動網頁程式入門(HTML/CSS/JS)以及動畫互動網頁特效入門(JS/CANVAS)有更多好玩的網頁動畫教學,那我們下次再見囉。

Codepen實作範例:https://codepen.io/frank890417/pen/bWrKOZ

此篇直播筆記由幫手 Jeudi Kuo 協助整理

墨雨設計banner

訂閱 Creative Coding Taiwan 電子報:

PHP Code Snippets Powered By : XYZScripts.com