瀑布流在最短列添加图片失效

用ajax实现瀑布流,设置了在最短列添加图片,但是有时刷新,图片却一溜烟加在某列上

部分代码如下:

给每个img包裹一层div,判断最短列后,将div插入到该列下

systemview瀑布图如何生成 瀑布图设置汇总没有用_加载

原因:图片加载太慢
添加下一张图片,需要计算当前每个li高度,这时前面添加的图片还未完全获取到,导致高度的计算失效,如果没有padding,相当于每次加载图片,高度仅加0,新加载的图片一直加在某一列上,直至某张图片加载完成,才可能改变局势

就像这样:后面红色的框代表没有加载完成的图片,仅靠padding撑起高度,前面的红色框框里的img没有加载出来,第2列刚好本就短,所以堆积了第5、6、7张在第2列上,当这些padding累加起来,终于高度大于第4列了,才开始加在第4列上

systemview瀑布图如何生成 瀑布图设置汇总没有用_请求数据_02


实际上,我们计算offsetHeight时,应该计算前面添加的图片的实际高度,所以,在获取的图片信息中加上图片的实际宽高

所以,我们在加载图片数据时,要把图片的高度固定住,这样就能解决只有padding的问题了

在给img添加src时,也添加上img的高度:

systemview瀑布图如何生成 瀑布图设置汇总没有用_ajax_03

多次重复请求数据

做新加载判断时,监听滚轮高度,设置了当窗口高度+滚动条高度 > 最短列高度时,就触发加载新的图片,但是,加载和插入需要时间,在这个时间内,我有滚动了滚轮,再一次触发滚轮滚动事件,此时还未完成新图片的加载,判断条件依然成立,就再一次触发请求

解决办法:设置锁,当前不在请求数据,才能请求数据

完整代码:

//分页
var num = 1;

//设置请求数据的锁
var flag = false; //false代表当前不在请求数据中

//调用ajax
function send(){
    //当前不在请求数据中,才能触发请求
    if (!flag){
        myajax('GET', './getData.php', cbs, 'cpages='+num, true);
        flag = true;
        num++;
    }
}
send();

//Ajax获取数据后执行该回调函数
var oLi = document.getElementsByTagName('li');
function cbs(data){
    var data = JSON.parse(data);
    if (data.length > 0){
        data.forEach(function(ele, index){
            var oItem = document.createElement('div');
            oItem.className = 'item';
            var oImg = document.createElement('img');
            oImg.src = ele.imgSrc;
            //图片等宽230px,对图片做了缩放,计算缩放后的高度
            oImg.height = ele.height * 230 / ele.width;
            oItem.appendChild(oImg);
            //在最短列添加新加载的图片
            oLi[findShortest(oLi)].appendChild(oItem);
        })
        // 数据加载完成并插入后,才开放请求数据的权限
        flag = false;
    }else {
        alert('已无数据')
    }
    

}

/*
* 判断高度最短的列,返回列索引
* lis:所有li
* index:最短li的索引
*/
function findShortest(lis){
    var len = lis.length,
        min = lis[0].offsetHeight,
        index = 0;
    for (var i = 0; i < len; i++){
        var h = lis[i].offsetHeight;
        if (h < min){
            min = h;
            index = i
        }
    }
    return index;
}

//解决多次重复发送请求
window.onscroll = function(){
    var index = findShortest(oLi);
    var h = oLi[index].offsetHeight;
    var clientHeight = document.documentElement.clientHeight || document.body.clientHeight,
        scrollHeight = document.documentElement.scrollTop || document.body.scrollTop;
    console.log(clientHeight,scrollHeight,h);
    if (clientHeight + scrollHeight > h){
        send();
    }
}