题外话:最近新建了一个专栏,里面专门用来发布一些前端学习中的一些小demo,但是以我一己之力想要将专栏丰富起来还是有点困难,所以,如果有想成为专栏作者或者想要投稿的小伙伴私我。
关注公众平台:【资料分享大师】
其他文章参考:
天之蓝源:三分钟在GitHub上搭建个人博客zhuanlan.zhihu.com
天之蓝源:零基础Hexo+Github搭建静态个人博客zhuanlan.zhihu.com
天之蓝源:原生js实现点击按钮复制文本内容zhuanlan.zhihu.com
天之蓝源:九种跨域方式实现原理zhuanlan.zhihu.com
天之蓝源:前端面试考点多?看这些文章就够了(转载)zhuanlan.zhihu.com
天之蓝源:干货!值得收藏的前端学习网站zhuanlan.zhihu.com
天之蓝源:原生JS实现一个日期选择器(DatePicker)组件zhuanlan.zhihu.com
天之蓝源:原生js一步一步实现《别踩白块儿》小游戏zhuanlan.zhihu.com
天之蓝源:原生js利用localstorage实现简易TODO list应用zhuanlan.zhihu.com
天之蓝源:原生js实现瀑布流效果zhuanlan.zhihu.com
天之蓝源:原生js实现图片懒加载(lazyLoad)zhuanlan.zhihu.com
天之蓝源:原生js实现简单路由切换zhuanlan.zhihu.com
进入正题-------->
前言:知识是学不完的,可是我们为什么还是要不停的去学习呢。原因很简单,因为我们要产生更多的知识,让更多的人学不完!前端技术也是在不停的革新,我们要做那个让别人有学不完的知识的人!
我们要实现的效果:
原生js实现瀑布流式布局https://www.zhihu.com/video/1072171787252445184
一.什么是瀑布流
瀑布流,又被称作为瀑布流式布局,是一种比较流行的网站页面布局方式,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部。这种布局方式常见于一些图片为主的网站,就比如说一些常见的网站:
瀑布流式布局瀑布流式布局由上面的两张图我们可以很容易的明白什么是瀑布流式布局,可以看出,每个图片的高度是不一样的但是它们的宽度是统一的,每个图片之间的间隙也是均匀的。
总结瀑布流式布局的特征如下:
- 内容框宽度固定,高度不固定。
- 内容框从左到右排列,一行排满后,其余内容框就会按顺序排在短的一列后。
二.为什么要用瀑布流布局
1、吸引用户
当用户在浏览瀑布流式布局的时候(这里抛开懒加载),用户会产生一种错觉,就是信息是不停的在更新的,这会激发用户的好奇心,使用户不停的往下滑动。
2.良好视觉体验
采用瀑布流布局的方式可以打破常规网站布局排版,给用户眼前一亮的新鲜感,用户在浏览内容时会感到很有新鲜感,带来良好的视觉体验。
3.更好的适应移动端
由于移动设备屏幕比电脑小,一个屏幕显示的内容不会非常多,因此可能要经常翻页。而在建网站时使用瀑布流布局,用户则只需要进行滚动就能够不断浏览内容。(这一点和懒加载有一点像)
三.实现原理
我们已经总结出了瀑布流式布局的两大特征:
- 内容框宽度固定,高度不固定。
- 内容框从左到右排列,一行排满后,其余内容框就会按顺序排在短的一列后。
那么我们根据这两大特征就不难想出它的实现原理:
首先我们先通过计算一行能够容纳几列元素(因为我们需要在不同的设备上浏览),然后在通过计算比较找出这一列元素中高度之和最小一列,然后将下一行的第一个元素添加至高度之和最小的这一列的下面,然后继续计算所有列中高度之和最小的那一列,然后继续将新元素添加至高度之和最小的那一列后面,直至所有元素添加完毕。
可能饶了这么一大段话还是有小伙伴不明白,我们还是看图说话,这才是最容易理解的;
(1)首先我们放上一行
,它们高度不同,宽度相同:
高度不同,宽度相同(2)找出所有元素高度之和的最小的那列在那一列的下面添加新的元素
在第五列添加新元素(3)然后继续计算,获取高度之和最小的那一列,在那一列继续添加新元素
继续在高度之和最小那一列添加新元素看了这几张图是不是明确了很多,就是这样不停的计算,不停的添加新元素,直至所有元素添加完成。但是我们都知道一些元素是块级元素,一个元素占据一行,这里就会有小伙伴想到了,我们可以利用浮动啊,具体是不是,我们继续实验。
现在明白了瀑布流是布局是怎么实现的了,那么就来写具体的代码来实现一下吧!
四.实现步骤及方法
1.通过浮动的方式进行布局
首先我们添加一些
元素,并设置为
左浮动,分别给这些
元素给予不同的背景方便我们观察,注意,这些元素的宽度是一样的,只是高度不一样。
通过左浮动设置的布局这就是通过左浮动设置的布局样式,我们可以看到在第二行的时候,第七个盒子浮动是根据第三个盒子来进行定位的。第三行的时候第七个盒子又挡住了第十个盒子的去路,所以这样我们是没法完成布局的。
2.通过定位的方式进行布局
前面我们已经知道了浮动布局不能满足我们的需求,所以我们寻求另外一种布局方式,那就是通过定位,给每个盒子设置定位属性后,我们就可以通过动态的设置相应的top,left值来让盒子规规矩矩的为我们排列。
(一)给所有盒子的父元素加上相对定位属性,给所有盒子加上绝对定位属性:
position:relative;
position:absolute;
(二)定位之后我们得到的界面是这样的:
设置定位后的元素(三)如何判断一行有多少列:
因为我们的界面宽度是变化的,所以列数也需要跟着变化,动态设置列数的原理大致如下:
1.获取到页面的宽度
2.获取到每个盒子的宽度
3.需要显示的列数 = 页面宽度/盒子宽度
注意:一般盒子之间都有一个间隙,所以我们的公式变成如下:
显示的列数(column) = 页面宽度(pageWidth)/(盒子宽度(itemWidth)+间隙(gap))
(四)排列第一行
- 我们有很多盒子&#xff0c;太多了我们就不好管理&#xff0c;所以我们把所有盒子装进一个数组arr里面&#xff0c;下标从0开始&#xff0c;用i来代表盒子。那么我们如何知道这个盒子是不是应该排列在第一行呢。其实很简单&#xff0c;想一下&#xff0c;我们这么多盒子&#xff0c;全部都要动态布局&#xff0c;动态的设置他的left、top值&#xff0c;那么for循环肯定是避免不了的&#xff0c;当i&#xff08;所有盒子的索引&#xff09;的时候&#xff0c;盒子应该在第一行。比如说我们一行有5个盒子&#xff0c;那么第五个盒子的索引就是4&#xff0c;由于4<5&#xff0c;所以在第一行&#xff0c;如果索引为6&#xff0c;由于6>5&#xff0c;所以在第二行。代码基本就是这个样子
- 知道了盒子在第1行之后&#xff0c;我们只需要动态的设置盒子的left值就能排列好了。
- 怎么动态计算每个盒子的left值呢&#xff1a;left&#61;i*(itemWidth&#43;gap)&#xff0c;比如说我们排列第二个盒子&#xff0c;它的索引值i就是1&#xff0c;i*(itemWidth&#43;gap)刚好就是第一个盒子和间隙的宽度和&#xff0c;所以距离left值也刚刚好。
说了这么多&#xff0c;画个图理解一下&#xff1a;
获取left值&#xff08;五&#xff09;获取所有列的高度和
- 在第一行排列好后&#xff0c;我们就需要排列第二行了&#xff0c;但是第二行我们需要用到top值了&#xff0c;前面原理的时候说了&#xff0c;我们就是根据每一列的最小高度和来进行排列&#xff0c;所以这里我们需要计算出第一行所有列的高度和并保存。
- 我们定义一个数组arr来保存高度。
我们需要在页面一进入的时候就获取高度&#xff0c;也就是写在onload里面&#xff0c;因为图片的加载特征是&#xff1a;等页面都加载完之后才去请求加载&#xff0c;所以不写在入口函数里可能会出现高度获取不到的情况。
&#xff08;六&#xff09;排列第二行
- 获取到刚刚数组中&#xff0c;高度最小的那一列&#xff0c;将第
2
行的第1
个盒子放置在它的下方&#xff1b; - 此时的
left
值就是高度最小列的offsetLeft
&#xff1b;top
值就是第1
行高度最小列的高度(为了布局美观可以加上上下间隙gap
)。 - 记录下高度最小列的索引
index
&#xff0c;后面计算会用到&#xff1b; - 设置完成之后&#xff0c;会发现后面所有的盒子都叠在这个高度最小列的下面&#xff0c;原因就是此时的最小列高度没有改变&#xff0c;应该加上下面盒子 的高度&#xff0c;得出一个新高度。我们需要在最小列后面加了一个盒子之后重新计算所有列的最小高度的列。
看图说话&#xff1a;我们看到第六个盒子下面下面全是其他盒子。
将第二行第一个盒子排列在最小高度和的那一列下面&#xff08;七&#xff09;重新获取最小高度列的高度
- 排了第二行的第一个盒子之后&#xff0c;最小高度列已经发生了变化&#xff0c;我们需要重新计算一下
- 当前高度最小列的高度 &#61; 当前高度最小列的高度 &#43; 间隙 &#43; 下面图片盒子的高度
看图说话&#xff1a;现在知道我们保留index做什么了吧。
&#xff08;八&#xff09;设置为响应式
- 将整个设置样式的部分封装成一个函数&#xff0c;在onload里面注册一个resize事件&#xff0c;只要页面一发生改变&#xff0c;就触发样式部分的代码。
实时改变pageWidth的宽度&#xff0c;这样瀑布流就会是一个响应式的效果了
&#xff08;九&#xff09;添加懒加载效果
懒加载的实现原理可以参考我的上一篇文章&#xff0c;说得很清楚详细。大致原理用一张图来描述&#xff1a;
懒加载实现原理图&#xff08;十&#xff09;所有代码(没有包含懒加载代码)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
注意&#xff1a;如果要加入懒加载效果的话&#xff0c;可以参考我的之前一篇文章&#xff0c;讲的较为详细&#xff0c;由于这里没有在
里面添加图片&#xff0c;所以&#xff0c;不能实现懒加载效果。这里只设置了div&#xff0c;并且分别给div设置的高度&#xff0c;稍加繁琐。如果有合适的图片资源&#xff0c;可以不用设置。
五.总结
到这里&#xff0c;我们的瀑布流式布局布局也算讲完了&#xff0c;讲得过程比较啰嗦&#xff0c;也是为了让更多的人能够轻松理解。从整个实现过程来看&#xff0c;我们主要有两个重点&#xff1a;
- 瀑布流式布局是利用定位来实现的&#xff0c;动态的改变元素的top和left值。
- 获取最小高度和的列并保存它的索引&#xff0c;以便让下一行的元素知道该放在哪里。
六.源码
更多源码请移步GitHub&#xff1a;
Hacker233/Javascriptgithub.com
推荐阅读
-
1、创建高级对象使用构造函数来创建对象构造函数是一个函数,调用它来例示并初始化特殊类型的对象。可以使用new关键字来调用一个构造函数。下面给出了使用构造函数的新示例。 ...
[详细]
蜡笔小新 2024-09-27 16:12:55
-
这篇文章主要介绍了PyQt如何创建自定义QWidget,帮助大家更好的理解和学习使用pyqt,感 ...
[详细]
蜡笔小新 2024-09-28 17:51:22
-
-
Adapter相当于C(Controller,控制器),listView相当于V(View,视图)用于显示数据为ListView提供数据的List,数组或数据库相当于MVC模式中的 ...
[详细]
蜡笔小新 2024-09-28 15:24:54
-
本篇内容主要讲解“JavaScript在网页设计中的嵌入应用方法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小 ...
[详细]
蜡笔小新 2024-09-28 12:59:54
-
首页#father{border:0pxso ...
[详细]
蜡笔小新 2024-09-27 17:56:58
-
作者|相学长原文|https:github.comwuomzfxblogblobmasterthis.md日常开发中,我们经常用到this。例如用Jquery绑定事件 ...
[详细]
蜡笔小新 2024-09-27 17:44:48
-
这两天做了一个小项目,里面有个下载进度的进度条需要制作。先看呈现的效果:点击进度,然后依次递增,直到递增到百分之百。现在把这部分代码分享下来。<!DOCTYPEhtml><html ...
[详细]
蜡笔小新 2024-09-27 14:38:43
-
篇首语:本文由编程笔记#小编为大家整理,主要介绍了js正则表达式属性及方法的使用相关的知识,希望对你有一定的参考价值。正则表达式直接量 ...
[详细]
蜡笔小新 2024-09-27 14:19:50
-
1、对于List而言,要不然就使用迭代器,要不然就从后往前删除,从前往后删除会出现角标越界。因为我List有两个remove方法,一个是int作为形参(删除指定位置的元素),一个是 ...
[详细]
蜡笔小新 2024-09-27 12:42:00
-
(一)前言:二次开发编辑器neditor(基于百度编辑器ueditor):界面相对于ueditor会更美观.(二)问题描述:最近在公司项目中遇到一个比较奇葩的问题。neidito ...
[详细]
蜡笔小新 2024-09-27 10:58:09
-
下载器,就是一种网络工具,从网络中接收自己想要的数据。下载器是一个网络客户端。它的下载流程无非就是客户端连接服务器端,然后发送资源下载请求 ...
[详细]
蜡笔小新 2024-09-28 11:59:38
-
pdf怎么把html变成pdf1 用AdobeAcroat8.1.2,打开网页后,页面右键菜单中会出现一个“转换为AobePDF的选项,点击就可以转换。 安装AdobeAcroba ...
[详细]
蜡笔小新 2024-09-28 11:07:23
-
经常在各大论坛或新闻板块详情页面下边看到评论功能,当然不单单是直接发表评论内容那么简单,可以对别人的评论进行回复,别人又可以对你的回复再次 ...
[详细]
蜡笔小新 2024-09-27 16:56:46
-
上一篇Lightning内容描述的是LDS,通过LDS可以很方便的实例化一个对象的数据信息。当我们通过列表展示数据需要编辑时,我们常使用两种方式去处理编辑页面:PopUpWindo ...
[详细]
蜡笔小新 2024-09-27 10:39:03
-
自定义窗口实现同时按照计数和时间(processing-time)触发计算 TriggersA Trigger determineswhenawindow(asformedbyth ...
[详细]
蜡笔小新 2024-09-27 10:30:04
-