javascript瀑布流效果javascript
其實javascript瀑布流 前幾年都已經很流行了(特別是美麗說,蘑菇街),最近看到網上有人問這個瀑布流效果,因此本身有空的時候就研究了下,其實也是研究別人的代碼,研究了下別人寫的思路,因此有了一個本身的版本代碼。下面來說講瀑布流的思路吧!css
思路:1.先計算當前屏幕或者當前容器最多能容納幾列瀑布,其計算方法爲 maxCol = "Math.floor(屏幕可見區域寬度或者容器可視區寬度 / (格子寬度+間距))";html
2. 若是當前的容器沒有定寬度話,能夠設置容器的寬度爲:width = 列數* (格子寬度+間距) – 間距. 由於 當容器的寬度計算出來以後再顯示,不然會形成頁面寬度的抖動,影響體驗。計算方法能夠理解以下:java
上面列數爲 6列 ,5個間距,由於最右邊間距不算的,因此容器的計算方法爲:width = 列數 * (格子寬度+間距) - 間距。node
3. 排序: 目前支持2種插入方式: 1. 計算出每列最短的高度,依次插入。2. 每列是按順序插入進去。瀏覽器
下面仍是看看JSFiddler效果吧!app
組件配置項以下:this
代碼分析以下:
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時, 會去加載更多數據. };