基於 flex 的 order 實現 carousel 輪播圖

緣由

項目裏須要使用輪播圖,electron + vue 技術棧,項目應用一旦啓動會持續運行24小時,而且機器性能較差,因此很關注兩個點css

  1. 內存泄漏
  2. 性能

目前社區的輪播組件,大多隻是適用於常規 web 應用,通過內部測試後,並不能知足內存和性能方面的要求,因此須要本身實現輪播組件html

思路

最開始找到了這篇文章,裏面講解了傳統的輪播圖實現思路和做者原創的輪播思路,並在文末給出了性能較高的原創方案。vue

做者的原創方案性能是很高了,可是我注意到每次執行輪播都須要移動一個 DOM 節點,這會觸發瀏覽器重排重繪,性能依舊不夠高,還能夠繼續優化。web

首先想到了 flex 佈局的 order 屬性:https://developer.mozilla.org/zh-CN/docs/Web/CSS/orderchrome

兼容性

能夠看到只有現代瀏覽器才支持,若是要兼容老久瀏覽器就不用考慮本方案了,個人環境是electron 2.0,集成的chrome 61,可以使用。瀏覽器

實現方案

本文章只記錄實現方案與僞代碼,不會給出 demo。electron

基本功能實現

html結構函數

<div class="carousel">
  <div class="carousel-container" style="transition-duration: 0ms; transform: translate3d(0px, 0px, 0px);">
    <!-- 輪播列表元素 -->
    <div class="carousel-item" style="order: 0;"></div>
    <div class="carousel-item" style="order: 1;"></div>
    <div class="carousel-item" style="order: 2;"></div>
    <div class="carousel-item" style="order: 3;"></div>
    <div class="carousel-item" style="order: 4;"></div>
  </div>
</div>
<style> .carousel { width: 100%; } .carousel-container { width: 100%; display: flex; transition-property: transform; } .carousel-item { width: 100%; } </style>
複製代碼

從裏面元素開始解釋佈局

  1. 父級設置 display: flex ,子級能夠經過 order 屬性實現排序,這種排序雖然依然會引起重排和重繪,可是開銷更小
  2. 外圍一層元素,使用 transition 實現 動畫,使用 transform 的 translate3d 實現硬件加速與顯示範圍。在非動畫狀態,X軸的位置永遠都是 0,在動畫狀態,纔給 X軸 賦值,因此整個組件其實就是在作兩件事: 順序X軸位置(也就是動畫)
  3. 順序:非動畫狀態須要 X 軸一直爲0,那麼就要保證當前要顯示的輪播元素的 order 值最小,我暫時約定最小爲 0,由於動畫涉及到下一張,因此當前輪播的order 爲 0,下一張爲 1,其餘的只要大於1 便可。
  4. 動畫,若是需求是切換的時候不須要動畫,那麼保證順序就已經完成了輪播切換了,但需求一般須要動畫。動畫的實現由三部分,起始狀態結束狀態重置狀態
  5. 起始狀態:動畫一開始,就是要在當前輪播元素開始,對應的X軸是0,起就是靜止狀態,因此起止狀態不須要設置,默認就是了,因此一般其實狀態無需處理
  6. 結束狀態:結束的狀態是下一張輪播元素徹底顯示,也就是X增長一個 輪播元素的寬度。動畫時間 transition-duration 賦值 500ms,就能實現動畫。
  7. 重置狀態:動畫完成後,從新計算各個元素的 order 值,把 X 軸重設爲0,動畫時間重設爲0

到此就完成了輪播組件的基本功能post

功能擴展

自動輪播

先實現一個函數 next() 方法,定時調用

拖動滾動

  1. 記錄開始拖動時鼠標位置的 X軸
  2. 移動過程當中獲取鼠標位置X軸,減去開始拖動時的X軸位置,獲得X軸移動的距離,再把這個距離數字賦值給 translate3d 的X軸

反向動畫與拖動

一般的輪播都是 從右往左 滾動的,可是有時須要兼容 從左往右,實現方案:

非動畫狀態無需調整,主要關注動畫狀態。

  1. 排序:要反過來排序,當前顯示的元素 order 爲0,下一張爲 -1,其餘的小於 -1便可
  2. 動畫的不一樣狀態都須要調整
  3. 起始狀態:X軸位置:-1 * (輪播條數 - 1) * 輪播寬度
  4. 結束狀態:X軸位置:-1 * (輪播條數 - 與上條間隔數量) * 輪播寬度
  5. 重置狀態:X軸位置:0,排序重置爲正向

反向拖動,若是拖動的時候拖動的距離是個正數,則立刻更新順序爲反向,若是爲負數,立刻更新順序爲正向

總結

該方案的性能很高,可是兼容性不太好。並且實現過程當中,對元素的排序計算若是涉及到反向動畫的話會比較複雜

相關文章
相關標籤/搜索