javascript瀑布流效果
javascript瀑布流效果
其实javascript瀑布流 前几年都已经很流行了(特别是美丽说,蘑菇街),最近看到网上有人问这个瀑布流效果,所以自己有空的时候就研究了下,其实也是研究别人的代码,研究了下别人写的思路,所以有了一个自己的版本代码。下面来讲讲瀑布流的思路吧!
思路:1.先计算当前屏幕或者当前容器最多能容纳几列瀑布,其计算方法为 maxCol = "Math.floor(屏幕可见区域宽度或者容器可视区宽度 / (格子宽度+间距))";
2. 如果当前的容器没有定宽度话,可以设置容器的宽度为:width = 列数* (格子宽度+间距) – 间距. 因为 当容器的宽度计算出来之后再显示,否则会造成页面宽度的抖动,影响体验。计算方法可以理解如下:

上面列数为 6列 ,5个间距,因为最右边间距不算的,所以容器的计算方法为:width = 列数 * (格子宽度+间距) - 间距。
3. 排序: 目前支持2种插入方式: 1. 计算出每列最短的高度,依次插入。2. 每列是按顺序插入进去。
下面还是看看JSFiddler效果吧!
组件配置项如下:
| container |
'', 瀑布流容器 必填项 |
| columnWidth | '204', 列宽度 必填 |
| columnClassName | 'columnCls', // 列类名 必填 |
| columnSpace | 10, // 列间距 |
| cellCls | '.cell', // 每一列单元格class类名 |
| isLoadTarget | 'img', // 要加载目标选择器 默认为img |
| isAutoLoadHeight | true, // 是否需要自动计算图片的高度 |
| fadeIn | true, // 是否渐显加载 默认为true |
| speed | 500, // 渐显速率 默认为500(毫秒) |
| type | 1, // 插入方式 1为插入最短那列,2 为按顺序插入 |
| diff | 100 // 滚动时, 当最小高度的列超过在屏幕高度+已滚动高度+diff时, 会去加载更多数据 |
代码分析如下:
1. 初始化方法:_init(); 1. 创建列,2. 渲染页面内容。3.处理窗口滚动及缩小窗口事件。如下图所示:






下面是所有的JS代码如下:
/**
* JS瀑布流布局
* @ver 1.0
* @param {options,callback} 对象配置项 回调
**/ function WaterFall(options,callback) {
var self = this;
self.options = $.extend({},defaults,options || {});
this.cache = {
$columns : 0, // 所有的列
loadIndex : 0 // 加载的次数
};
self.callback = callback;
this._init();
}
$.extend(WaterFall.prototype,{ /*
* 代码初始化 {创建列操作 对已存在的元素排序 窗口缩放或滚动事件}
* @method _init {private}
*/
_init: function(){
var self = this,
cache = self.cache;
var cfg = self.options;
if(cfg.container == '') {return;}
cache.$columns = self._createColumn(); //重排已存在元素时强制不渐显
self.render($(cfg.container).find(cfg.cellCls),false); var scrollTime,
resizeTime; $(window).unbind('scroll').bind('scroll',function(){
scrollTime && clearTimeout(scrollTime);
scrollTime = setTimeout(function(){
self._onScroll();
},100);
}); $(window).unbind('resize').bind('resize',function(){
resizeTime && clearTimeout(resizeTime);
resizeTime = setTimeout(function(){
self._onResize();
},100);
});
},
/*
* 创建列
* @method _createColumn {private}
*/
_createColumn: function(){
var self = this,
cfg = self.options;
var columnLen = self._calculateColumns();
var html = "";
for(var i = 0; i < columnLen; i++) {
html+= '<div class="'+cfg.columnClassName+'" style="width:'+cfg.columnWidth+'px;display:inline-block;vertical-align:top;*display:inline;zoom:1;margin-left:'+cfg.columnSpace/2+'px;margin-right:'+cfg.columnSpace/2+'px;overflow:hidden"></div>'
}
$(cfg.container).prepend(html);
return $('.'+cfg.columnClassName,cfg.container);//列集合
},
/*
* 共有多少列
* 计算方法: maxCol = Math.floor(屏幕可见区域的宽度或者父容器的宽度/(格子宽度+间距));
* @method _calculateColumns {private}
*/
_calculateColumns: function(){
var self = this,
cfg = self.options;
var num = Math.floor($(cfg.container).outerWidth()/(cfg.columnWidth *1 + cfg.columnSpace*1));
if(num < 1){num = 1;}
return num;
},
/*
* 渲染内容
* @param {elements flag} 所有.cell类元素 boolean
*/
render: function(elements,flag){
var self = this,
cfg = self.options,
cache = self.cache; if($(elements).length <= 0) {return;}
$(elements).each(function(index,$this){
if(!cfg.isAutoLoadHeight) { //如果给出了图片高度 不需要自动计算高度
if(cfg.type == 1) {
self._byShortInsert($(this),cfg.fadeIn && flag);//插入最短那列
}else if(cfg.type == 2){
self._byOrderInsert($(this),cfg.fadeIn && flag);// 按顺序插入
}
}else {
self._renderHTML($(this),flag,index);
}
});
},
_renderHTML: function(elem,flag,index){
var self = this,
cfg = self.options;
if($(elem)[0].nodeName.toLowerCase()=='img'|| $(elem).find(cfg.isLoadTarget).length > 0) {
var image = new Image();
var src = $(elem)[0].nodeName.toLowerCase()=='img' ? $(elem).attr('src'):$(elem).find(cfg.isLoadTarget).attr('src'); //图片加载后才能自动计算出尺寸 除IE以外的浏览器
image.onload = function(){
image.onreadystatechange=null;
if(cfg.type == 1) {
self._byShortInsert(elem,cfg.fadeIn && flag);//插入最短那列
}else if(cfg.type == 2){
self._byOrderInsert(elem,cfg.fadeIn && flag,index);// 按顺序插入
}
image = null;
};
// 针对IE私有 onreadystatechange
image.onreadystatechange = function(){
if(image.readyState == "complete"){
image.onload=null;
if(cfg.type==1){
self._byShortInsert(elem,cfg.fadeIn && flag);//插入最短那列
}else if(cfg.type == 2){
self._byOrderInsert(elem,cfg.fadeIn && flag);// 按顺序插入
}
image=null;
}
}
image.src=src;
}else {
if(cfg.type == 1) {
self._byShortInsert(elem,cfg.fadeIn && flag);//插入最短那列
}else if(cfg.type == 2){
self._byOrderInsert(elem,cfg.fadeIn && flag,index);// 按顺序插入
}
}
},
/*
* 按最短的那列插入
* @method _byShortInsert
* @param {elem flag}
*/
_byShortInsert: function(elem,flag){
var self = this,
cfg = self.options,
cache = self.cache; var $columns = cache.$columns;
if(flag) { //渐显
var calculateLowest = self._calculateLowest();
$(elem).css('opacity',0).appendTo($columns.eq(calculateLowest)).fadeTo(cfg.speed,1);
}else {
//不渐显
var calculateLowest = self._calculateLowest();
$(elem).appendTo($columns.eq(calculateLowest));
}
},
/*
* 计算最短的那列的索引
* @method _calculateLowest {private}
* @return 返回列最短的索引 index
*/
_calculateLowest: function(){
var self = this,
cache = self.cache;
var $columns = cache.$columns,
index = 0;
// 获取第一列的高度 循环 依次对比 然后返回最小的高度
var firstHeight = $columns.eq(0).outerHeight();
for(var i = 0; i < $columns.length; i++){
var curHeight = $($columns[i]).outerHeight();
if(curHeight < firstHeight) {
firstHeight = curHeight;
index = i;
}
}
return index;
},
/*
* 按顺序插入
* @method _byOrderInsert {private}
*/
_byOrderInsert: function(elem,flag,index){
var self = this,
cfg = self.options;
var columnLen = self._calculateColumns(),
$columns = cache.$columns;
if(flag) { //渐显
$(elem).css('opacity',0).appendTo($columns.eq(index % columnLen)).fadeTo(cfg.speed,1);
}else { //不渐显
$(elem).appendTo($columns.eq(index % columnLen));
}
},
/*
* 滚动到底部时 再进行加载
*/
_onScroll: function(){
var self = this,
cfg = self.options,
cache = self.cache;
var lowestIndex = self._calculateLowest(),
$lowest_column = cache.$columns.eq(lowestIndex); //最短列底部距离浏览器窗口顶部的距离
var colHeight = $lowest_column.offset().top + $lowest_column.outerHeight(); // 当最小高度的列超过在屏幕高度+已滚动高度+diff时, 会去加载更多数据
if(cfg.diff + $(window).scrollTop() + $(window).outerHeight() >= colHeight) {
cache.loadIndex++;
if(self.callback && $.isFunction(self.callback)){
self.callback(cache.loadIndex);
var curHtml = self.callback(cache.loadIndex);
self.render(curHtml,true);
}
}
},
/*
* 窗口缩放时候 重新排序
*/
_onResize: function(){
var self = this,
cfg = self.options,
cache = self.cache;
var num = self._calculateColumns(); // 如果列数没有变 返回
if(num == cache.$columns.length) {
return;
}
var $cells=$(cfg.container).find(cfg.cellCls);
cache.$columns.remove();
cache.$columns = self._createColumn();
self.render($cells,false);
}
});
var defaults = {
container : '', // 需要加载的容器 (必填)
columnWidth : '204', // 列宽
columnClassName : 'columnCls', // 列类名
columnSpace : 10, // 列间距
cellCls : '.cell', // 每一列单元格class类名
isLoadTarget : 'img', // 要加载目标选择器 默认为img
isAutoLoadHeight : true, // 是否需要自动计算图片的高度
fadeIn : true, // 是否渐显加载 默认为true
speed : 500, // 渐显速率 默认为500(毫秒)
type : 1, // 插入方式 1为插入最短那列,2 为按顺序插入
diff : 100 // 滚动时, 当最小高度的列超过在屏幕高度+已滚动高度+diff时, 会去加载更多数据.
};
javascript瀑布流效果的更多相关文章
- 利用JS实现简单的瀑布流效果
哈哈, 我又来啦, 在这一段时间里, 我简单的学习了一下javascript(JS), 虽然不是很懂啦, 但是我也简单的尝试着做了点小东西, 就比如现在流行的瀑布流效果, 经过我的努力终于成功的完成了 ...
- css基础之 图片瀑布流布局:用CSS+DIV等宽格子堆砌瀑布流效果 (一)
<!doctype html> <html> <head> <meta charset="UTF-8"/> <title> ...
- 【前端】用jQuery实现瀑布流效果
jQuery实现瀑布流效果 何为瀑布流: 瀑布流,又称瀑布流式布局.是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部.最早 ...
- web页面和小程序页面实现瀑布流效果
小程序实现瀑布流效果,和web页面差不多,都要经过以下步骤: 1).加载图片,获取图片的宽高度: 2).根据页面需要显示几列计算每列的宽度: 3).根据图片真实宽度和每列的宽度比,计算出图片需要显示的 ...
- jQuery淡入淡出瀑布流效果
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- RecylerView完美实现瀑布流效果
RecylerView包含三种布局管理器,分别是LinearLayoutManager,GridLayoutManager,StaggeredGridLayoutManager,对应实现单行列表,多行 ...
- 使用JS实现图片展示瀑布流效果
不知大家有没有发现,一般的图片展示网站都会使用瀑布流效果,所谓的瀑布流 就是网站内的图片不会一下子全缓存出来,而是等你滚动到一定的距离的时候, 下面的图片才会继续缓存,并且图片也是随机出现的,只是宽度 ...
- WPF下制作的简单瀑布流效果
最近又在搞点小东西,美化界面的时候发现瀑布流效果比较不错.顺便就搬到了WPF,下面是界面 我对WEB前端不熟,JS和CSS怎么实现的,我没去研究过,这里就说下WPF的实现思路,相当简单. 1.最重要的 ...
- [Android Pro] RecyclerView实现瀑布流效果(二)
referece to : http://blog.csdn.net/u010687392 在上篇中我们知道RecyclerView中默认给我们提供了三种布局管理器,分别是LinearLayoutMa ...
随机推荐
- 在IDEA里创建web项目,以及web 项目部署
在IDEA里创建web项目很简单: 1).先创建一个简单的maven项目,这个步骤我就不说了. 2).maven项目创建完后,因为我们需要的是web项目,因此我们要在pom.xml文件里设置packa ...
- CentOS7下安装caffe(包括ffmpeg\boost\opencv)
因为有项目想采用深度学习,而caffe是深度学习框架中比较理想的一款,并且跨平台,以及可以采用python/matlab的方式进行调用等优势,所以想在服务器上安装,下面就开始了血泪史... 服务器是阿 ...
- SSM框架下的redis缓存
基本SSM框架搭建:http://www.cnblogs.com/fuchuanzhipan1209/p/6274358.html 配置文件部分: 第一步:加入jar包 pom.xml <!-- ...
- SpringMVC—Struts2拦截器学习网址整理
引自:http://blog.csdn.net/wp1603710463/article/details/49982683 SpringMVC—Struts2拦截器学习网址整理 最近项目中遇到权限相关 ...
- 在ASP.NET MVC 中使用ActiveReports报表控件
随着MVC模式的广泛运用,对Web应用系统的开发带来了巨大的影响,我们好像又回到了原来的ASP时代,视乎这是一种后退而不是一种进步,不过MVC模式给我们带来的影响不仅限于我们所看到的这一点..MVC看 ...
- 语义SLAM的数据关联和语义定位(二)Semantic Localization Via the Matrix Permanent
论文假设和单目标模型 这部分想讲一下Semantic Localization Via the Matrix Permanent这篇文章的一些假设. 待求解的问题可以描述为 假设从姿态\(x\)看到的 ...
- 单表(SSM、SpringBoot、SpringCloud、Freemaker、BootStrap等)
山门也有门门道道, 开发.测试.安卓...... 小子被纳入MIS小山峰,虽不及BOP势力庞大,高手如云, 仅寥寥七人, 却也于入小山峰之事乐趣至极. 前几日峰主布下一道新手任务, 制作一张单表并运行 ...
- UWP开发细节记录:加载图像文件到D2D位图和D3D纹理
在UWP中加载文件一般先创建 StorageFile 对象,然后调用StorageFile.OpenReadAsync 方法得到一个IRandomAccessStream 接口用来读取数据: Stor ...
- Sql Server Tempdb原理-日志机制解析实践
笔者曾经在面试DBA时的一句”tempdb为什么比其他数据库快?”使得95%以上的应试者都一脸茫然.Tempdb作为Sqlserver的重要特征,一直以来大家对它可能即熟悉又陌生.熟悉是我们时时刻刻都 ...
- Azure 中 Windows 虚拟机的大小
本文介绍可用于运行 Windows 应用和工作负荷的 Azure 虚拟机的可用大小和选项. 此外,还提供在计划使用这些资源时要考虑的部署注意事项. 本文也适用于 Linux 虚拟机. 类型 大小 说明 ...