解析瀑布流布局:JS+绝对定位的实现


Posted in Javascript onMay 08, 2013

绝对定位方式的瀑布流布局:

一、布局

1、包围块框的容器:

<div id="main">
    ... ...
<div>

2、一个块框:
<div class="pin">
    <div class="box">
        <img src="./images/g (1).jpg"/>
    </div>
</div>

3、初始化第一行/5个块框:
.pin{
        padding: 15px 0 0 15px;
        float: left;}
    .box{
        padding: 10px;
        border:1px solid #ccc;}
    .box img{
        width:192px;
        height:auto;}

效果:

解析瀑布流布局:JS+绝对定位的实现

二、思路:

1、设置父级main的样式:水平居中。
2、设置每个块框pin的样式:绝对定位。
3、设置窗口滚动事件的监听函数:读取数据添加块框。

JS实现:

1-①:获取父级oParent:

1-②:创建函数getClassObj()-通过父级id和块框类名-获取包含块框的数组。

    var oParent=document.getElementById('main');// 父级对象
    var aPin=getClassObj(oParent,pin);// 获取存储块框pin的数组aPin
    var num=Math.floor(document.documentElement.clientWidth/aPin[0].offsetWidth);//获取-每行中能容纳的块框个数-num【窗口宽度除以一个块框宽度】

oParent.style.cssText='width:'+iPinW*num+'px;margin:0 auto;';//用cssText属性为父级main添加居中样式:定宽+自动水平外边距

function getClassObj(parent,className){
        var obj=parent.getElementsByTagName('*');//获取 父级的所有子集
        var pinS=[];//创建一个数组 用于存储类为className的元素
        for (var i=0;i<obj.length;i++) {//遍历子集、判断类名、压入数组
            if (obj[i].className==className)
                pinS.push(obj[i]);
        };
        return pinS;}

2-①:创建数组pinHArr-用于存储每一列高度;

2-②:for语句遍历每个块框aPin[i],将前num个块框赋值给数组pinHArr,对超出一行能容纳的块框数num的块框绝对定位。

2-③:用创建函数getminHIndex()-返回一个数组中的最小值

var pinHArr=[];//用于存储 每列中的所有块框相加的高度【随着列数的不同此数组的length也随之改变】
    for(var i=0;i<aPin.length;i++){//遍历数组aPin的每个块框元素
        var pinH=aPin[i].offsetHeight;//获取数组aPin的第i个块框的可见宽offsetHeight
        if(i<num){//
            pinHArr[i]=pinH; //第一行中的num个块框aPin 先添加进数组pinHArr
        }else{
            var minH=Math.min.apply(null,pinHArr);//计算数组pinHArr中的最小值minH
            var minHIndex=getminHIndex(pinHArr,minH);//通过创建的getminHIndex()-获取最小值minH在数组pinHArr中的索引minHIndex
            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;//更新添加块框后的列高
        }
    }

    function getminHIndex(arr,minH){
        for(var i in arr){
            if(arr[i]==minH)return i;
        }
    }

 

3:设置窗口滚动事件的监听函数:读取数据添加块框。

var dataInt={'data':[{'src':'g (1).jpg'},{'src':'g (9).jpg'},{'src':'g (2).jpg'},{'src':'g (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'); //创建添加 元素节点pin
            oPin.className='pin';                   //添加 类名 name属性
            oParent.appendChild(oPin);              //创建添加 子节点box
            var oBox=document.createElement('div');
            oBox.className='box';
            oPin.appendChild(oBox);
            var oImg=document.createElement('img');//创建添加 子节点img
            oImg.src='./images/'+dataInt.data[i].src;
            oBox.appendChild(oImg);
        }
        waterfall('main','pin');//将①②封装成函数waterfall(),将添加的节点添加到添加和定位到文档中。
        };
    }

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()函数
    }

三、最终效果:解析瀑布流布局:JS+绝对定位的实现

四、总结:此为让自己梳理一下思路,表达不太仔细连贯,仅供参考。

五、完成后的html文件和js文件:

html:index.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
 <meta name="anchor" content="who care?" />
 <script type="text/javascript" src="waterfall.js"/></script> <title></title>
 <style type="text/css">
     *{padding: 0;margin:0;}
     #main{
         position: relative;
     }
     .pin{
         padding: 15px 0 0 15px;
         float:left;
     }
     .box{
         padding: 10px;
         border:1px solid #ccc;
         box-shadow: 0 0 6px #ccc;
         border-radius: 5px;
     }
     .box img{
         width:162px;
         height:auto;
     }
 </style>
 </head>
 <body>
 <div id="main">
     <div class="pin">
         <div class="box">
             <img src="./images/g (1).jpg"/>
         </div>
     </div>
     <div class="pin">
         <div class="box">
             <img src="./images/g (2).jpg"/>
         </div>
     </div>
     <div class="pin">
         <div class="box">
             <img src="./images/g (3).jpg"/>
         </div>
     </div>
     <div class="pin">
         <div class="box">
             <img src="./images/g (4).jpg"/>
         </div>
     </div>
     <div class="pin">
         <div class="box">
             <img src="./images/g (5).jpg"/>
         </div>
     </div>
 </div>
 </body>
 </html>

js:waterfall.js 1 window.onload=function(){
waterfall('main','pin');
     var dataInt={'data':[{'src':'g (1).jpg'},{'src':'g (9).jpg'},{'src':'g (2).jpg'},{'src':'g (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 元素id
 */
 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='width:'+iPinW*num+'px;ma rgin: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()函数
     }
Javascript 相关文章推荐
js禁止document element对象选中文本实现代码
Mar 21 Javascript
JS特殊函数(Function()构造函数、函数直接量)区别介绍
May 19 Javascript
js调用css属性写法
Sep 21 Javascript
javascript 获取HTML DOM父、子、临近节点
Jun 16 Javascript
jQuery简单操作cookie的插件实例
Jan 13 Javascript
javascript弹出带文字信息的提示框效果
Jul 19 Javascript
js方法数据验证的简单实例
Sep 17 Javascript
微信小程序实现点击按钮修改view标签背景颜色功能示例【附demo源码下载】
Dec 06 Javascript
详解VUE2.X过滤器的使用方法
Jan 11 Javascript
vue-baidu-map 进入页面自动定位的解决方案(推荐)
Apr 28 Javascript
vue slot与传参实例代码讲解
Apr 28 Javascript
js实现小时钟效果
Mar 25 Javascript
JavaScript 对任意元素,自定义右键菜单的实现方法
May 08 #Javascript
深入document.write()与HTML4.01的非成对标签的详解
May 08 #Javascript
使用JavaScript 实现各种跨域的方法
May 08 #Javascript
jQuery根据纬度经度查看地图处理程序
May 08 #Javascript
使用JavaScript 实现对象 匀速/变速运动的方法
May 08 #Javascript
JavaScript 创建运动框架的实现代码
May 08 #Javascript
jQuery输入城市查看地图使用介绍
May 08 #Javascript
You might like
如何在smarty中增加类似foreach的功能自动加载数据
2013/06/26 PHP
PHP魔术方法__GET、__SET使用实例
2014/11/25 PHP
JS实现在Repeater控件中创建可隐藏区域的代码
2010/09/16 Javascript
JS 自定义带默认值的函数
2011/07/21 Javascript
解决Extjs4中form表单提交后无法进入success函数问题
2013/11/26 Javascript
js表单验证实例讲解
2016/03/31 Javascript
Bootstrap每天必学之轮播(Carousel)插件
2016/04/25 Javascript
javascript实现简单的on事件绑定
2016/08/23 Javascript
jQuery实现的导航下拉菜单效果示例
2016/09/05 Javascript
微信小程序 Page()函数详解
2016/10/17 Javascript
HTML5基于Tomcat 7.0实现WebSocket连接并实现简单的实时聊天
2016/10/31 Javascript
easyui form validate总是返回false的原因及解决方法
2016/11/07 Javascript
JavaScript中boolean类型之三种情景实例代码
2016/11/21 Javascript
layer.confirm取消按钮绑定事件的方法
2018/08/17 Javascript
在Vue 中使用Typescript的示例代码
2018/09/10 Javascript
JS函数本身的作用域实例分析
2020/03/16 Javascript
bootstrapValidator表单校验、更改状态、新增、移除校验字段的实例代码
2020/05/19 Javascript
JS实现时间校验的代码
2020/05/25 Javascript
Python使用函数默认值实现函数静态变量的方法
2014/08/18 Python
python中单下划线(_)和双下划线(__)的特殊用法
2019/08/29 Python
TensorFlow绘制loss/accuracy曲线的实例
2020/01/21 Python
Python图像阈值化处理及算法比对实例解析
2020/06/19 Python
Python openpyxl模块实现excel读写操作
2020/06/30 Python
Django Form设置文本框为readonly操作
2020/07/03 Python
CSS3 box-sizing属性
2009/04/17 HTML / CSS
深深扎根运动世界的生活品牌:Tillys
2017/10/30 全球购物
手工制作的豪华英式沙发和沙发床:Willow & Hall
2019/05/03 全球购物
员工工作表扬信范文
2014/01/13 职场文书
全国爱牙日活动总结
2015/02/05 职场文书
律政俏佳人观后感
2015/06/09 职场文书
2015初一年级组工作总结
2015/07/24 职场文书
mysql死锁和分库分表问题详解
2021/04/16 MySQL
react中props 的使用及进行限制的方法
2021/04/28 Javascript
HTML通过表单实现酒店筛选功能
2021/05/18 HTML / CSS
Python实现打乒乓小游戏
2021/09/25 Python
Netty分布式客户端处理接入事件handle源码解析
2022/03/25 Java/Android