搜索
首页web前端H5教程JS代码实现瀑布流插件

JS代码实现瀑布流插件

Feb 07, 2018 am 09:25 AM
javascript插件

瀑布流布局中的图片有一个核心特点—等宽不定等高,瀑布流布局在国内网网站都有一定规模的使用,比如pinterest、花瓣网等等。本文主要和大家详细分析了一个原生JS实现瀑布流插件以及代码相关讲解,对此有兴趣的读者们参考学习下吧,希望能帮助到大家。

基础功能实现

首先我们定义好一个有 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()
})

相关推荐:

纯原生JS的瀑布流插件Macy.js使用详解

Jquery瀑布流插件使用介绍_jquery

jQuery瀑布流插件Wookmark使用实例_jquery

以上是JS代码实现瀑布流插件的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
H5:如何增强网络上的用户体验H5:如何增强网络上的用户体验Apr 19, 2025 am 12:08 AM

H5通过多媒体支持、离线存储和性能优化提升网页用户体验。1)多媒体支持:H5的和元素简化开发,提升用户体验。2)离线存储:WebStorage和IndexedDB允许离线使用,提升体验。3)性能优化:WebWorkers和元素优化性能,减少带宽消耗。

解构H5代码:标签,元素和属性解构H5代码:标签,元素和属性Apr 18, 2025 am 12:06 AM

HTML5代码由标签、元素和属性组成:1.标签定义内容类型,用尖括号包围,如。2.元素由开始标签、内容和结束标签组成,如内容。3.属性在开始标签中定义键值对,增强功能,如。这些是构建网页结构的基本单位。

了解H5代码:HTML5的基本原理了解H5代码:HTML5的基本原理Apr 17, 2025 am 12:08 AM

HTML5是构建现代网页的关键技术,提供了许多新元素和功能。1.HTML5引入了语义化元素如、、等,增强了网页结构和SEO。2.支持多媒体元素和,无需插件即可嵌入媒体。3.表单增强了新输入类型和验证属性,简化了验证过程。4.提供了离线和本地存储功能,提升了网页性能和用户体验。

H5代码:Web开发人员的最佳实践H5代码:Web开发人员的最佳实践Apr 16, 2025 am 12:14 AM

H5代码的最佳实践包括:1.使用正确的DOCTYPE声明和字符编码;2.采用语义化标签;3.减少HTTP请求;4.使用异步加载;5.优化图像。这些实践能提升网页的效率、可维护性和用户体验。

H5:网络标准和技术的发展H5:网络标准和技术的发展Apr 15, 2025 am 12:12 AM

Web标准和技术从HTML4、CSS2和简单的JavaScript演变至今,经历了显着的发展。 1)HTML5引入了Canvas、WebStorage等API,增强了Web应用的复杂性和互动性。 2)CSS3增加了动画和过渡功能,使页面效果更加丰富。 3)JavaScript通过Node.js和ES6的现代化语法,如箭头函数和类,提升了开发效率和代码可读性,这些变化推动了Web应用的性能优化和最佳实践的发展。

H5是HTML5的速记吗?探索细节H5是HTML5的速记吗?探索细节Apr 14, 2025 am 12:05 AM

H5不仅仅是HTML5的简称,它代表了一个更广泛的现代网页开发技术生态:1.H5包括HTML5、CSS3、JavaScript及相关API和技术;2.它提供更丰富、互动、流畅的用户体验,能在多设备上无缝运行;3.使用H5技术栈可以创建响应式网页和复杂交互功能。

H5和HTML5:网络开发中常用的术语H5和HTML5:网络开发中常用的术语Apr 13, 2025 am 12:01 AM

H5与HTML5指的是同一个东西,即HTML5。HTML5是HTML的第五个版本,带来了语义化标签、多媒体支持、画布与图形、离线存储与本地存储等新功能,提升了网页的表现力和交互性。

H5指的是什么?探索上下文H5指的是什么?探索上下文Apr 12, 2025 am 12:03 AM

H5referstoHTML5,apivotaltechnologyinwebdevelopment.1)HTML5introducesnewelementsandAPIsforrich,dynamicwebapplications.2)Itsupportsmultimediawithoutplugins,enhancinguserexperienceacrossdevices.3)SemanticelementsimprovecontentstructureandSEO.4)H5'srespo

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无尽的。

热工具

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

功能强大的PHP集成开发环境

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

EditPlus 中文破解版

EditPlus 中文破解版

体积小,语法高亮,不支持代码提示功能

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具