zoukankan      html  css  js  c++  java
  • 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="'+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时, 会去加载更多数据.
     };

    demo下载:

  • 相关阅读:
    简单两行,实现无线WiFi共享上网,手机抓包再也不用愁了
    Windows下Python 3.6 安装BeautifulSoup库
    RSA加密算法破解及原理
    干货,Wireshark使用技巧-过滤规则
    干货:Wireshark使用技巧-显示规则
    干货!链家二手房数据抓取及内容解析要点
    Wireshark分析实战:某达速递登录帐号密码提取
    协议分析中的TCP/IP网络协议
    Wireshark使用教程:不同报文颜色的含义
    VMware kali虚拟机环境配置
  • 原文地址:https://www.cnblogs.com/tugenhua0707/p/3852294.html
Copyright © 2011-2022 走看看