js|js 实现瀑布流布局
仿照淘宝实现瀑布流
- 实现的效果图如下(以iphone6/7/8以及ipadpro为例):
文章图片
文章图片
- 利用绝对定位进行布局
- 定义gap(上下左右的间距)
- 先计算出列数(columnNum)即网页的可视区域的宽度(clientWidth)/列宽(itemWidth),所以公式如下:
columnNum=clientWidth/itemWidth
- 将第一行每列的高度装进一个数组(
columnHeightArr
),用于高度定位 - 通过循环,
index
时,说明是第一行,同时将元素的高度装入 columnHeightArr
数组其他情况为非第一行 - 找出
columnHeightArr
里面的最小值(minHeight
),以及最小值对应的index
,该列的下面就是下一个元素的位置,然后计算出距离左边,距离右边的距离,然后重置最小值的高度 - 距离左边为:
index*(item.offsetWidth+gap)
- 距离上边边为:
(元素对应的index)*(minHeight+gap)
- 【js|js 实现瀑布流布局】重置
columnHeightArr
数组对应的最小值为columnHeightArr[index]=item.offsetHeigth+gap+columnHeightArr[index]
js示例代码如下:/* 瀑布流 */ class WaterFallFlow { constructor(parentEl, childWidth) { this.parentEl = parentEl; //瀑布流布局对应的父节点 this.childWidth = childWidth; //瀑布流布局对应的每个子节点的宽度 this.gap = 10; //上下左右的间距 /* 网页的可是区域 */ this.clientWidth = 0 this.coulmnNum = 0; //列数(可视区域的宽度/要瀑布流布局元素的宽度) this.columnHeightArr = []; //用于装列的高度 } startWaterFall() { this.columnHeightArr = []//初始化以及窗口改变的时候重置第一列的高度 this.clientWidth = document.documentElement.clientWidth || document.body.clientWidth || window.clientWidth const parentEl = this.parentEl; //瀑布流布局对应的父节点 const childWidth = this.childWidth; //瀑布流布局对应的每个子节点的宽度 document.querySelector(parentEl).style.position = 'relative'//将父元素设置为相对定位 const children = [...document.querySelector(parentEl).children]; if (children.length == 0) throw new Error(`${parentEl}节点下未找到子节点`) children.forEach((item) => { item.style.position = 'absolute'//每一个元素设置为绝对定位 item.style.width = `${childWidth}px` }) const itemWidth = children[0].offsetWidth; this.coulmnNum = parseInt(this.clientWidth / itemWidth)//向下取整 /* 第一行的布局 */ children.forEach((item, index) => { /* 第一行 */ if (index < this.coulmnNum) { item.style.top = 0; item.style.left = `${index * (item.offsetWidth + this.gap)}px`; this.columnHeightArr.push(item.offsetHeight + item.offsetTop) } else { // 不是第一行 const minHeight = Math.min(...this.columnHeightArr)//找到列中高度最小的哪一个元素,依次排在最小元素的后面 const minIndex = this.columnHeightArr.indexOf(minHeight)//找到最小高度的下标是哪一个 item.style.top = `${minHeight + this.gap}px` item.style.left = `${minIndex * (item.offsetWidth + this.gap)}px` this.columnHeightArr[minIndex] = minHeight + item.offsetHeight + this.gap//重置最小高度 }}); } init() { this.startWaterFall(); window.addEventListener('resize', () => { setTimeout(() => { this.startWaterFall() }, 300) }) } } window.onload = function () { const waterfallflow = new WaterFallFlow('ul', 182.5); waterfallflow.init() }
htnl代码如下:Document - 锐客网 * { padding: 0; margin: 0; list-style: none; }img {width: 100%; }body { background-color: #ccc; }-
文章图片
-
文章图片
-
文章图片
-
文章图片
-
文章图片
-
文章图片
-
文章图片
-
文章图片
-
文章图片
-
文章图片
-
文章图片
-
文章图片
-
推荐阅读
- live|live to inspire 一个普通上班族的流水账0723
- 关于QueryWrapper|关于QueryWrapper,实现MybatisPlus多表关联查询方式
- MybatisPlus使用queryWrapper如何实现复杂查询
- python学习之|python学习之 实现QQ自动发送消息
- 流转
- Guava|Guava RateLimiter与限流算法
- 孩子不是实现父母欲望的工具——林哈夫
- opencv|opencv C++模板匹配的简单实现
- Node.js中readline模块实现终端输入
- java中如何实现重建二叉树