zoukankan      html  css  js  c++  java
  • 瀑布流特效

    瀑布流特效

          瀑布流,又称瀑布流式布局。是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部。最早采用此布局的网站是Pinterest,逐渐在国内流行开来。国内大多数清新站基本为这类风格。

    image

          瀑布流特点:

    1、琳琅满目:整版以图片为主,大小不一的图片按照一定的规律排列。
    2、唯美:图片的风格以唯美的图片为主。
    3、操作简单:在浏览网站的时候只需要轻轻滑动一下鼠标滚轮,一切的美妙的图片精彩便可呈现在你面前。

    瀑布流布局实现方式:

    1、传统多列浮动

    image

    · 各列固定宽度,并且左浮动;
    · 一列中的数据块为一组,列中的每块依次排列;
    · 更多数据加载时,需要分别插入到不同的列中;

    优点:

          布局简单,应该说没啥特别的难点;

          不用明确知道数据块高度,当数据块中有图片时,就不需要指定图片高度。

    缺点:

          列数固定,扩展不易,当浏览器窗口大小变化时,只能固定的x列,如果要添加一列,很难调整数据块的排列;

          滚动加载更多数据时,还要指定插入到第几列中,还是不方便。

    示例:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>传统多列浮动</title>
        <style>
           div{
                  float:left;
                  margin: 5px 5px 5px 5px;
           }
           p{
               background: #90EE90;
               width:160px;
               text-align:center;
           }
        </style>
    </head>
    <body>
        <div>
            <p style="height:230px;">a1</p>
            <p style="height:100px;">a2</p>
        </div>
        
        <div>
            <p style="height:100px;">a3</p>
            <p style="height:300px;">a4</p>
        </div>
    
        <div>
            <p style="height:250px;">a5</p>
            <p style="height:200px;">a6</p>
        </div>
    </body>
    </html>

    效果:

    image

    2、 CSS3 样式定义

     image

    优点:

          直接 CSS 定义,最方便了;

          扩展方便,直接往容器里添加内容即可。

    缺点:

          只有高级浏览器中才能使用;

          还有一个缺点,他的数据块排列是从上到下排列到一定高度后,再把剩余元素依次添加到下一列,这个本质上就不一样了;

          鉴于这两个主要缺点,注定了该方法只能局限于高端浏览器,而且,更适合于文字多栏排列。

    示例:

    <!DOCTYPE HTML>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>CSS3瀑布布局</title>
    <style>
            .container{
                    -webkit-column-width:160px;
                    -moz-column-width:160px;
                    -o-colum-width:160px;
                    -webkit-column-gap:1px;
                    -moz-column-gap:1px;
                    -o-column-gap:1px;
            }
            div:not(.container){
                    -webkit-border-radius:5px;
                    -moz-border-radius:5px;
                    border-radius:5px;
                    background:#90EE90;
                    border::#CCC 1px solid;
                    display:inline-block;
                    width:157px;
                    position:relative;
                    margin:2px;
            }
            .title{
                     line-height:80px; font-size:18px; color:#999;
                     text-align:center;
                     font-family:"Microsoft YaHei";
            }
    </style>
    </head>
    
    <body>
    <section>
            <div class="container">
            <div style="height:80px" class="title">纯CSS3瀑布布局</div>
            <div style="height:260px"></div>
            <div style="height:65px"></div>
            <div style="height:120px"></div>
            <div style="height:145px"></div>
            <div style="height:90px"></div>
            <div style="height:145px"></div>
            <div style="height:160px"></div>
            <div style="height:65px"></div>
            <div style="height:230px"></div>
            <div style="height:140px"></div>
            <div style="height:85px"></div>
            <div style="height:20px"></div>
            <div style="height:145px"></div>
            <div style="height:50px"></div>
            <div style="height:65px"></div>
            <div style="height:230px"></div>
            <div style="height:140px"></div>
            <div style="height:85px"></div>
            <div style="height:20px"></div>
            <div style="height:145px"></div>
            <div style="height:50px"></div>
            <div style="height:145px"></div>
            <div style="height:160px"></div>
            <div style="height:240px"></div>
        </div>
    </section>
    </body>
    </html>

    效果:

    image

    3、绝对定位

          最优的一种方案,方便添加数据内容,窗口变化,列数/数据块都会自动调整;

    优点:
          方便添加数据内容,窗口变化,列数/数据块都会自动调整;

    缺点:

          需要实现知道数据块高度,如果其中包含图片,需要知道图片高度;

          JS 动态计算数据块位置,当窗口缩放频繁,可能会狂耗性能。

    思路:

    1) 数据块排列(对容器中已有元素进行排列),算法步骤简述下:
    设置(块元素宽度一致)
    · 初始化时,对容器中已有数据块元素进行第一次计算,需要用户给定: a,容器元素 — 以此获取窗口总宽度; b,列宽度(块元素宽度); c,最小列数;
    ·计算显示列数:窗口宽度除以一个块框宽度向下取整,并设置waterfall显示的居中
    ·存储每列的高度
    · 获得列数后,需要保存每个列的当前高度,这样在添加每个数据块时,才知道起始高度是多少;
    · 依次取容器中的所有数据块,先寻找当前高度最小的某列,之后根据列序号,确定数据块的left,top值,left 为所在列的序号乘以列宽,top 为所在列的当前高度,最后更新所在列的当前高度加上这个数据块元素的高度,至此,插入一个元素结束;
    · 当所有元素插入完毕后,调整容器的高度为各列最大的高度值,结束依次调整。

    2) 异步加载数据,包含两个步骤:
    · 绑定滚动事件,并确定预加载线高度值,即滚动到哪个高度后,需要去加载数据,其实这个就是列的最小高度值,这样当前滚动值和最小高度值比较一下即可判断出来,是否要触发加载数据;
    · 加载数据,函数传参,能提供加载数据函数和停止加载(加载多少时停止)函数,以更方便的控制。

    3.1 原生JavaScript版

    原生JavaScript版源代码:https://github.com/jingwhale/javascript-waterfall/tree/master/waterfall

    waterfall.js代码如下:

    window.onload=function(){
    
        waterfall('main','pin');
    
        var dataInt={'data':[{'src':'1.jpg'},{'src':'2.jpg'},{'src':'3.jpg'},{'src':'4.jpg'}]};
        
        window.onscroll=function(){
            if(checkscrollside()){
                var oParent = document.getElementById('main');// 父级对象
                for(var i=0;i<dataInt.data.length;i++){
                    var oPin=document.createElement('div'); //添加 元素节点
                    oPin.className='pin';                   //添加 类名 name属性
                    oParent.appendChild(oPin);              //添加 子节点
                    var oBox=document.createElement('div');
                    oBox.className='box';
                    oPin.appendChild(oBox);
                    var oImg=document.createElement('img');
                    oImg.src='./images/'+dataInt.data[i].src;
                    oBox.appendChild(oImg);
                }
                waterfall('main','pin');
            };
        }
    }
    
    
    /*
        parend 父级id
        pin 元素class
    */
    function waterfall(parent,pin){
        var oParent=document.getElementById(parent);// 父级对象
        var aPin=getClassObj(oParent,pin);// 获取存储块框pin的数组aPin
        var iPinW=aPin[0].offsetWidth;// 一个块框pin的宽
        var num=Math.floor(document.documentElement.clientWidth/iPinW);//每行中能容纳的pin个数【窗口宽度除以一个块框宽度】
        oParent.style.cssText=''+iPinW*num+'px;margin:0 auto;';//设置父级居中样式:定宽+自动水平外边距
    
        var pinHArr=[];//用于存储 每列中的所有块框相加的高度。
        for(var i=0;i<aPin.length;i++){//遍历数组aPin的每个块框元素
            var pinH=aPin[i].offsetHeight;
            if(i<num){
                pinHArr[i]=pinH; //第一行中的num个块框pin 先添加进数组pinHArr
            }else{
                var minH=Math.min.apply(null,pinHArr);//数组pinHArr中的最小值minH
                var minHIndex=getminHIndex(pinHArr,minH);
                aPin[i].style.position='absolute';//设置绝对位移
                aPin[i].style.top=minH+'px';
                aPin[i].style.left=aPin[minHIndex].offsetLeft+'px';
                //数组 最小高元素的高 + 添加上的aPin[i]块框高
                pinHArr[minHIndex]+=aPin[i].offsetHeight;//更新添加了块框后的列高
            }
        }
    }
    
    /*
        通过父级和子元素的class类 获取该同类子元素的数组
    */
    function getClassObj(parent,className){
        var obj=parent.getElementsByTagName('*');//获取 父级的所有子集
        var pinS=[];//创建一个数组 用于收集子元素
        for (var i=0;i<obj.length;i++) {//遍历子元素、判断类别、压入数组
            if (obj[i].className==className){
                pinS.push(obj[i]);
            }
        };
        return pinS;
    }
    
    /*
        获取 pin高度 最小值的索引index
    */
    function getminHIndex(arr,minH){
        for(var i in arr){
            if(arr[i]==minH){
                return i;
            }
        }
    }
    
    /*
        判断加载图片的条件
    */
    function checkscrollside(){
        var oParent=document.getElementById('main');
        var aPin=getClassObj(oParent,'pin');
        var lastPinH=aPin[aPin.length-1].offsetTop+Math.floor(aPin[aPin.length-1].offsetHeight/2);//创建【触发添加块框函数waterfall()】的高度:最后一个块框的距离网页顶部+自身高的一半(实现未滚到底就开始加载)
        var scrollTop=document.documentElement.scrollTop||document.body.scrollTop;//注意解决兼容性
        var documentH=document.documentElement.clientHeight;//页面高度
        return (lastPinH<scrollTop+documentH)?true:false;//到达指定高度后 返回true,触发waterfall()函数
    }
    效果:

    readme

    3.2 jQuery版

    jQuery版源代码:https://github.com/jingwhale/javascript-waterfall/tree/master/waterfall-jquery

    使用jquery-1.8.3.min.js,waterfall.js代码如下:

    $( window ).load( function(e){
        waterfall();
        var dataInt = { 'data': [{ 'src': '1.jpg' },{ 'src': '2.jpg' },{ 'src': '3.jpg' },{ 'src': '4.jpg' }]};
        $(window).scroll(function(){
            if( checkscrollside() ){
                $.each( dataInt.data, function(index,value){
                    var $oPin = $('<div>').addClass('pin').appendTo( $("#main") );
                    var $oBox = $('<div>').addClass('box').appendTo( $oPin );
                    $('<img>').attr('src','./images/' + $(value).attr('src')).appendTo( $oBox );
                });
                waterfall();
            }
        });
        function waterfall(){
            var $aPin = $( "#main>div" );
            var iPinW = $aPin.eq(0).outerWidth();
            var num = Math.floor( $(window).width() / iPinW );
            $( "#main" ).css({
                'width' : iPinW * num,
                'margin' : '0 auto'
            });
    
            var pinHArr = [];
            $aPin.each(function( index, value ){
                var pinH = $aPin.eq( index ).height();
                if( index < num ){
                    pinHArr[ index ] = pinH;
                }else{
                    var minH = Math.min.apply( null, pinHArr );
                    var minHIndex = $.inArray( minH, pinHArr );
                    $( value ).css({
                        'position': 'absolute',
                        'top': minH + 15,
                        'left': $aPin.eq( minHIndex ).position().left
                    });
                    pinHArr[ minHIndex ] += $aPin.eq( index ).height() + 15;
                }
            });
        }
        function checkscrollside(){
            var $aPin = $("#main>div");
            var lastPinH = $aPin.last().get(0).offsetTop + Math.floor( $aPin.last().height()/2);
            var scrollTop = $( window ).scrollTop();
            var documentH = $( document ).height();
            return (lastPinH < scrollTop + documentH ) ? true : false;
        }
    });

    附Metro风兼搭瀑布流(Html5响应式瀑布流):

    https://github.com/jingwhale/javascript-waterfall/tree/master/metro-waterfall

    效果:

    image

    参考:http://ued.taobao.org/blog/2011/09/waterfall/

    转载需注明转载字样,标注原作者和原博文地址。

  • 相关阅读:
    6、short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 += 1;有错吗?-Java面试题答案
    5、switch语句能否作用在byte上,能否作用在long上,能否作用在String上?-Java面试题答案
    4、在JAVA中如何跳出当前的多重嵌套循环?-Java面试题答案
    3、说说&和&&的区别-Java面试题答案
    2、Java有没有goto?-Java,面试题答案
    1、一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制?-Java面试题答案
    javaScript属性
    javaScript基本知识
    javaScript额外笔记
    OOP-基础知识(c#)
  • 原文地址:https://www.cnblogs.com/jingwhale/p/4305681.html
Copyright © 2011-2022 走看看