一步步教你js原生瀑布流效果实现

一步步教你js原生瀑布流效果实现

什么是瀑布流效果

  首先,让我们先看一段动画:

  在动画中,我们不难发现,这个动画有以下特点:

  • 1.所有的图片的宽度都是一样的
  • 2.所有的图片的高度是不一样的
  • 3.图片一张挨着一张竖直排列
  • 4.鼠标向下滚动,一直不停的加载图片
  • 5.浏览器的宽度改变,图片的列数会进行相应的更改

那么这种效果类似现实生活中的瀑布,所以我们叫它瀑布流的效果.

Js原生瀑布流效果的实现

  从上述分析中,我们可以把整个效果分为以下四个部分:

  • html+css界面搭建
  • 瀑布流效果
  • 浏览器向下滚动一直加载的效果
  • 浏览器宽度改变,图片的列数改变的效果

那么,我们也从这四个分来实现

html+css界面搭建

  从效果布局中我们发现,在整体的div标签里面,放置着无数div标签,用于固定每个图片的位置,在每个固定div位置的标签里面又有一个存放图片的div标签,用于图片的定位以及设置边框,在有存放图片的div标签里面放着一个img标签.如下图所示:

布局很简单,也不是这篇文章的重点,所以我就不多说,直接上代码.

html代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>瀑布流</title>
    <link rel="stylesheet" href="css/index.css">
</head>
<body>
<div id="outBox">
    <div class="box"><div class="pic"><img src="images/1.jpg" alt=""></div></div>
    <div class="box"><div class="pic"><img src="images/2.jpg" alt=""></div></div>
    <div class="box"><div class="pic"><img src="images/3.jpg" alt=""></div></div>
    <div class="box"><div class="pic"><img src="images/4.jpg" alt=""></div></div>
    <div class="box"><div class="pic"><img src="images/5.jpg" alt=""></div></div>
    <div class="box"><div class="pic"><img src="images/6.jpg" alt=""></div></div>
    <div class="box"><div class="pic"><img src="images/7.jpg" alt=""></div></div>
    <div class="box"><div class="pic"><img src="images/8.jpg" alt=""></div></div>
    <div class="box"><div class="pic"><img src="images/9.jpg" alt=""></div></div>
    <div class="box"><div class="pic"><img src="images/10.jpg" alt=""></div></div>
    <div class="box"><div class="pic"><img src="images/11.jpg" alt=""></div></div>
    <div class="box"><div class="pic"><img src="images/12.jpg" alt=""></div></div>
    <div class="box"><div class="pic"><img src="images/13.jpg" alt=""></div></div>
    <div class="box"><div class="pic"><img src="images/1.jpg" alt=""></div></div>
    <div class="box"><div class="pic"><img src="images/2.jpg" alt=""></div></div>
    <div class="box"><div class="pic"><img src="images/3.jpg" alt=""></div></div>
</div>
<script src="js/Underscore-min.js"></script>
<script src="js/MyFun.js"></script>
<script src="js/index.js"></script>
</body>
</html>

css代码如下:

*{
    margin: 0;
    padding: 0;
    border: 0;
}
img{
    vertical-align: top;
}
#outBox{
    position: relative;

}
.box{
    padding: 15px 0 0 15px;
    float: left;
}
.pic{
    padding: 10px;
    border: 1px solid #ccc;
    width: 240px;
}
.pic img {
    width: 100%;
}

效果图如下:

实现瀑布流效果

实现最外层div居中显示

  首先,我们可以想到给一个div设置居中显示需要两个步骤:1.给div设置宽度2.给div设置margin属性为auto即可实现div的水平居中显示.那么,我们应该给最外侧大的div设置多少的宽度呢?

  我们再来回想一下上述动画效果,我们发现当浏览器宽度变大时,div宽度变宽,显示图片的列数增加,当浏览器宽度变小时,div宽度变窄,显示图片的列数减少.那么我们是不是可以理解为在div的宽度为:当前浏览器宽度下,显示最多的列数乘以div里面用于定位的div的宽度.所以接下来让我们来设置div的宽度及让其居中显示.我的代码每句话都有注释,所以我就不再单独讲解每段代码的含义.

  js代码如下:

  

//首先将大盒子outBox居中排列
    //要给大盒子设置宽度,大盒子的宽度为屏幕的宽度/小盒子box的宽度 取整 然后再乘以小盒子的宽度
    //获取大盒子
    var outBox=$(outBox);
    //获取大盒子中所有的小盒子
    var allBoxs=outBox.children;
    //由于小盒子的宽度一样,所以随便找到一个小盒子,获取齐宽度
    var boxWidth=allBoxs[0].offsetWidth;
    //获取浏览器的宽度
    screenWidth=document.documentElement.clientWidth||document.body.clientWidth;
    //那么可以计算显示的列数就是浏览器的宽度除以每个小盒子的宽度取整
    var cols=parseInt(screenWidth/boxWidth);
    //设置大盒子的宽度
    outBox.style.width=cols*boxWidth +‘px‘;
    //设置大盒子的margin值
    outBox.style.margin=‘0 auto‘;

效果图如下:

对除第一排之外的盒子做定位

  首先,我们先了解,为什么是除第一排之外的盒子做定位,因为我们从上述图片中发现,第一排的位置摆放的非常整齐,我们并不需要对他们做定位.

  那么,我们如何对第一排之外的盒子做定位呢?有人则认为从左至右逐一排列即可.那么由于所有的盒子高度不一样,我们假设一种情况所有的第一列的高度最大,第二列的高度最小,其它列依次增加,当我们排列的多了,会不会出现如下图所示非常丑陋的布局?

  

  答案是肯定的,因为每张照片的长度都不一样,任何排列组合都有可能,所以我们不能从左到右依次排列,当然也不能从右至左依次排列.

  接下来让我们想想,如果有一个容器,我们往里面放大小不等的物品,放进去的物品是不是会落到高度最小的那个位置?(如果理解不了的话,可以自己找个容器往里面丢东西试试.)所以我们排放图片也基于这个原理,把图片放高度最低的列,放置之后,更新列高为原列高+放置图片的高度.依次来放置图片即可.代码实现如下:

  

//遍历所有的box,然后将第一排(前cols个盒子的高度放入数组中)
    //创建一个空数组
    var boxHeightArr=[];
    //创建两个临时变量最小的高度以及盒子的高度
    var minHeight=0,boxHeight=0;
    //遍历所有的盒子
    for(var i=0;i<allBoxs.length;i++){
        //获取遍历到每个盒子的高度
        boxHeight=allBoxs[i].offsetHeight;
        if(i<cols){//讲第一排的高度放入数组中
            boxHeightArr.push(boxHeight);
        }else { //然后将第一排后面的所有的元素放入之前数组中高度最小的那一列
           //获取数组中最小的高度
            minHeight=_.min(boxHeightArr);
            //计算最小高度的下标,通过遍历实现
            var minIndex=getIndexByValue(boxHeightArr,minHeight);
            //设置当前盒子的样式,首先为固定定位
            allBoxs[i].style.position=‘absolute‘;
            //设置当前盒子的top,为最小高度
            allBoxs[i].style.top= minHeight +‘px‘;
            //设置当前盒子的left为最小高度的下标乘以盒子的宽度,如果第三个为最小高度,那么当前盒子的left和第三个left一样,为3*盒子的宽度,因为盒子的宽度都一样
            allBoxs[i].style.left= minIndex*boxWidth+‘px‘;
            //将数组中最小盒子的高度更新为当前高度+原来高度
            boxHeightArr[minIndex]+=allBoxs[i].offsetHeight;
        }
    }
}
/*
 * 作用:通过数组中某一个元素,返回其在数组的索引
 * 用法:getIndexByValue(数组,数组元素)
 * 返回值:返回数组元素在数组中的索引
 * */
function getIndexByValue(arr,value) {
    //遍历数组
    for(var i=0;i<arr.length;i++){
        //输入数组中第i个元素的值和value一样,则返回i,i为最小宽度的下标
        if(arr[i]==value){
            return i;
        }
    }
}

效果如下:

  

实现浏览器向下滚动一直加载的效果

  首先,我们要先监听到浏览器向下滚动事件.其次我们需要计算出什么时候需要加载盒子.那么我们就定义一下,当最后一个盒子显示出来之后,我们就开始加载,那么最后一个盒子显示出来的判断条件是什么呢?请看下图.

  从图中我们不难看出,当最后一个盒子的offsetTop值大于浏览器的高度+浏览器滚动的高度时,我们是在浏览器中看不到最后一个盒子的,所以最后一个盒子显示出来的条件为最后一个盒子的offsettop值大于浏览器的高度+浏览器滚动的高度.

  接下来我们要实现自动创建盒子,这些dom的基本的知识,想必大家都很熟悉,那么问题来了,我们如何给盒子里面的img标签设置图片呢?当然,实际开发中我们是通过向服务器获取的方式获得图片的地址,但是现在这边文档的重点不是这个,所以我就随便创建了一个json,然后把数据事先写在json里面,需要用到的时候调用一下就行了.

  判断是否需要加载的代码如下:

/*
* 功能:判断是否需要加载图片
* 用法:willBeLoad()
* 返回值:true 需要加载 false不需要加载
* */
function willBeLoad() {
    //1.先获取到最后一张照片,然后看它是否显示出来.如果显示则返回true,否则返回false
    //如果图片已经显示出来,那么这个图片到顶部的距离offsettop <屏幕的高度+滚动的高度
    //获取所有的照片
    var allBoxs=document.getElementsByClassName(‘box‘);
    //获取最后一张图片,最后一张图片的下标为数组的长度减一
    var lastBox=allBoxs[allBoxs.length-1];
    //获取最后一张图片的offsetTop值
    var lastBoxDis=lastBox.offsetTop;
    //获取屏幕的高度,这里需要适配不同的浏览器,所以使用||兼容一下
    var screenHeight=document.documentElement.clientHeight||document.body.clientHeight;
    //获取滚动的高度
    var scrollHeight=scroll().top;
    //判断,返回结果
    if(lastBoxDis<=scrollHeight+screenHeight){
        return true;
    }else {
        return false;
    }
}

  实现无限加载的js代码如下:

 

//实现向下滚动,无线加载图片
    //监听滚动事件
    window.onscroll=function () {
        if(willBeLoad()){//需要加载
            //制造点假数据
            var dataArr=[
                {src:‘1.jpg‘},
                {src:‘5.jpg‘},
                {src:‘3.jpg‘},
                {src:‘4.jpg‘},
                {src:‘2.jpg‘},
                {src:‘9.jpg‘},
                {src:‘8.jpg‘},
                {src:‘6.jpg‘},
                {src:‘7.jpg‘},
                {src:‘10.jpg‘},
                {src:‘12.jpg‘},
                {src:‘13.jpg‘},
            ]
            //遍历数据
            for(var i=0;i<dataArr.length;i++){
                //创建一个新的盒子
                var newBox=document.createElement(‘div‘);
                //新盒子的className为box,和其它的样式一样
                newBox.className=‘box‘;
                //添加新盒子
                $(‘outBox‘).appendChild(newBox);
                //创建一个新的pic盒子
                var newPic=document.createElement(‘div‘);
                //新盒子的className为pic,和其它的样式一样
                newPic.className=‘pic‘;
                //添加新盒子
                newBox.appendChild(newPic);
                //创建一个img标签
                var newImg=document.createElement(‘img‘);
                //img标签的src是哪个从json数据中取出
                newImg.src=‘images/‘+dataArr[i].src;
                //添加新的img标签
                newPic.appendChild(newImg);
            }
            //所有的盒子都创建完成之后,再执行一次瀑布流方法,否则新创建的标签不会实现瀑布流的效果
            waterFall(‘outBox‘,screenWidth);
        }
    }

效果图如下:

浏览器宽度改变,图片的列数改变的效果

  首先要监听浏览器宽度改变事件,然后当浏览器宽度改变之后,重新获取宽度,重新计算可以摆放的列数,然后加载瀑布流方法,这个比较简单,不多说,直接看代码即可

  js代码如下:

 window.onresize=function () {//监听窗口改变事件
        //获取浏览器的宽度
        screenWidth=document.documentElement.clientWidth||document.body.clientWidth;
        //重新执行瀑布流方法
        waterFall(‘outBox‘,screenWidth);
    }

   至此,所谓的js原生瀑布流效果已经实现,相信你看了这边博客之后也发现js原生瀑布流并没有想象中的那么难,关键是思路要正确.

时间: 2024-08-25 15:11:31

一步步教你js原生瀑布流效果实现的相关文章

js 图片瀑布流效果实现

/** * Created by wwtliu on 14/9/5. */$(document).ready(function(){ $(window).on("load",function(){ imgLocation(); var dataImg = {"data":[{"src":"1.jpg"},{"src":"2.jpg"},{"src":"3.j

原生JS实现瀑布流

浏览网页的时候经常会遇到瀑布流布局的网站.也许有些读者不了解瀑布流.瀑布流,又称瀑布流式布局.是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部.比如下面图片的效果,就是一个典型的瀑布流. 网上有很多JQ的瀑布流插件,而且都写好了兼容,都可以尝试去使用,这里只是跟大家分享一下原生js实现瀑布流的效果,一起学习. 一步一步来: 首先新建一个文件,就叫瀑布流.html吧. <!doctype html> <html

js实现瀑布流加载图片效果

今天学习了一个瀑布流加载效果,很多网站都有瀑布流效果,瀑布流就是很多产品显示在网页上,宽相同,高度不同,表现为多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部.原理是:1.设定一行中的列数:2.取第一行中每一个div的高度并把每一个高度放进一个数组中:3.算出数组中最小高度的index值:4.把第二行的第一个div放到最小高度的div的下方并把重新算出的高度值放进数组中,重新计算最小高度的index值:5.以此类推实现多栏布局的瀑布流效果:6.如果最后一张div的高度

bootstrap+masonry.js写瀑布流

最近在用bootstrap写一个网站,其中有个图文展示的页面要用到瀑布流的效果.因为项目要求,项目要以bootstrap为基准,不准私自添加内联样式.内部样式,所以,自己写瀑布流就不行了,所以,根据要求,百度查找相关资料,看到masonry.js.个人认为这是一个非常好用的瀑布流插件.下面说一下我在引用的过程中遇到的问题,一开始我用bootstrap栅格系统布局,代码如下 <div class="row masonry"> <div class="col-x

利用JS实现简单的瀑布流效果

哈哈, 我又来啦, 在这一段时间里, 我简单的学习了一下javascript(JS), 虽然不是很懂啦, 但是我也简单的尝试着做了点小东西, 就比如现在流行的瀑布流效果, 经过我的努力终于成功的完成了, 虽然中间非常的坎坷, 并不是一帆风顺但是最终我还是实现了个简单的效果, 下面就为大家简单的介绍下, 不知道的友友们, 有兴趣的话, 可以来参考下, 欢迎指出缺点和不足! 一.瀑布流之准备工作   首先声明下, 为了方便演示和联系, 我使用的是本地图片, 如果大家有需要的话可以尝试着写下网络的,

JS瀑布流效果-布局

<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>JS瀑布流效果-布局</title> <style> * { margin: 0px; padding: 0px; } #container { position: relative; } .box { padding: 5px; float: left; } .box_img {

用jQuery实现瀑布流效果学习笔记

jQuery一直没系统的学,只知道是js库,封装了好多js函数,方便了开发.以前做过一个原生的图片网站瀑布流效果,超级麻烦,这次用了jQuery方法,瞬间代码浓缩了,只有56行js代码.神奇的让我来把其中的几个函数具体记录一下. 首先,在WebStorm中新建一个工程,导入jquery库和几张img放在img文件夹下,新建html和css文件,用来搭建基本的网页结构.我们设定图片的宽度固定,高度不定,绝对定位,左浮动.这里就不细说了.我们主要讲jquery部分的知识. 这里我们讲一下我们要实现的

【前端】用jQuery实现瀑布流效果

jQuery实现瀑布流效果 何为瀑布流: 瀑布流,又称瀑布流式布局.是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部.最早采用此布局的网站是Pinterest,逐渐在国内流行开来.国内大多数清新站基本为这类风格. 瀑布流的应用: 瀑布流对于图片的展现,是高效而具有吸引力的,用户一眼扫过的快速阅读模式可以在短时间内获得更多的信息量,而瀑布流里懒加载模式又避免了用户鼠标点击的翻页操作,瀑布流的主要特性便是错落有致,定宽而不

jQuery+HTML5图片瀑布流效果

JavaScript与HTML5实现美女瀑布流布局,本方法是把图片的路径写在了JS的数组里,不过重点好像不是在这里,而是在图片如何自动排列的问题,你可以运行本实例后,点击“加载瀑布流布局”按钮,即可看到图片的瀑布流排列效果,现在很流行这个,希望您从本代码中能找到一些灵感. <!DOCTYPE HTML> <html> <head> <title>jQuery+HTML5图片瀑布流效果丨河北电动叉车|石家庄苗木</title> <style