解析瀑布流布局: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 相关文章推荐
jQuery chili图片远处放大插件
Nov 30 Javascript
JavaScript中九种常用排序算法
Sep 02 Javascript
javascript清空table表格的方法
May 14 Javascript
JQuery实现左右滚动菜单特效
Sep 28 Javascript
FullCalendar日历插件应用之数据展现(一)
Dec 23 Javascript
javascript自动恢复文本框点击清除后的默认文本
Jan 12 Javascript
BootStrap文件上传样式超好看【持续更新】
May 10 Javascript
JavaScript实现前端分页控件
Apr 19 Javascript
浅谈Angular文字折叠展开组件的原理分析
Nov 24 Javascript
解决vue 格式化银行卡(信用卡)每4位一个符号隔断的问题
Sep 14 Javascript
微信小程序实现点击页面出现文字
Sep 21 Javascript
Vue解决移动端弹窗滚动穿透问题
Dec 15 Vue.js
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
深入了解php4(1)--回到未来
2006/10/09 PHP
PHP 类型转换函数intval
2009/06/20 PHP
PHP中将字符串转化为整数(int) intval() printf() 性能测试
2020/03/20 PHP
php校验表单检测字段是否为空的方法
2015/03/20 PHP
PHP+mysql实现从数据库获取下拉树功能示例
2017/01/06 PHP
php使用curl模拟多线程实现批处理功能示例
2019/07/25 PHP
PHP+fiddler抓包采集微信文章阅读数点赞数的思路详解
2019/12/20 PHP
PHP $O00OO0=urldecode &amp; eval 解密,记一次商业源码的去后门
2020/09/13 PHP
摘自百度的图片轮换效果代码
2007/11/19 Javascript
jquery ajax请求实例深入解析
2012/11/26 Javascript
浅谈javascript中return语句
2015/07/15 Javascript
移动端点击态处理的三种实现方式
2017/01/12 Javascript
JS实现unicode和UTF-8之间的互相转换互转
2017/07/05 Javascript
详解在vue-cli中引用jQuery、bootstrap以及使用sass、less编写css
2017/11/08 jQuery
JavaScript引用类型之基本包装类型实例分析【Boolean、Number和String】
2018/08/09 Javascript
jQuery 点击获取验证码按钮及倒计时功能
2018/09/20 jQuery
React 实现拖拽功能的示例代码
2019/01/06 Javascript
Vue 中获取当前时间并实时刷新的实现代码
2020/05/12 Javascript
Vuex中的Mutations的具体使用方法
2020/06/01 Javascript
Ant Design的可编辑Tree的实现操作
2020/10/31 Javascript
解决vant-UI库修改样式无效的问题
2020/11/03 Javascript
创建与框架无关的JavaScript插件
2020/12/01 Javascript
[04:44]DOTA2西游记战队视频彩蛋流出 师徒开黑巧遇林书豪
2016/08/03 DOTA
Python中字典的setdefault()方法教程
2017/02/07 Python
Python + selenium自动化环境搭建的完整步骤
2018/05/19 Python
基于Python在MacOS上安装robotframework-ride
2018/12/28 Python
python使用opencv对图像mask处理的方法
2019/07/05 Python
使用python实现对元素的长截图功能
2019/11/14 Python
Python实现随机生成任意数量车牌号
2020/01/21 Python
python 匿名函数与三元运算学习笔记
2020/10/23 Python
美国第一大药店连锁机构:Walgreens(沃尔格林)
2019/10/10 全球购物
What is EJB
2016/07/22 面试题
公司庆典活动邀请函
2014/01/09 职场文书
2014年售后服务工作总结
2014/11/18 职场文书
兵马俑导游词
2015/02/02 职场文书
三下乡活动心得体会
2016/01/23 职场文书