搜尋
首頁web前端js教程使用JS如何實現瀑布流插件
使用JS如何實現瀑布流插件Jun 07, 2018 pm 02:28 PM
原生js瀑布流

這篇文章給大家詳細分析了一個原生JS實作瀑布流插件以及程式碼相關講解,對此有興趣的讀者們參考學習下吧。

瀑布流佈局中的圖片有一個核心特點—等寬不定等高,瀑布流佈局在國內網網站都有一定規模的使用,例如pinterest、花瓣網等等。那麼接下來就基於這個特點開始瀑布流探索之旅。

基礎功能實作

首先我們定義好一個有20 張圖片的容器,

<body>
 <style>
  #waterfall {
   position: relative;
  }
  .waterfall-box {
   float: left;
   width: 200px;
  }
 </style>
</body>
<p id="waterfall">
  <img  class="waterfall-box lazy"  src="/static/imghwm/default1.png"  data-src="images/1.png"    alt="使用JS如何實現瀑布流插件" >
  <img  class="waterfall-box lazy"  src="/static/imghwm/default1.png"  data-src="images/2.png"    alt="使用JS如何實現瀑布流插件" >
  <img  class="waterfall-box lazy"  src="/static/imghwm/default1.png"  data-src="images/3.png"    alt="使用JS如何實現瀑布流插件" >
  <img  class="waterfall-box lazy"  src="/static/imghwm/default1.png"  data-src="images/4.png"    alt="使用JS如何實現瀑布流插件" >
  <img  class="waterfall-box lazy"  src="/static/imghwm/default1.png"  data-src="images/5.png"    alt="使用JS如何實現瀑布流插件" >
  <img  class="waterfall-box lazy"  src="/static/imghwm/default1.png"  data-src="images/6.png"    alt="使用JS如何實現瀑布流插件" >
  ...
 </p>
由于未知的 css 知识点,丝袜最长的妹子把下面的空间都占用掉了。。。
接着正文,假如如上图,每排有 5 列,那第 6 张图片应该出现前 5 张图片哪张的下面呢?当然是绝对定位到前 5 张图片高度最小的图片下方。
那第 7 张图片呢?这时候把第 6 张图片和在它上面的图片当作是一个整体后,思路和上述是一致的。代码实现如下:
Waterfall.prototype.init = function () {
 ...
 const perNum = this.getPerNum() // 获取每排图片数
 const perList = []       // 存储第一列的各图片的高度
 for (let i = 0; i < perNum; i++) {
  perList.push(imgList[i].offsetHeight)
 }
 let pointer = this.getMinPointer(perList) // 求出当前最小高度的数组下标
 for (let i = perNum; i < imgList.length; i++) {
  imgList[i].style.position = &#39;absolute&#39; // 核心语句
  imgList[i].style.left = `${imgList[pointer].offsetLeft}px`
  imgList[i].style.top = `${perList[pointer]}px`

  perList[pointer] = perList[pointer] + imgList[i].offsetHeight // 数组最小的值加上相应图片的高度
  pointer = this.getMinPointer(perList)
 }
}

細心的朋友也許發現了程式碼中取得圖片的高度用到了offsetHeight 這個屬性,這個屬性的高度總和等於圖片高度內邊距邊框,正因為此,我們用了padding 而不是margin 來設定圖片與圖片之間的距離。另外除了offsetHeight 屬性,此外還要理解offsetHeightclientHeightoffsetTopscrollTop 等屬性的差異,才能比較好的理解這個項目。 css 程式碼簡單如下:

.waterfall-box {
 float: left;
 width: 200px;
 padding-left: 10px;
 padding-bottom: 10px;
}

scroll、resize 事件監聽的實作

##實作了初始化函數init 以後,下一步就要實作對scroll 捲動事件進行監聽,從而實現當滾到父節點的底部有源源不絕的圖片被載入出來的效果。這時候要考慮一個點,是滾動到什麼位置時觸發載入函數呢?這個因人而異,我的做法是當滿足

父容器高度滾動距離> 最後一張圖片的offsetTop 這個條件,即橙色線條紫色線條> 藍色線條時觸發加載函數,代碼如下:

window.onscroll = function() {
 // ...
 if (scrollPX + bsHeight > imgList[imgList.length - 1].offsetTop) {// 浏览器高度 + 滚动距离 > 最后一张图片的 offsetTop
  const fragment = document.createDocumentFragment()
  for(let i = 0; i < 20; i++) {
   const img = document.createElement(&#39;img&#39;)
   img.setAttribute(&#39;src&#39;, `images/${i+1}.png`)
   img.setAttribute(&#39;class&#39;, &#39;waterfall-box&#39;)
   fragment.appendChild(img)
  }
  $waterfall.appendChild(fragment)
 }
}

因為父節點可能自訂節點,所以提供了對監聽scroll 函數的封裝,程式碼如下:

proto.bind = function () {
  const bindScrollElem = document.getElementById(this.opts.scrollElem)
  util.addEventListener(bindScrollElem || window, &#39;scroll&#39;, scroll.bind(this))
 }
 const util = {
  addEventListener: function (elem, evName, func) {
   elem.addEventListener(evName, func, false)
  },
 }

resize 事件的監聽與scroll 事件監聽大同小異,當觸發了resize 函數,呼叫init 函數進行重置就行。

使用發布-訂閱模式和繼承實現監聽綁定

既然以開發插件為目標,不能僅僅滿足於功能的實現,還要留出相應的操作空間給開發者自行處理。聯想到業務場景中瀑布流中下拉加載的圖片一般都來自Ajax 異步獲取,那麼加載的數據必然不能寫死在庫裡,期望能實現如下調用(此處借鑒了waterfall 的使用方式),

const waterfall = new Waterfall({options})
waterfall.on("load", function () {
 // 此处进行 ajax 同步/异步添加图片
})

觀察呼叫方式,不難聯想到使用發布/訂閱模式來實現它,關於發布/訂閱模式,之前在Node.js 異步異聞錄有介紹它。其核心思想即透過訂閱函數將函數添加到快取中,然後透過發布函數實現異步調用,下面給出其程式碼實作:

function eventEmitter() {
 this.sub = {}
}
eventEmitter.prototype.on = function (eventName, func) { // 订阅函数
 if (!this.sub[eventName]) {
  this.sub[eventName] = []
 }
 this.sub[eventName].push(func) // 添加事件监听器
}
eventEmitter.prototype.emit = function (eventName) { // 发布函数
 const argsList = Array.prototype.slice.call(arguments, 1)
 for (let i = 0, length = this.sub[eventName].length; i < length; i++) {
  this.sub[eventName][i].apply(this, argsList) // 调用事件监听器
 }
}

接著,要讓Waterfall 能使用發布/訂閱模式,只需讓Waterfall 繼承eventEmitter 函數,程式碼實作如下:

function Waterfall(options = {}) {
 eventEmitter.call(this)
 this.init(options) // 这个 this 是 new 的时候,绑上去的
}
Waterfall.prototype = Object.create(eventEmitter.prototype)
Waterfall.prototype.constructor = Waterfall

繼承方式的寫法吸收了基於建構函式繼承和基於原型鏈繼承兩種寫法的優點,以及使用

Object.create 隔離了子類別和父類,關於繼承更多方面的細節,可以另寫一篇文章了,這裡點到為止。

小優化

為了防止 scroll 事件觸發多次載入圖片,可以考慮用函數防手震與節流實作。在基於發布-訂閱模式的基礎上,定義了個isLoading 參數表示是否在加載中,並根據其布爾值決定是否加載,代碼如下:

let isLoading = false
const scroll = function () {
 if (isLoading) return false // 避免一次触发事件多次
 if (scrollPX + bsHeight > imgList[imgList.length - 1].offsetTop) { // 浏览器高度 + 滚动距离 > 最后一张图片的 offsetTop
  isLoading = true
  this.emit(&#39;load&#39;)
 }
}
proto.done = function () {
 this.on(&#39;done&#39;, function () {
  isLoading = false
  ...
 })
 this.emit(&#39;done&#39;)
}

這時候需要在調用的地方加上

waterfall.done, 從而告知當前圖片已經加載完畢,代碼如下:

const waterfall = new Waterfall({})
waterfall.on("load", function () {
 // 异步/同步加载图片
 waterfall.done()
})

上面是我整理給大家的,希望今後會對大家有幫助。

相關文章:

Vue元件和Route的生命週期(詳細教學)

利用SpringMVC解決vue跨域請求

webpack 4.0.0-beta.0版本新功能(詳細教學)

以上是使用JS如何實現瀑布流插件的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
如何通过纯CSS实现瀑布流布局的方法和技巧如何通过纯CSS实现瀑布流布局的方法和技巧Oct 20, 2023 pm 06:01 PM

如何通过纯CSS实现瀑布流布局的方法和技巧瀑布流布局(WaterfallLayout)是一种在网页设计中常见的布局方式,它通过将内容以多列的方式排列,每一列的高度不一致,从而形成像瀑布般的视觉效果。这种布局常常被应用于图片展示、商品展示等需要展示大量内容的情景中,具有良好的用户体验。实现瀑布流布局的方法有很多种,可以使用JavaScript或CSS来完成。

CSS怎么实现瀑布流?两种方式介绍CSS怎么实现瀑布流?两种方式介绍Sep 26, 2021 am 10:58 AM

CSS怎么实现瀑布流?下面本篇文章给大家介绍一下使用CSS实现瀑布流的两种方式,希望对大家有所帮助!

原生js实现append()方法原生js实现append()方法Feb 18, 2024 pm 02:37 PM

原生js实现append()方法,需要具体代码示例在编写JavaScript代码时,经常需要在网页中往指定元素中添加新的内容。常见的操作是通过innerHTML属性来设置元素的HTML内容。然而,使用innerHTML属性有时会导致元素内部的事件监听器、样式等丢失。为了更好地实现添加内容的功能,我们可以自己实现一个append()方法。append()方法可

如何使用HTML和CSS实现瀑布流卡片布局如何使用HTML和CSS实现瀑布流卡片布局Oct 20, 2023 am 11:46 AM

如何使用HTML和CSS实现瀑布流卡片布局在网页开发中,瀑布流卡片布局是一种常见且炫酷的展示方式。瀑布流布局的特点是卡片呈现不规则的形状,高度和位置会根据内容的多少和屏幕大小自动适应,使页面更具吸引力和互动性。本文将介绍如何使用HTML和CSS实现瀑布流卡片布局,并提供具体的代码示例。一、HTML结构首先,我们需要创建HTML结构。在这个例子中,我们将使用一

如何使用Vue实现瀑布流布局特效如何使用Vue实现瀑布流布局特效Sep 19, 2023 am 10:16 AM

如何使用Vue实现瀑布流布局特效瀑布流布局是一种常见的网页布局方式,它可以将内容按照不同的高度自动排列,形成类似瀑布流般的效果。在前端开发中,我们可以使用Vue框架来实现瀑布流布局特效,下面将介绍具体的实现方法,并提供代码示例。引入Vue和Masonry布局库首先,在HTML文件中引入Vue和Masonry布局库的CDN链接,代码如下:&lt;script

CSS布局教程:实现瀑布流式卡片布局的最佳方法CSS布局教程:实现瀑布流式卡片布局的最佳方法Oct 20, 2023 am 10:40 AM

CSS布局教程:实现瀑布流式卡片布局的最佳方法引言:在现代网页设计中,瀑布流式卡片布局是非常流行的一种布局方式。它能够有效地展示大量的内容,并且在不同的屏幕尺寸下都能够自适应,给用户带来良好的浏览体验。本文将介绍实现瀑布流式卡片布局的最佳方法,并提供具体的代码示例。一、实现瀑布流式布局的原理瀑布流式布局的原理是根据不同内容的高度,将卡片按照一定的规则排列在不

如何使用HTML和CSS实现瀑布流网格布局如何使用HTML和CSS实现瀑布流网格布局Oct 16, 2023 am 08:42 AM

如何使用HTML和CSS实现瀑布流网格布局瀑布流网格布局是一种常见的布局方式,可以使网页元素呈现出类似瀑布流般的效果,给用户带来更好的视觉体验。本文将介绍如何使用HTML和CSS实现瀑布流网格布局,并提供具体的代码示例。首先,我们需要准备一些HTML结构和CSS样式。下面是一个基本的HTML结构,包含了几个需要展示的元素:&lt;!DOCTYPEhtml&

如何使用PHP实现微信小程序中的文本瀑布流效果如何使用PHP实现微信小程序中的文本瀑布流效果Jun 01, 2023 pm 10:40 PM

随着移动设备的普及,微信小程序成为了越来越多的企业和个人的选择。然而,在小程序的开发过程中,实现瀑布流效果是一项难度较大的任务。本文将介绍如何使用PHP实现微信小程序中的文本瀑布流效果。一、瀑布流效果的实现方式瀑布流效果是指将不同高度的元素按照顺序排列,使其看上去像瀑布一样流淌的视觉效果。在Web端的瀑布流效果实现中,常用的方式是通过CSS的Column布局

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
2 週前By尊渡假赌尊渡假赌尊渡假赌
倉庫:如何復興隊友
4 週前By尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒險:如何獲得巨型種子
4 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )專業的PHP整合開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境