简单瀑布流小插件(宽度一定)

本文介绍了一种使用JavaScript实现瀑布流布局的方法,详细解释了其工作原理,并提供了一个具体实例。该方法通过动态调整元素位置来确保视觉上的均衡分布。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

瀑布流这个东西,学过很久了,现在把它记录一下。

简单说一下原理:定义一个数组保存第一行中的所有div的高度(如果有间隙,加上间隙),找出第一行中的最小高度,然后下一行第一个div的top值就等于这个最小高度,然后更新保存的最小高度,继续重复执行。

如果我们要将它做成小插件的话,需要考虑:
1. 我们要将它放到什么地方去?
2. 当前显示的是第几页
3. 每页显示多少数量
4. jsonp返回的数据
5. 每个div的宽度
6. div与div之间的间隙
7. 传入进来的图片的key值
8. 如果有文字说明,传入进来的文本的key值

以上几点都是我们要考虑的,因为这些可能是会变化的,所以这些都要做成变量,让用户传入。

好了,以下附上源码(还有点小问题,但我还不知哪里出问题了)。

/**
 * 瀑布流
 * @param {Object} json:数据
 */
function WaterFall(json){
    this.obj = json.obj;                // 瀑布流要在哪个对象中显示
    this.page = json.page || 1;         // 当前的页数,默认为1
    this.count = json.count || 10;      // 每页显示的数据量,默认为10
    this.data = json.data;              // 利用jsonp获取的数据
    this.width = json.width;            // 每张图片的宽度
    this.gap = json.gap;                // 图片与图片之间的间隙
    this.path = json.path;              // 利用jsonp返回的数据中的图片路径的key值,不是value值
    this.textName = json.textName;      // 文本描述,如果没有文本,可以不写或者传入可以转换为false的值

    this.arrHeight = [];                // 记录一行中每个div高度的数组
    this.divs = [];                     // 装着产生的div
    this.num = this.page * this.count;  // 当前显示的图片的总数
    this.isEnd = false;                 // 是否到了利用jsonp获取的最后一个数据,如果到了,就算继续滚动鼠标滚轮,也不会再加载任何数据
}
// 初始化方法
WaterFall.prototype.init = function(){
    this.setObj();
    this.createElements();
    this.updatePosition();
    this.mouseEnd();
};
// 主要用于设置传入进来的对象的position属性
WaterFall.prototype.setObj = function(){
    this.obj.style.position = 'relative';
};
// 获取最小高度
WaterFall.prototype.getMinHeight = function(){
    var min = 0;
    for(var i = 0, len = this.arrHeight.length; i < len; i ++){
        if(this.arrHeight[i] < this.arrHeight[min]){
            min = i;
        }
    }
    return min;
};
// 获取最大高度
WaterFall.prototype.getMaxHeight = function(){
    var max = 0;
    for(var i = 0, len = this.arrHeight.length; i < len; i ++){
        if(this.arrHeight[i] > this.arrHeight[max]){
            max = i;
        }
    }
    return max;
};
// 创建div、创建img
WaterFall.prototype.createElements = function(){
    var start = this.count * (this.page - 1); // 当前已经显示了多少数据
    for(var i = start; i < this.num; i ++){
        var div = document.createElement('div');
        div.style.width = this.width + 'px';
        div.style.margin = this.gap/2 + 'px';
        div.style.position = 'absolute';

        var img = document.createElement('img');
        img.src = this.data[i][this.path];
        img.style.width = this.width + 'px';

        div.appendChild(img);

        // 如果有传入文本,则创建p标签
        if(this.textName){
            var p = document.createElement('p');
            p.innerHTML = this.data[i][this.textName];

            div.appendChild(p);
        }

        this.divs.push(div);
    }
};
// 更新div的位置
WaterFall.prototype.updatePosition = function(){
    // 计算一行能放多少个div
    var cols = parseInt(this.obj.offsetWidth / (this.width + this.gap));
    // 计算更新位置的起始值(上一次的结束位置)
    var start = this.count * (this.page - 1); // 当前已经显示了多少数据

    for(var i = start; i < this.num; i ++){
        var d = this.divs[i];
        this.obj.appendChild(d); // 将创建的div添加到对象中
        if(i < cols){ // 计算并设置第一行的div的left
            d.style.top = 0;
            d.style.left = i * (this.width + this.gap) + 'px';
            // 将第一行中每个div的(高度+间隙)添加到数组中
            this.arrHeight.push(d.offsetHeight + this.gap);
        }else{
            var min = this.getMinHeight(); // 获得每一行中的最小高度的div的下标
            d.style.top = this.arrHeight[min] + 'px';
            d.style.left = min * (this.width + this.gap) + 'px';

            // 更新数组中保存的最小高度,上一行的最小高度加上目前div的高度及间隙
            this.arrHeight[min] += (d.offsetHeight + this.gap);
        }
    }
    // 设置最外层obj的高度值
    var max = this.getMaxHeight();
    this.obj.style.height = this.arrHeight[max] + 'px';

};
// 鼠标滚动到底部时,页数加1,继续加载剩余的数据,当数据加载完成,不再继续加载
WaterFall.prototype.mouseEnd = function(){
    var t = this;
    window.onscroll = function(){
        var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
        var clientHeight = document.documentElement.clientHeight || document.body.clientHeight;
        if(scrollTop + clientHeight > t.obj.offsetHeight){
            if(t.isEnd){
                return;
            }
            // 当当前页面的总数据量大于jsonp传递过来的数据量时,将isEnd设置为true
            // 并将页面总数据量设置为jsonp传递过来的数据量
            // 当前页数设置为jsonp传递过来的数据量除以每页数据,并向上取整
            if(t.num >= t.data.length){
                t.isEnd = true;
                t.num = t.data.length;
                t.page = Math.ceil(t.data.length / t.count);
            }else{
                // 如果当前页面的总数据量小于或等于jsonp传递过来的数据量时,
                // 当前页数加1,更新当前页面总数据量
                t.page++;
                t.num = t.count * t.page;
                // 如果当前页面的总数据量刚好等于jsonp传递过来的数据量时,也将isEnd设置为true
                if(t.num == t.data.length){
                    t.isEnd = true;
                }
            }
            // 根据页面总数据量创建节点及更新节点位置
            t.createElements();
            t.updatePosition();
        }
    };
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值