如何快速實現一個無縫輪播效果

林恒發表於2024-07-09

🧑‍💻 寫在開頭

點贊 + 收藏 === 學會🤣🤣🤣

需求簡介

輪播圖是我們前端開發中的一個常見需求,在專案開發中,我們可以使用element、ant等UI庫實現。某些場景,為了一個簡單的功能安裝一個庫是沒必要的,我們最好的選擇就是手搓。

我們來看一個需求

上述需求核心就是實現一個無縫輪播的切換效果。以這個需求為例,我們看看最終實現效果:

實現思路

要想實現一個無縫的輪播效果,其實非常簡單,核心思想就是動態改變顯示的列表而已。比如我們有這樣一個陣列

const list = ref([
    { name: 1, id: 1 }, 
    { name: 2, id: 2 },
    { name: 3, id: 3 }
])

如果我們想無縫切換的展示這個資料,最簡單的程式碼就是動態的改變下面的程式碼的index

<template>
    <div>
       {{ list[index] }}
    </div>
</template>
<script setup>
    const index = ref(0)
    const list = ref([{ name: 1, id: 1 }, { name: 2, id: 2 }, { name: 2, id: 2 }])
<scriptp>

那如何實現切換的樣式呢?也非常簡單,我們只要給元素新增一個出現樣式和離開樣式即可。現在,我們來具體實現這樣一個需求。

技術方案

資料的動態切換

要想實現一個資料的動態迴圈切換效果,是非常容易的:

<template>
 <div v-for="(build, index) in list" :key="index">
    <div v-show="index === selectIndex">
       卡片自定義內容
    </div>
 </div>
</template>
<script setup>
const selectIndex = ref(0)
const list = ref(
    [{ name: "卡片1", id: 1 }, { name: "卡片1", id: 2 }, { name: "卡片1", id: 2 }]
)

// #計時器例項
let timer: any = null

// >計時器邏輯
const timeFuc = () => {
    timer = setInterval(() => {
      // 更改選中的index
      if (selectIndex.value >= list.value.length - 1) {
        selectIndex.value = 0
      } else {
        selectIndex.value++
      }
    }, 5000)
}

timeFuc()
<scriptp>

上述程式碼中,我們設定了一個定時器,定時器每5s執行一次,每次執行都會動態更改當前要顯示的資料索引值,當索引值達到最大實,在將其重置。透過上述的簡單程式碼,我們就實現了一個可以自動切換的迴圈渲染的卡片。

動畫新增

要想實現最終效果的動態效果也非常容易,我們只需要給每個元素出現時設定一些樣式,離開時設定一些樣式即可。藉助vue的Transition元件,我們能很容易實現這樣一個效果。

如果你不瞭解vue的Transition元件,請去官網補充下知識:cn.vuejs.org/guide/built…

<template>
<div class="main-content">
    <Transition v-for="(build, index) in list" :key="selectIndex">
        <div class="banner-scroll-wrap" v-show="index === selectIndex">
            卡片自定義內容
        </div>
    </Transition>
</div>
</template>
<script setup>
const selectIndex = ref(0)
const list = ref(
    [{ name: "卡片1", id: 1 }, { name: "卡片1", id: 2 }, { name: "卡片1", id: 2 }]
)

// #計時器例項
let timer: any = null

// >計時器邏輯
const timeFuc = () => {
    timer = setInterval(() => {
      // 更改選中的index
      if (selectIndex.value >= list.value.length - 1) {
        selectIndex.value = 0
      } else {
        selectIndex.value++
      }
    }, 5000)
}

timeFuc()
<scriptp>
<style lang="less" scoped>
.main-content {
    position: relative;
    height: 100%;
    .banner-scroll-wrap {
        position: absolute;
        top: 0;
        bottom: 0;
        right: 0;
        left: 0;
    }
}

.v-enter-from {
    transform: translateX(100%);
    opacity: 0;
}

.v-enter-active,
.v-leave-active {
    transition: transform 600ms ease-in-out, opacity 600ms ease-in-out;
}

.v-enter-to {
    transform: translateX(0);
    opacity: 1;
}

.v-leave-from {
    transform: translateX(0);
    opacity: 1;
}

.v-leave-to {
    transform: translateX(-100%);
    opacity: 0;
}
<style/>

上述程式碼中,由於 selectIndex是動態的,元素不斷地在顯示與隱藏。因此,Transition標籤的進入樣式和離開樣式會動態觸發,從而形成切換效果。

v-enter是元素的進入樣式,進入時,我們從最右邊偏移100%的距離到正常位置,透明度從0到1,這個過程持續0.6s,實現了元素左移淡入的效果。

v-leave是元素的離開樣式,離開時,我們從正常位置偏移到100%的左側位置,透明度從1到0,這個過程持續0.6s,實現了元素左移淡出的效果。

在這些類的共同作用下,我們實現了元素的動態切換。

你可能注意到了我給元素設定了一個banner-scroll-wrap類名,並使用了position: absolute,這樣設定的注意目的是保證切換離開元素的淡出效果和進入元素的淡入效果是連貫的。如果你不這樣寫,可能會出現樣式問題。

此外,注意我給Transition設定了key="Transition",這樣些會保證每次資料在切換時,transition能夠重新渲染,觸發元素離開和進入的樣式。

至此,我們就完成了基本功能樣式

輪播的停止與恢復

很常見的一種情況就是我們需要滑鼠放在卡片上時停止輪播,離開卡片的時候恢復輪播,這非常容易。

<template>
<div class="main-content"  @mouseenter="stop()" @mouseleave="start()">
    <Transition v-for="(build, index) in list" :key="selectIndex">
        <div class="banner-scroll-wrap" v-show="index === selectIndex">
            卡片自定義內容
        </div>
    </Transition>
</div>
</template>
<script setup>
const selectIndex = ref(0)
const list = ref(
    [{ name: "卡片1", id: 1 }, { name: "卡片1", id: 2 }, { name: "卡片1", id: 2 }]
)

// #計時器例項
let timer: any = null

// >計時器邏輯
const timeFuc = () => {
    timer = setInterval(() => {
      // 更改選中的index
      if (selectIndex.value >= list.value.length - 1) {
        selectIndex.value = 0
      } else {
        selectIndex.value++
      }
    }, 5000)
}

  // >開啟輪播
  const start = () => {
    if (timer) return
    timeFuc()
  }

  // >關閉輪播
  const stop = () => {
    clearInterval(timer)
    timer = null
  }

timeFuc()
<scriptp>
<style lang="less" scoped>
<style/>

解決重影問題

在某些情況下,我們離開這個頁面很久後(瀏覽器切換到其他選項卡),然後在切回來的時候,可能會出現短暫的畫面重影問題,這個問題也很好解決,加上下面的程式碼即可

<script setup>

    //...

    // 解決切屏後重影的問題
  onMounted(() => {
    document.addEventListener('visibilitychange', () => {
      // 使用者息屏、或者切到後臺執行 (離開頁面)
      if (document.visibilityState === 'hidden') {
        stop()
      }
      // 使用者開啟或回到頁面
      if (document.visibilityState === 'visible') {
        start()
      }
    })
  })
    
  onBeforeUnmount(() => stop())

<scriptp>

visibilitychange 事件:當其選項卡的內容變得可見或被隱藏時,會在 document 上觸發 visibilitychange 事件。該事件不可取消。

總結

在本教程中,我們透過簡單程式碼實現了無縫輪播效果,樣式是左右切換,我們也可以透過樣式控制實現上下切換的效果,比如將translateX設定為translateY即可。

 .v-enter-from {
    transform: translateY(100%);
    opacity: 0;
}
時間原因,本教程也沒有對技術上做深究,也希望各位大佬能提供自己的思路與建議,感謝大家分享!

如果對您有所幫助,歡迎您點個關注,我會定時更新技術文件,大家一起討論學習,一起進步。

如何快速實現一個無縫輪播效果

相關文章