用Masonry和jQuery.lazyload插件实现网页瀑布流布局
瀑布流布局
我们常能在网上看到很多瀑布流布局的页面,尤其是很多图片网站,例如百度图片。这种最典型的瀑布流布局,每个元素的宽度是固定的,但图片长度各不相同,于是通过下图这种样子竖着排列了下来,达到了最大的页面空间利用率。
因为对前端开发不了解,一开始为了找到这种布局叫什么名字也是花了我好久时间o(╯□╰)o
瀑布流布局不局限于等宽布局,例如下面这种形式也可以,来自Masonry
官网截图。
Masonry官网 http://masonry.desandro.com/
瀑布流布局作为一种响应式布局,网页元素会自动根据页面宽度进行调整。按住Ctrl键并滚动鼠标滚轮,对网页进行缩放,我们就能看到网页元素之间的排版位置会不断变化,如上图所示。
瀑布流布局实现
对于上面的等宽瀑布流布局,看起来其实似乎很容易实现。但是由于HTML文档流的原理,网页元素的排列是先从左往右的,超出了才会换行,而不能直接控制成从上往下,因此直接利用HTML和CSS不太好处理,完美的瀑布流布局需要借助javascript
或jQuery
插件实现。这里说的不是很清楚,可以看下文中详细的图文解释。瀑布流布局的实现有很多种方式,这篇文章写得也很详细。
Masonry插件
Masonry
插件是用的比较多的瀑布流布局插件。下面两张图展示了插件使用前后的网页布局,很容易看出其作用。
没使用Masonry
时,网页元素按照HTML文档流排列,先从左到右,超出再换行,中间会有很多空隙,如下图所示。
使用了Masonry
之后,每个元素位置会自动被调整,空隙少了很多,如图所示。
Masonry的基本使用
Masonry插件有两个版本,一个用的原生javascript
,一个用的jQuery
,如果你的网页刚好用到了其他jQuery
库,建议用后者,因为代码量会少很多。两个版本的插件都可以在附件中的Demo里找到。
Masonry官方GitHub链接(JavaScript版本,含多个Demo示例)
https://github.com/desandro/masonryjQuery Masonry也可在此下载(不知道这个站点算不算官网,感觉有点乱)
http://www.fishspotr.com
Masonry
插件的使用很简单,但是官方GitHub给出的Demo里面代码太长不容易看明白,所以我提供了一个简化的Demo,使用了最常用的几个参数。具体的参数可以参考官方的Demo。
调用Masonry
的代码可以写在<script>
标签中,也可以直接写在HTML标签的data-masonry-options
属性中,我提供的javascript
版本的代码就写在了data-masonry-options
属性中。
另外网上的很多文档都有错,都是套用官方的文档,把两个版本混为一谈。例如jQuery
和javascript
版本有一些参数是不一样的,例如javascript
版本中的gutter
参数在jQuery
版本里面是gutterWidth
,这个可以从源码中看到(也可能是版本升级改了参数名)。
Lazyload延迟加载图片
网页中常用Lazyload
插件进行图片的延迟加载,用户滚动页面,要浏览到图片所在的位置时,才开始加载图片,否则不加载。一方面能加快网页刚刚载入时的速度,因为省去了很多图片的加载;另一方面能节省流量,因为只需要加载用户滚动到的地方的图片,如果用户中途离开页面,部分图片就不会被加载了。
这里顺便提一下Lazyload
,使用这个插件时,IMG
标签需要写成这种形式:<img
src="loading.gif" data-original="img.jpg" />
,src中是一个体积较小的占位图片,而真实图片地址写在后面的data-original
属性中。网上有人说的Lazyload不能用、有bug,就是因为这个地方没有写好。
另外,为了防止有些用户浏览器没开javascript
,上面这样写会导致图片不显示,因此稳妥起见还有必要添加一个<noscript>
标签,在里面写上正常的图片标签,没有javascript
时这段代码就会生效,如下所示。
<img src="loading.gif" data-original="img.jpg" />
<noscript><img src="img.jpg" /></noscript>
Masonry与Lazyload插件冲突
同时使用Masonry
和Lazyload
插件,会造成冲突。因为Masonry
需要获取每个元素的尺寸从而计算出元素的位置,但是在网页滚动过程中,由于Lazyload
动态加载图片会导致元素尺寸变化,而此时Masonry
并不会重新计算,于是排列就混乱了,如图所示。
解决思路是每次Lazyload
加载好一张图片就让Masonry
重新排版。但找了很久也没找到Lazyload
的回调参数……
先后考虑或尝试了滚动网页事件、IMG加载完成事件、DIV尺寸变化事件、延时等来触发Masonry
,还考虑过提前在后台计算好图片标签的尺寸、把Lazyload
换成其他插件,但是怎么做都感觉不好,效率低或是很麻烦等问题。
最后感觉最好的办法还是干脆自己改一下Lazyload
的源码好了。但在看源码的时候意外发现了Lazyload
其实有回调函数,也就是load
参数。
网上大量文章都是复制粘贴来的一摸一样的几句话,甚至连官方也都没有说这个参数……莫非是我的打开方式不对?
我眼里的Lazyload官网 http://www.appelsiini.net/projects/lazyload
最后的解决方案就很清楚了,关键代码大致如下。示例Demo也在附件中。
<script>
$(function() {
f_masonry();
$("img").lazyload({
effect:"fadeIn",
failurelimit:40,
load:f_masonry,
});
});
function f_masonry() {
$(‘.masonry‘).masonry({
gutterWidth: 20,
itemSelector: ‘.item‘,
isAnimated: true,
});
}
</script>
最后再吐槽一下网上各种不负责任复制粘贴来的文章,参考价值略低,甚至各种错误(自己动手丰衣足食)。
附件:Demo下载地址
https://github.com/jzj1993/masonry-lazyload-demos