實例詳解如何給輪播圖做自適應的高度

藏色散人
發布: 2023-04-01 08:30:02
轉載
1982 人瀏覽過
這篇文章為大家帶來了關於前端的相關知識,其中主要介紹了怎麼給輪播圖做一個自適應的高度,感興趣的朋友下面一起來看一下吧,希望對大家有幫助。

不知道大家有沒有遇到這樣的需求或說看到類似的效果,就是清單進去詳情看輪播圖的時候,當手指滾動輪播圖時輪播的高度容器會自適應,這樣下面的內容就向上擠,滑動的過程會計算高度,釋放的時候也會滾到下一張,也會計算對應圖片的高度,然後做一個緩動的動畫效果。就像下面這張圖的樣子。

實例詳解如何給輪播圖做自適應的高度

可以看到上面的圖片內容文字,隨著輪播的滑動高度也在改變。費話不多說直接上代碼。

實作方法

可以透過監聽滑鼠mounse 或手指的滑動touch 事件來控制圖片,這裡本文只說一下輪播的功能實現思路,重點說的是怎麼實現高度的自適應。

直接開始正文,先看 html 程式碼結構。

html 結構

<div>
  <div>
    <div>
      <div>
        <img  alt="實例詳解如何給輪播圖做自適應的高度" >
      </div>
      <div>
        <img  alt="實例詳解如何給輪播圖做自適應的高度" >
      </div>
      <div>
        <img  alt="實例詳解如何給輪播圖做自適應的高度" >
      </div>
    </div>
  </div>
  <div>这是一段内容</div>
</div>
登入後複製

css 樣式

.container {
  width: 100%;
  overflow: hidden;
}.wrapper {
  width: 100%;
}.swiper {
  font-size: 0;
  white-space: nowrap;
}.item {
  display: inline-block;
  width: 100%;
  vertical-align: top; // 一定要使用顶部对齐,不然会出现错位的情况
}.item img {
  width: 100%;
  height: auto;
  display: block;
}.content {
  position: relative;
  z-index: 9;
  font-size: 14px;
  text-align: center;
  padding-top: 20px;
  background-color: #fff;
  height: 200px;
}
登入後複製

值得注意的地方有幾點;

  1. #使用父級white-space 時,子集元素設定display: inline-block 會出現高度不同的排列錯位,解決方法就是加上一句 vertical-align: top ,具體什麼原因我也不細講了。
  2. 另外父級還要設定 font-size: 0 ,如果沒加上的話,就會出現兩個子集有空隙出現,加上之後空隙就會去掉。
  3. img 圖片最好設定成高度自適應,寬度100% 還要加上 display: block ,沒有的話底部就會出現間隙。

寫好上面的 html容器部分和 樣式,下面就來看看 js 上是怎麼處理的。

Js 實作

開始之前我們先思考一下去怎麼實現這個輪播以及高度的自適應問題,分成幾個步驟;

  1. 滑鼠按下時,需要記錄目前的位置和一些其他初始化的訊息,並且在目前的父元素中加入對應的滑鼠事件。
  2. 滑鼠移動時,需要透過當前即時移動時點位和按下時點位的相減,得到移動的距離位置,然後再賦值給父元素設定其樣式transform 位置,中間還做其他的邊界處理,當然還有高度的變化。
  3. 滑鼠釋放是,透過移動時記錄的距離資訊判斷是左滑還是右滑,拿到其對應的索引,透過索引就可以計算到滾動下一張的距離,釋放之後設定transition 過渡動畫即可。

按照我們試想的思路,開始正文;

初始化資料

const data = {
  ele: null,
  width: 0,
  len: 0,
  proportion: .3,
  type: false,
  heights: [500, 250, 375],
  currentIndex: 0,
  startOffset: 0,
  clientX: 0,
  distanceX: 0,
  duration: 30,
  touching: false
}

const wrapper = data.ele = document.querySelector(&#39;.wrapper&#39;)
const items = document.querySelectorAll(&#39;.item&#39;)
data.width = wrapper.offsetWidth
data.len = items.length - 1
wrapper.addEventListener(&#39;touchstart&#39;, onStart)
wrapper.addEventListener(&#39;mousedown&#39;, onStart)
登入後複製

注意,這裡在做高度之前,我們需要等圖片載入完成後才能拿到每一個元素的高度,我這裡為了省懶就沒寫具體代碼,上面的heights 對應的是每個圖片在渲染之後的高度,一般情況下最好讓後端傳回來頻寬高,這樣就不需要用onload 再去處理這個。

滑鼠按下時

function onStart(event) {
  if (event.type === &#39;mousedown&#39; && event.which !== 1) return
  if (event.type === &#39;touchstart&#39; && event.touches.length > 1) return
  data.type = event.type === &#39;touchstart&#39;
  const events = data.type ? event.touches[0] || event : event

  data.touching = true
  data.clientX = events.clientX
  data.startOffset = data.currentIndex * -data.width

  data.ele.style.transition = `none`
  window.addEventListener(data.type ? &#39;touchmove&#39; : &#39;mousemove&#39;, onMove, { passive: false })
  window.addEventListener(data.type ? &#39;touchend&#39; : &#39;mouseup&#39;, onEnd, false)
}
登入後複製

上面的程式碼裡面我做了PC和行動端的相容,跟計畫的一樣,儲存一下clientX 座標和一個初始的座標startOffset 這個由當前索引和父級寬度計算得到,場景是當從第二張圖片滾動到第三張圖片時,會把之前的第一張圖片的距離也要加上去,不然就計算錯誤,看下面滑動時的程式碼。

另外在做監聽移動的時候加上了 passive: false 是為了在行動端相容處理。

滑鼠移動時

function onMove(event) {
  event.preventDefault()
  if (!data.touching) return
  const events = data.type ? event.touches[0] || event : event

  data.distanceX = events.clientX - data.clientX

  let translatex = data.startOffset + data.distanceX
  if (translatex > 0) {
    translatex = translatex > 30 ? 30 : translatex
  } else {
    const d = -(data.len * data.width + 30)
    translatex = translatex < d ? d : translatex
  }

  data.ele.style.transform = `translate3d(${translatex}px, 0, 0)`
  data.ele.style.webkitTransform = `translate3d(${translatex}px, 0, 0)`
}
登入後複製

做了一個邊界處理的,超了30 的距離就不讓繼續​​滑動了,加上之前儲存的startOffset 的值,得到的就是具體移動的距離了。

滑鼠釋放時

function onEnd() {
  if (!data.touching) return
  data.touching = false

  // 通过计算 proportion 滑动的阈值拿到释放后的索引
  if (Math.abs(data.distanceX) > data.width * data.proportion) {
    data.currentIndex -= data.distanceX / Math.abs(data.distanceX)
  }
  if (data.currentIndex < 0) {
    data.currentIndex = 0
  } else if (data.currentIndex > data.len) {
    data.currentIndex = data.len
  }
  const translatex = data.currentIndex * -data.width

  data.ele.style.transition = &#39;all .3s ease&#39;
  data.ele.style.transform = `translate3d(${translatex}px, 0, 0)`
  data.ele.style.webkitTransform = `translate3d(${translatex}px, 0, 0)`

  window.removeEventListener(data.type ? &#39;touchmove&#39; : &#39;mousemove&#39;, onMove, { passive: false })
  window.removeEventListener(data.type ? &#39;touchend&#39; : &#39;mouseup&#39;, onEnd, false)
}
登入後複製

透過計算proportion 滑動的閾值拿到釋放後的索引,也就是超過父級寬度的三分之一時釋放就會捲動到下一張,拿到索引之後就可以設定需要移動的最終距離,記得加上transition 做一個緩動效果,最後也別忘記移除事件的監聽。

至此上面的簡單的輪播效果就大功告成了,但是還缺少一點東西,就是本篇需要講的自適應高度,為了方便理解就單獨拿出來說一下。

高度自適應

在移動時就可以在裡面做相關的程式碼整理了,onMove 函數裡加上以下程式碼,來獲取實時的高度。

const index = data.currentIndex
const currentHeight = data.heights[index]
    
// 判断手指滑动的方向拿到下一张图片的高度
let nextHeight = data.distanceX > 0 ? data.heights[index - 1] : data.heights[index + 1]
let diffHeight = Math.abs((nextHeight - currentHeight) * (data.distanceX / data.width))
let realHeight = currentHeight + (nextHeight - currentHeight > 0 ? diffHeight : -diffHeight) 
 data.ele.style.height = `${realHeight}px`
登入後複製

这里是移动时的高度变化,另外还需要在释放时也要处理, onEnd 函数里加上以下代码。

// ... 因为上面已经拿到了下一张的索引 currentIndex
const currentHeight = data.heights[data.currentIndex]

data.ele.style.height = `${currentHeight}px`
登入後複製

因为上面已经拿到了下一张的索引 currentIndex 所以再滚动到下一张是就直接通过数据获取就可以了。

推荐学习:《web前端开发视频教程

以上是實例詳解如何給輪播圖做自適應的高度的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:juejin.im
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!