js瀑布流布局(2018-8-01)


八月了,时间过得可真快。不知道自己现在的状态是什么,有点不太明确自己的定位。也算是个大二的学生了,可是一直都是一颗大一的心。要学的东西还有很多呢,加油!


看到让写“瀑布流”的时候,自己还是很懵的,因为不太清楚它的具体操作。只是所谓的“瀑布流”其实还是比较常见的,比如百度图片时,就是以瀑布流的形式呈现的。所以形式熟悉,操作的关键呢,就是在图片的布局,和上下图片的衔接上。这两大部分,一个是关于宽度的操作,一个是关于高度的操作。在html和css部分都是很简单的,主要的操作就在js上。


思路
第一步:确定图片的每行图片的个数,及图片的居中显示
思路:一个大的div包括了所有的图片div,图片分为外层的div ->'box',内层的图片div ->'img_box'。通过传参传入父级div ->'container',在经过for循环判断id 得到 子级的每张图片的div 为'box',将其放入数组。然后通过数组元素计算出每张图片的大小,再得到屏幕的大小,再而算出来每行可以放多少张图片。为了避免图片在窗口大小变化时,每行的个数也发生变化,从而要固定每行的图片张数。

第二步:确定图片的高度,以及每行图片的衔接摆放
思路:将第一行图片的高度放入数组,然后找出其中高度最小的图片,再调用方法通过for循环找到最小高度的图片的下标,然后让下一行的第一张图片放在上一行高度最低的那张图片下面,进行定位,再改变图片的高度(上一张+下一张),以及相对于 距离左边的距离,并改变最小下标的高度,在通过数组‘box’的改变(i++)进行下一次循环。以实现图片的无限循环排放。


下面来介绍一下瀑布流的操作:
1.将图片添加到整个大的div -> 'container'中,每张图片都放入一个div ->'box'中,然后设置图片的css样式。

图片在html文件中的布局
<div id="container">
      <div class="box">
          <div class="img_box">
              <img src="image/13.jpg">
          </div>
      </div>
      <div class="box">
          <div class="img_box">
              <img src="image/14.jpg">
          </div>
      </div>
</div>
图片的css样式
*{
    padding: 0;
    margin: 0;
}
#container{
    position: relative;
}
.img_box{
    border: 1px solid #cccccc;
    border-radius: 5px;
    padding: 5px;
    box-shadow: 0 0 5px #cccccc;
}
.box{
    padding: 5px;
    float: left;
}
.img_box img{
    width: 200px;
    height: auto;
}

2. 将承载每张图片的div ->'box',放入数组中,为接下来得到每张图片的宽度,图片的高度,距离左边的距离做好铺垫。

//得到所有的‘box’数组
function getElementboxs(parent,content) {
    var getboxsArr = [];//得到所有的‘box’放入数组
    var allcontent = parent.getElementsByTagName("*");
    for(var i =0;i<allcontent.length;i++){
        if(allcontent[i].className === content){
            getboxsArr.push(allcontent[i]);
        }
    }
    return getboxsArr;
}

3. 得到每张图片的宽度(每张图片的宽度一样),以及屏幕的宽度,就可以得到屏幕一行可以放多少张图片。并固定每行可以放置的图片个数,并居中放置。放置浏览器的窗口大小变化,影响每行图片的摆放。

function imageLocation(parent,content){
   var cparent = document.getElementById(parent);//通过父级元素得到子级
   var ccontent = getElementboxs(cparent,content);//得到所有的‘box’,为数组
   var imgWidth = ccontent[0].offsetWidth; //每张图片的宽度
   var screenWidth = document.documentElement.clientWidth;//得到屏幕的宽度
   var num = Math.floor(screenWidth/imgWidth); //得到每行可以放下图片的个数,取整数
   cparent.style.cssText = "width:"+ imgWidth * num +"px;margin:0 auto";
   //固定每行图片个数,并居中显示
}

4.通过数组得到每张图片的高度,找到高度最低的图片的下标,实现每张图片的绝对定位,设置其距离顶部的高度为最低的图片高度,其离左边的距离是最低的图片离左边的距离,给每次筛选出来的图片定位。

将每张图片的高度加入数组,并给每次筛选出来的图片定位。
 var imgHeightArr = [];//将第一行的图片的高度放入数组
   for(var i = 0;i<ccontent.length;i++){
      if(i<num){
          imgHeightArr[i] = ccontent[i].offsetHeight;
      }
     else{
        var minHeigthImg = Math.min.apply(null,imgHeightArr);//得到高度最小的图片
        var minHeightIndex =getminHeightIndex(imgHeightArr,minHeigthImg);
       //得到最小高度的下标
        ccontent[i].style.position = "absolute";//固定图片的位置,绝对定位
        ccontent[i].style.top= minHeigthImg +"px";
        //设置图片距顶部的高度,刚好是高度最小的那张图片的位置
        ccontent[i].style.left = ccontent[minHeightIndex].offsetLeft + "px";
       //设置图片距离左边的距离,则是最低图片的下标距离最左边的距离
        imgHeightArr[minHeightIndex] = imgHeightArr[minHeightIndex] + ccontent[i].offsetHeight; 
        //图片放好后,改变最低图片的高度,加上新放上去的,其成为最高的图片,进入下次循环
       }
循环找到高度最低的图片的下标
function getminHeightIndex(imgHeightArr,minHeightImg) {
    for(var i in imgHeightArr){
        if(imgHeightArr[i] === minHeightImg){
            return i;
        }
    }
}


基本的瀑布流就实现了,我们来看下效果图:


实现瀑布流的效果

为了达到美观的效果,还模仿着做了一个滚动条无限滚动鼠标都会显示图片的效果。就像百度网页的图片是一样的效果,感觉图片时刷不完的。

实现无限加载的关键:
找到最后一张图片的距离顶部的高度,以及滚动条的高度(会随着鼠标滚动,数值不断变化,会有隐藏部分),和屏幕的高度。如果距离顶部的高度<(滚动条高度+屏幕高度),则在for循环进行添加图片节点,追加节点添加,与html文件中的嵌套相同(注意父节点与子节点的改变),来实现图片的不断添加,无限滚动。由于真正的网页图片由服务器提供,我们如果要实现图片的添加,就要模拟json字符串来增加图片。
那现在来看看代码的实现:

1.找到该进行加载的高度,进行循环的无限加载

function checkTop() {
   var parents = document.getElementById("container");
   var contents = getElementboxs(parents,"box");//通过父级元素找到所有的‘box’的数组
   var lastImagetop = contents[contents.length - 1].offsetTop;
    //得到最后一张图片距顶部的高度
   var scrollTop = document.documentElement.scrollTop||document.body.scrollTop;
    //得到滚动条的高度(包括隐藏部分)
   var screenHeight = document.documentElement.clientHeight||document.body.clientHeight;
    //得到屏幕的高度
   if(lastImagetop < screenHeight + scrollTop){
        return true;
    }
}

2.找到要加载的高度,开始循环进行无限加载,重点是节点的添加与html文件中的嵌套相同。

window.onload = function () {
    imageLocation("container","box");
    var ImageData = {  //模拟json字符串,获取图片数据
        "data":[{"src":"38.jpg"},{"src":"13.jpg"},{"src":"22.jpg"},{"src":"23.jpg"},{"src":"27.jpg"},
            {"src":"40.jpg"},{"src":"34.jpg"},{"src":"33.jpg"},{"src":"32.jpg"},{"src":"31.jpg"},{"src":"30.jpg"}]};
    //添加节点以至于可以无限浏览。循环中操作。
  (div层层嵌套注意父节点与子节点的改变)
  window.onscroll = function () {  //监控滚动条
        if(checkTop()){
            var container = document.getElementById("container"); //先找到父元素
            for(var i =0 ;i<ImageData.data.length;i++){   //循环json字符串
                var box = document.createElement("div"); //创建子元素节点(第一层div)
                box.className = "box";    //设置统一的class,以识别其添加的层次
                container.appendChild(box); //向父级元素中追加创建的新节点
                var imgbox = document.createElement("div");//(第二层div)
                imgbox.className = "img_box";
                box.appendChild(imgbox);
                var img = document.createElement("img"); //(第三层内包含图片)
                img.src = "image/"+ImageData.data[i].src;
                imgbox.appendChild(img);
            }
            imageLocation("container","box");
            //每次加载过后要进行高度排序,d要重新进行循环放置图片
        }
    }
}

来看下实现无限加载后的效果图:


注意右边的滚动条已经在底部,但图片并没有到底部

就结束啦,是个小收获,算是学习的js的综合应用吧。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,686评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,668评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,160评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,736评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,847评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,043评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,129评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,872评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,318评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,645评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,777评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,861评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,589评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,687评论 2 351

推荐阅读更多精彩内容

  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 13,741评论 1 92
  • html结构 (Emmet) (div.box>div.pic>img[src="images/$.jpg"])*...
    LaBaby_阅读 635评论 0 0
  • html结构 (Emmet)(div.box>div.pic>img[src="images/$.jpg"])*2...
    黎贝卡beka阅读 515评论 1 4
  • 所谓瀑布流,就是图片分几列有规律的排列,但是这里的排列是有要求的,普通的浮动布局会使图片与图片之间有很多的空隙,这...
    小飞侠zzr阅读 819评论 0 0
  • -01- 塔基族世代感受神谕,并虔诚地严格遵守,这体现在千百年来每当有婴孩即将降生,准父母们便会斋戒三天,沐浴更衣...
    摘星妮妮阅读 269评论 0 1