详解网页中的瀑布流显示效果

来源:互联网 发布:sql server 2005 教程 编辑:程序博客网 时间:2024/06/05 04:26

网页实现瀑布流显示效果

本网页基于JQuery框架。

瀑布流是什么?

瀑布流,又称瀑布流式布局。是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部。——摘自百度百科“瀑布流”

瀑布流布局的几个特征:
1. 单元格宽固定,高不固定。
2. 每单元格从左到右依次排列,当第一行排满后,剩余的单元格依次排在当前最短的列后。


单元格为什么可以高低错落地显示?

主要运用了元素的绝对定位,而如何正确的将不同元素定位在各自的位置,就是实现瀑布流的关键。


如何实现?

先简单的搭建网页布局,这里只需写一个单元格的代码,后续会在js中添加剩余的单元格。
单元格的内容自定,这里作为一个简单的demo仅插入一张图片,图片路径同样后续在js中添加 。

<div id="wf">    <div class="unit">        <img />    </div></div>

设置页面的CSS样式。

*{    padding: 0;    margin: 0;}#wf{    margin-top: 50px;    //将外层div设为相对定位,单元格才会相对于外层进行绝对定位    position: relative; }#wf .unit{    position: absolute;    border: 1px solid black;}#wf .unit img{    //因下js中单元格宽度设为250px,故此将图片设为230px    width: 230px;    //四周各设10px内边距    padding: 10px;}

以上完成了HTML和CSS的编写,接下来是js对于功能的实现。

  • 设定几个全局变量
    这些全局变量在接下来的编码过程中会用到,变量值可根据个人偏好酌情设置。
//单元格宽度var unit_wid = 250;//单元格间距var unit_edge = 30;//瀑布流整体大致占比var unit_rate = 0.8;//插入单元格个数(原HTML中已设一个,故实际个数再+1)var unit_num = 9;
  • 添加其余的单元格到HTML中。
//该方法需在DOM加载完成后立即执行function set_unit(){    for (var i = 0;i < unit_num;i++){        var temp = '<div class="unit"><img /></div>';        $('#wf').append(temp);    }}
  • 为每个单元格设置图片路径。
//该方法需在set_unit()方法完成后执行function set_img () {    var img = $('#wf .unit img');    for (var i = 0;i < img.length;i++){        img.eq(i).attr('src','images/' + (i+1) + '.jpg');    }}
  • 对瀑布流整体居中布局。
    1). 确定整个瀑布流的页面大致占比;
    2). 根据瀑布流整体宽度计算可容纳的单元格列数;
    3). 计算出瀑布流整体左右外边距,使其居中显示。
var wf_wid = $(window).width() * 0.8;var num = Math.floor(wf_wid / unit_wid);//整体宽度包含num个单元格宽及num-1个间距var wf_edge = ($(window).width() - (unit_wid * num + unit_edge * (num - 1))) / 2;
  • 新建数组,存放每一列的列高度,并为其赋初值0。
var heightList = [];for (var i = 0;i< num ;i++) {    heightList[i] = 0;}
  • 写两个接下来会用到的两个方法,一个用来获取数组中的最大值,一个用来获取数组中的最小值及最小值下标。
function getMax (arr) {    var max = arr[0];    for (var i = 1;i < arr.length;i++) {        if (arr[i] > max) {            max = arr[i];        }    }    return max;}
function getMin (arr) {    var min = arr[0];    var index = 0;    for(var i = 1;i < arr.length;i++){        if (arr[i] < min) {            min = arr[i];            index = i;        }    }    return {min:min,index:index};}
  • 为每个单元格绝对定位。
    每个单元格的定位位置是实现瀑布流的关键,即要先确定单元格定位样式的top与left值。
    1)列高度数组中的最小值代表了当前瀑布流最短列的高度(含单元格间距),top值直接设为该值即可。
    2)列高度数组中的最小值的下标代表了最短列是哪一列(列号=下标+1),将列号-1后再乘以每一列所占宽度(含列之间边距),再加上瀑布流整体的左边距即为left最后的值。
for (var j = 0;j < $('#wf .unit').length;j++) {    var col_minHeight = getMin(heightList).min;    var col_minIndex = getMin(heightList).index;    var initial_top = col_minHeight;    //计算left值    var initial_left = col_minIndex * (unit_wid + unit_edge) + wf_edge;    var unit = $('#wf .unit');    //为单元格定位    unit.eq(j).css({'top': initial_top + 'px','left': initial_left + 'px'});    //单元格定位完成后更新数组值保证后续定位    //原列高度数组最小值加上当前单元格高度及一个间距为新最小值    heightList[col_minIndex] = col_minHeight + unit.eq(j).height() + unit_edge;}
  • 所有单元格定位完成后设外层div(#wf)高度。
    因所有单元格均采用绝对定位,而绝对定位后的元素会脱离文档流,外层div(#wf)高度不进行设置的话默认为0,如果后续在网页中添加其他内容,新增内容会被瀑布流单元格所遮挡。
//该方法需在所有单元格定位完成后执行,传参:列高度数组的最大值function set_wfHeight (max) {    //为美观,使瀑布流最高列与底部留有50px间距    var wf_height = max + 50;    $('#wf').css('height',wf_height + 'px');}

至此瀑布流的初始定位全部完成,把相应代码放入同一个方法内,如下:

//该方法需在set_img()方法完成后执行function initial_position () {    var wf_wid = $(window).width() * 0.8;    var num = Math.floor(wf_wid / unit_wid);    var wf_edge = ($(window).width() - (unit_wid * num + unit_edge * (num - 1))) / 2;    var heightList = [];    for (var i = 0;i< num ;i++) {        heightList[i] = 0;    }    for (var j = 0;j < $('#wf .unit').length;j++) {        var col_minHeight = getMin(heightList).min;        var col_minIndex = getMin(heightList).index;        var initial_top = col_minHeight;        var initial_left = col_minIndex * (unit_wid + unit_edge) + wf_edge;        var unit = $('#wf .unit');        unit.eq(j).css({'top': initial_top + 'px','left': initial_left + 'px'});        heightList[col_minIndex] = col_minHeight + unit.eq(j).height() + unit_edge;    }    set_wfHeight(getMax(heightList));}

在浏览器DOM加载完成后按次序执行各方法,如下:

$(document).ready(function(){    set_unit();    set_img();    //设置定位方法延时加载,以确保之前方法都执行完成    setTimeout("initial_position()",500);});

定位完成后的截图
瀑布流初始定位


还可以改进吗?

毫无疑问,现在的瀑布流还有不足,最突出的一点就是:当浏览器可视窗口变化时,我们的瀑布流依然保持原样,要改变其布局只有刷新网页。

所以,接下来我们就使瀑布流可以随着浏览器窗口的变化而变化。
1)要使瀑布流可以变化,首先要解决的就是窗口变化后新的位置的top值与left值,用initial_position()中方法获取即可。
2)获得位置后如何使单元格移动到新位置上?直接修改CSS属性可以,但太过生硬,这里我采用JQuery提供的animate()方法为这一过程设一简单的动画。

$(window).resize(function(){    var wf_wid = $(window).width()*unit_rate;    var num = Math.floor(wf_wid / unit_wid);    var wf_edge = ($(window).width() - (unit_wid * num + unit_edge * (num - 1))) / 2;    var heightList = [];    for (var i = 0;i< num ;i++) {        heightList[i] = 0;    }    for (var j = 0;j < $('#wf .unit').length;j++) {        var col_minHeight = getMin(heightList).min;        var col_minIndex = getMin(heightList).index;        //-----------------------与initial_position()中不同的代码段-----------------------        var new_top = col_minHeight;        var new_left = col_minIndex * (unit_wid + unit_edge) + wf_edge;        var unit = $('#wf .unit');        //为防止窗口变化过快导致动画冲突,在执行动画前,先用stop()方法停止未完成动画        unit.eq(j).stop().animate({'top': new_top + 'px','left': new_left + 'px'},300);        //-----------------------与initial_position()中不同的代码段-----------------------        heightList[col_minIndex] = col_minHeight + unit.eq(j).height() + unit_edge;    }    set_wfHeight(getMax(heightList));});

最后放一张可动态变化的瀑布流截图
瀑布流动态定位


HTML代码:

<!DOCTYPE html><html>    <head>        <meta charset="utf-8" />        <title></title>        <style>            *{                margin: 0;                padding: 0;            }            #wf{                margin-top: 50px;                position: relative;            }            #wf .unit{                position: absolute;                border: 1px solid black;            }            #wf .unit img{                width: 230px;                padding: 10px;            }        </style>    </head>    <body>        <div id="wf">            <div class="unit">                <img />            </div>        </div>        <script type="text/javascript" src="js/jquery-3.2.0.min.js" ></script>        <script type="text/javascript" src="js/new_file.js" ></script>    </body></html>

JavaScript代码:

var unit_wid = 250;var unit_edge = 30;var unit_rate = 0.8;var unit_num = 9;$(document).ready(function(){    set_unit();    set_img();    setTimeout("initial_position()",500);});function initial_position(){    var wf_wid = $(window).width()*unit_rate;    var num = Math.floor(wf_wid / unit_wid);    var wf_edge = ($(window).width() - (unit_wid * num + unit_edge * (num - 1))) / 2;    var heightList = [];    for (var i = 0;i< num ;i++) {        heightList[i] = 0;    }    for (var j = 0;j < $('#wf .unit').length;j++) {        var col_minHeight = getMin(heightList).min;        var col_minIndex = getMin(heightList).index;        var initial_top = col_minHeight;        var initial_left = col_minIndex * (unit_wid + unit_edge) + wf_edge;        var unit = $('#wf .unit');        unit.eq(j).css({'top': initial_top + 'px','left': initial_left + 'px'});        heightList[col_minIndex] = col_minHeight + unit.eq(j).height() + unit_edge;    }    set_wfHeight(getMax(heightList));}$(window).resize(function(){    var wf_wid = $(window).width()*unit_rate;    var num = Math.floor(wf_wid / unit_wid);    var wf_edge = ($(window).width() - (unit_wid * num + unit_edge * (num - 1))) / 2;    var heightList = [];    for (var i = 0;i< num ;i++) {        heightList[i] = 0;    }    for (var j = 0;j < $('#wf .unit').length;j++) {        var col_minHeight = getMin(heightList).min;        var col_minIndex = getMin(heightList).index;        var new_top = col_minHeight;        var new_left = col_minIndex * (unit_wid + unit_edge) + wf_edge;        var unit = $('#wf .unit');        unit.eq(j).stop().animate({'top': new_top + 'px','left': new_left + 'px'},300);        heightList[col_minIndex] = col_minHeight + unit.eq(j).height() + unit_edge;    }    set_wfHeight(getMax(heightList));});function set_wfHeight (max) {    var wf_height = max + 50;    $('#wf').css('height',wf_height + 'px');}function set_img () {    var img = $('#wf .unit img');    for (var i = 0;i < img.length;i++){        img.eq(i).attr('src','images/' + (i+1) + '.jpg');    }}function set_unit(){    for (var i=0;i<unit_num;i++) {        var temp = '<div class="unit"><img /></div>';        $("#wf").append(temp);    }}function getMax (arr) {    var max = arr[0];    for (var i=1;i<arr.length;i++) {        if (arr[i] > max) {            max = arr[i];        }    }    return max;}function getMin(arr){    var min = arr[0];    var index = 0;    for(var i=1;i<arr.length;i++){        if (arr[i] < min) {            min = arr[i];            index = i;        }    }    return {min:min,index:index};}

如有不足,还请各位看官见谅~

3 0
原创粉丝点击