這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助
前言: 近期我在專案中就接到了一個完成輪播圖組件的需求,最開始我也像大家一樣,直接選擇使用了知名的開源專案 "Swiper",但是后來發現它在移動端專案中某些測驗環境下會白屏一段時間,無論如何除錯都不能修復這個問題,于是就自己上手寫了個輪播圖組件,實作代碼其實也只有 200 行,很少但是完美解決了我們專案的問題,
雖然已經 2023 年了,但是輪播圖組件的實作仍然是考驗前端基本功的經久不衰的題目,于是來分享一下實作思路,??
tips: 本文主要目的不是一上來就貼代碼,而是會一步一步帶你理清細節部分,即使你現在沒有輪播圖這個需求,
一. 使用 overflow-scroll 完成基礎框架
-
大家在專案中肯定接觸到溢位滾動的需求,其實就是用到了 overflow-auto 等相關屬性,
-
注意:樣式方面,在這里我使用的是
UnoCSS
,將樣式內聯在了標簽里,如果你還不了解這種寫法,你可以點擊下方的文章學習,不過即使你之前從未了解過UnoCSS
,也不會影響你下面的閱讀,因為樣式不是本文的重點,并不影響整體閱讀,
??手把手教你如何創建一個代碼倉庫 -
讓我們快速制造一個溢位的場景來完成準備作業,其實非常簡單,就是簡單的創造一個容器,容器里放著三個和容器寬高相同的 div,然后給父容器一個 overflow-auto 屬性,讓它可以在內容溢位的時候發生滾動,
-
效果如下:
二. 實作合適位置自動切換
-
現在我們僅僅實作了一個可以滾動的容器而已,但是輪播圖最主要的事情就是用戶滾動的位置不合適,那么我們也要自動調整到合適的位置顯示,
-
更具體來講,就是當我們拖動圖片到了中間這樣的位置松手時,輪播圖最重要一個功能就是可以自動切換到上一張或者下一張,準確的顯示合適的內容給用戶,(因為展示內容區域展示一半一半的內容毫無意義嘛,)
-
這里就需要用到兩個至關重要的 CSS 屬性,
- snap-type
- snap-align
我們先看 snap 這個單詞的意思,在這里它的意思我認為 “咔嚓一聲,折斷” 更符合這個屬性的含義,不要著急,你可以暫時先帶著這個模糊的概念來慢慢理解接下來的內容,
-
我們先看 snap-type 是用來干什么的,
這里 MDN 的解釋不是特別好懂,接下來我會用人話翻譯一下它想表達的含義, -
回到我們的代碼部分,我們創建了一個容器 div,并且這個容器因為溢位,并且設定了 overflow-滾動 相關屬性,
其實我們的 scroll-type 是用來給滾動容器的!這里特別注意,它一定是用在設定了 overflow-auto 等屬性的那個元素上的, -
關于屬性值,我們采用 snap-type: x mandatory,
在這里x
的含義代表著橫軸發生的滾動,那么聰明的你可以猜到,它也有一個y
屬性,代表著豎軸發生滾動時的設定, -
這里還有一個關鍵字
mandatory
代表著強制的意思,因為在某些情況下,瀏覽器會認為用戶滑到下面這種位置是自愿的,但是我們的場景是不需要考慮這種情況的,所以要告訴瀏覽器我們需要你幫我 “強制咔嚓折斷”, -
至于 proximity ,這個屬性的演算法有點奇怪,我也沒太搞懂它的含義,不過我們的需求不需要用到這個關鍵字,大家有興趣也可以自行查閱,
-
接下來給我們的容器設定這個屬性,讓我們先看看效果,
-
什么情況?怎么沒效果呢?目前為止我們僅僅給容器設定了滾動的需求還是不夠的,還得告訴子元素滾動到什么位置停下才行,這里就需要用到
snap-align
屬性了,它是給滾動容器的子元素設定的, -
snap-align
,這個屬性有三個值可以設定,none
,center
和end
,
其實從這個屬性的名字就可以猜到,它其實設定的是子元素的位置是相對于滾動容器的左邊對齊還是右邊對齊, -
怎么理解呢?我們將滾動容器的寬度調大,讓它可以漏出一點點其它元素的內容,并且只給數字2的元素設定 scroll-align 相關屬性,(tips: 這里需要重點注意,我們只給了一個元素設定了這個屬性,另外兩個元素是沒有設定這個屬性的,)
-
snpa-align: start (元素2無論如何都會在松開滑鼠的時候緊貼著滾動容的左邊,也就是滾動容器的 start 位置
-
snap-align: center (元素2無論如何都會緊貼著滾動容器中間位置
-
snap-align: end (元素2的右邊無論如何都會緊貼著滾動容器
-
-
知道了這三個屬性的區別,那么接下來復原我們的容器樣子,因為我們實際上輪播圖的每一項的寬高和滾動容器的內容區是恰好相等的,所以我們給子元素無論設定怎樣的三個值的效果都是一樣的,
讓我們看一下效果:
看起來效果還不錯~
三. 實作上一項和下一項切換功能
-
我們準備兩個按鈕,當用戶點擊這兩個按鈕的時候,可以進行手動的切換上一張和下一張,
-
這里我們需要用到滾動容器的 scroll 事件,需要給滾動容器系結相對的回呼函式,
這里通過e.target
就可以拿到我們滾動容器本身,容器自身存在一個 scollLeft 屬性,你需要知道一個知識點其實發生滾動的本質就是 scrollLeft 值的變化,
注意觀看下面滾動容器的 scrollLeft 屬性值的變化,
-
知道了這個關鍵點,那么我們的
pre
和next
函式就可以很明確的書寫了, 首先通過 ref 拿到元素本身,
-
然后在
pre
函式內部獲取當前滾動元素的scollLeft
值,
-
緊接著,你需要知道的是,這個值即是一個可讀屬性,也是一個可寫屬性,那么我們就可以進行判斷,如果當前照片不是第一張的話,,那么我就讓 scrollLeft 的值 -300,這里有兩個關鍵的知識點,
- 第一張對應的 scrollLeft 等于0
- 這里的 300 是我們寫死的寬度,你可以根據后面自己的專案優化這個值,
-
讓我們看一下效果,先讓我們手動滾動到第三張,然后點擊上一張切換,
-
這里好像有一點點不對勁,我們不是平緩過度到上一張的而是直接切換到上一張的,這里很簡單,需要給滾動容器設定一個
scroll-behavior:smooth
即可,
我們看一下效果:
-
下一張按鈕的實作同理,這里不過多贅述,代碼如下:
-
最終的效果:
四. 原始碼
<script setup lang="ts"> import { ref, computed } from "vue"; const box = [ { number: 1, bg: "blue", }, { number: 2, bg: "pink", }, { number: 3, bg: "red", }, ]; const containerEl = ref<HTMLDivElement>(); function scrollEvent(e: UIEvent) { const containerEl = e.target as HTMLDivElement; } // 上一張 function pre() { const el = containerEl.value; if (!el) return; const scrollLeft = el?.scrollLeft; if (scrollLeft > 0) { el.scrollLeft = scrollLeft - 300; } } function next() { const el = containerEl.value; if (!el) return; const scrollLeft = el?.scrollLeft; const max = (box.length - 1) * 300; //輪播圖的數量 -1 if (scrollLeft < max) { el.scrollLeft = scrollLeft + 300; } } </script> <template> <div > <div @click.stop="pre" > <span >上一張</span> </div> <div ref="containerEl" @scroll="scrollEvent" > <div v-for="(item, index) in box" :style="{ backgroundColor: item.bg }" > <span >{{ item.number }}</span> </div> </div> <div @click="next" > <span >下一張</span> </div> </div> </template>
本文轉載于:
https://juejin.cn/post/7248655627927601207
如果對您有所幫助,歡迎您點個關注,我會定時更新技術檔案,大家一起討論學習,一起進步,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/556056.html
標籤:Html/Css
上一篇:React實戰--利用甘特圖和看板,強化Paas平臺應用
下一篇:返回列表