原生js实现瀑布流效果

实现目标:实现瀑布流布局、当滚动条滚动到一定距离时加载图片
瀑布流布局:结合窗口改变 定位第一行的盒子 第二行第一个盒子接到第一行最矮的盒子下面 当接完后更新最矮盒子 以此类推
滚动加载图片:案例是用数组对象实现图片加载 条件是当加载到最后一张图片一半+最后盒子的offsetTop小于等于屏幕的高度+滚动的距离时 加载图片
当窗口更新时:运用onresize事件重置 运用节流使得加载性能提高

html+css

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>瀑布流</title>
    <style>
        body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, dl, dt, dd, ul, ol, li, pre, form, fieldset, legend,
        button, input, textarea, th, td { margin:0; padding:0;border:none;list-style:none; }
        body,html{
            width: 100%;
            height: 100%;
        }
        #main{
            position: relative;
        }
        .box{
            float: left;
            padding: 15px 0 0 15px;

        }
        .pic{
            border:1px solid #ccc;
            border-radius: 5px;
            padding: 10px;
        }
        .pic img{
            width: 150px;
        }
    </style>

</head>
<body>
<div id="main">
    <div class="box">
        <div class="pic"><img src="imgs/img01.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img02.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img03.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img04.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img05.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img06.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img07.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img08.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img09.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img10.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img11.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img12.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img13.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img14.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img15.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img16.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img17.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img18.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img19.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img20.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img21.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img22.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img23.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img24.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img25.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img26.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img27.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img28.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img29.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img30.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img31.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img32.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img33.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img34.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img35.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img36.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img37.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img38.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img39.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img40.jpg" alt=""></div>
    </div>
</div>
<script src="js/index.js"></script>
<script src="js/scroll.js"></script>
</body>
</html>

注意:index.js为主要js代码 scroll.js为封装scroll的代码 链接:https://www.jianshu.com/p/6427731bb125
css方面:添加定位

window.onload = function () {
    // 1. 实现瀑布流布局
    waterFull("main", "box");

    // 2. 动态加载图片
    var timer1 = null;
    window.onscroll = function () {
        clearTimeout(timer1);
        timer1 = setTimeout(function () {
            if(checkWillLoadImage()){
                // 2.1 造数据
                var dataArr = [
                    {"src": "img04.jpg"},
                    {"src": "img06.jpg"},
                    {"src": "img08.jpg"},
                    {"src": "img09.jpg"},
                    {"src": "img10.jpg"},
                    {"src": "img12.jpg"},
                    {"src": "img14.jpg"},
                    {"src": "img16.jpg"},
                    {"src": "img18.jpg"}
                ];

                // 2.2 创建元素
                for(var i=0; i<dataArr.length; i++){
                    var newBox = document.createElement("div");
                    newBox.className = "box";
                    $("main").appendChild(newBox);

                    var newPic = document.createElement("div");
                    newPic.className = "pic";
                    newBox.appendChild(newPic);

                    var newImg = document.createElement("img");
                    newImg.src = "images/" + dataArr[i].src;
                    newPic.appendChild(newImg);
                }

                // 2.3 重新布局
                waterFull("main", "box");
            }
        }, 200);
    };
    // 3. 窗口的大小发生改变
    var timer = null;
    window.onresize = function () {
        clearTimeout(timer);
        // 节流
        timer = setTimeout(function () {
            waterFull('main', 'box');
        }, 200);
    }
};

/**
 * 实现瀑布流布局
 */
function waterFull(parent, child) {
    // 1. 父盒子居中
    // 1.1 获取所有的盒子
    var allBox = $(parent).getElementsByClassName(child);
    // 1.2 获取子盒子的宽度
    var boxWidth = allBox[0].offsetWidth;
    // 1.3 获取屏幕的宽度
    var screenW = document.documentElement.clientWidth;
    // 1.4 求出列数
    var cols = parseInt(screenW / boxWidth);
    // 1.5 父盒子居中
    $(parent).style.width = cols * boxWidth + 'px';
    $(parent).style.margin = "0 auto";


    // 2. 子盒子的定位
    // 2.1 定义高度数组
    var heightArr = [], boxHeight = 0, minBoxHeight = 0, minBoxIndex = 0;
    // 2.2 遍历子盒子
    for (var i = 0; i < allBox.length; i++) {
        // 2.2.1 求出每一个子盒子的高度
        boxHeight = allBox[i].offsetHeight;
        // 2.2.2 取出第一行盒子的高度放入高度数组
        if (i < cols) { // 第一行
            heightArr.push(boxHeight);
            allBox[i].style = '';
        } else { // 剩余行
            // 1. 取出最矮的盒子高度
            minBoxHeight=Math.min.apply(this,heightArr);
            // 2. 求出最矮盒子对应的索引
            minBoxIndex = getMinBoxIndex(heightArr, minBoxHeight);
            // 3. 子盒子定位
            allBox[i].style.position = "absolute";
            allBox[i].style.left = minBoxIndex * boxWidth + 'px';
            allBox[i].style.top = minBoxHeight + 'px';
            // 4. 更新数组中的高度
            heightArr[minBoxIndex] += boxHeight;
        }
    }

    // console.log(heightArr, minBoxHeight, minBoxIndex);
}
/**
 * 获取数组中最矮盒子高度的索引
 * @param arr
 * @param val
 * @returns {number}
 */
function getMinBoxIndex(arr, val) {
    for(var i=0; i<arr.length; i++){
        if(arr[i] === val){
            return i;
        }
    }
}
function $(id) {
    return typeof id === "string" ? document.getElementById(id) : null;
}
/**
 * 判断是否具备加载图片的条件
 */
function checkWillLoadImage() {
    // 1. 获取最后一个盒子
    var allBox = document.getElementsByClassName("box");
    var lastBox = allBox[allBox.length - 1];

    // 2. 求出最后一个盒子自身高度的一半 + offsetTop
    var lastBoxDis = lastBox.offsetHeight * 0.5 + lastBox.offsetTop;

    // 3. 求出屏幕的高度
    var screenW = document.body.clientHeight || document.documentElement.clientHeight;

    // 4. 求出页面偏离浏览器的高度
    var scrollTop = scroll().top;

    return lastBoxDis <= screenW + scrollTop;
}


步骤:瀑布流布局封装
传入参数父盒子 子盒子
1.获取所有盒子
2.获取盒子宽度 窗口宽度
3.结合窗口改变 获取列数
4.子盒子定位
5.获取第一行盒子的宽度加入数组 (遍历所有的子盒 子 i小于列数即为第一行 )
6.取出第一行最小值 Math.min.apply(this,数组)
7.添加剩余行的定位 left=最小值的索引*盒子的宽度 top=最小盒子的高度(最小值的索引函数封装实现)
8.更新数组里的最小值 +=当前盒子的高度

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

推荐阅读更多精彩内容

  • 你只是路过我的人生, 却占据我所有的记忆。 我害怕你不苟言笑的冷漠, 也害怕你转瞬即逝的热情。 白天想你, 黑夜想...
    于曼妮阅读 268评论 0 0
  • 早上5点起床,参加凤凰队小组会。与学员的回应中我有一些严肃,本组有3人未破零,其实内心的焦急时时的反应在脸上。学员...
    顾国胜阅读 191评论 0 2
  • 黑中群,顾名思义,就是本世纪初期活跃于世界足坛的黑人中场群的简称。这个称谓始于本世纪初期在世界足坛掀起的一股在中场...
    zanmato阅读 6,743评论 6 10
  • 由高中到大学的过渡就像由天使到堕天使的进化。 在高中阶段时,我们有梦想,有进入大学的向往,有对未来的希...
    三使阅读 137评论 0 0