百度图片的横向瀑布流是怎么实现的?

前端瀑布流是老生常谈的话题,一般都是固定宽度,新内容不停地追加到最短列,但是百度图片的瀑布流就不这么简单了。百度图片是固定高度,每一行图片宽度不定,但是都能恰好排满,而且调整屏幕大小时,图片整体高度都会跟着变,每一行的图片个数也会跟着变,厉害了,我的百度,研究半天,没看出门道。

阅读 7.2k
3 个回答

flex布局

<div>
    <img/>
    <img/>
    <img/>
    <img/>
<div>
div{            
        display: flex;/*显示模式设置为弹性盒子*/
        flex-wrap: wrap;/*进行强制换行*/
    }        
    div:after{            
        /*对最后一个伪元素进行最大限度伸缩*/            
        content: ' ';            
        flex-grow: 999999999999999999999999999999999999;        
    }        
    img{             
        height: 200px;/*高度*/            
        width: auto;            
        margin: 2px;            
        flex-grow: 1;/*进行按比例伸缩*/            
        object-fit: cover;/*进行裁切,并且图片按比例缩放*/        
    }

这种是不定高的瀑布流,把高度计算的逻辑换成宽度就能实现了
demo

            for(var i = 0; i < this.items.length; i++){
                if(i < colMaxNumber){
                    itemHeightArray[i] = this.items[i].offsetHeight + this.margin;
                    this.items[i].style.top = 0;
                    this.items[i].style.left = i * this.singleItemWidth + 'px';
                }else{
                    var minHeight = Math.min.apply(null, itemHeightArray);
                    var minHeightIndex = $.inArray(minHeight, itemHeightArray);

                    this.items[i].style.top = minHeight + 'px';
                    this.items[i].style.left = minHeightIndex * this.singleItemWidth + 'px';
                    itemHeightArray[minHeightIndex] += this.items[i].offsetHeight + this.margin;

                //    另一种方法
                // var innsertColumn = this.min(itemHeightArray);
                // //    当前要放置的元素的高度加上边距
                // var imgHeight = this.items[i].offsetHeight + this.margin;

                // this.items[i].style.top = itemHeightArray[innsertColumn] + 'px';
                // this.items[i].style.left = innsertColumn * this.singleItemWidth + 'px';
                // itemHeightArray[innsertColumn] += imgHeight;
                }    

            }

有完整代码请在谷歌浏览器中测试

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <link rel="stylesheet" type="text/css" href="index.css">
</head>
<body>
<div id="waterfall">
</div>
<script type="text/javascript" src="index.js"></script>
</body>
</html>
var img = null;//临时的图片对象
var box =document.getElementById("waterfall");//容器对象
var lastS=0; //上一次的scrollTop
var nowS=0;//现在的scrollTop
var delS=0;//scrollTop间隔
var sum=0;//用来测试一共加载了多少张图片

//用来计算什么时候适合加载图片
box.onscroll=function()
{
  nowS=box.scrollTop;
  delS=nowS-lastS;
  if(delS>=100){
    lastS=box.scrollTop;
    insertImg();
  }
}
function insertImg()
{
  img=new Image();
  //测试用的实际可以放你先要的图片地址
  img.src="imgs/"+Math.floor(Math.random()*13)+".jpg";
  img.onload=function(){
    box.appendChild(this);
    sum++
    console.log(sum);
    //用来判断停止加载的时机
    if(this.offsetTop<box.offsetHeight+box.scrollTop){
      insertImg();
    }
  }
}
insertImg();
*{
  margin: 0px;
  padding: 0px;
}
#waterfall{            
  display: flex;
  flex-wrap: wrap;
  width: 100%;
  height:600px;
  align-content:flex-start;
  overflow-y: scroll;
}        
#waterfall:after{                       
    content: ' ';            
    flex-grow: 999999999999999999999999999999999999;        
}        
#waterfall img{             
    height: 200px;           
    width: auto;            
    margin: 2px;            
    flex-grow: 1;            
    object-fit: cover;
    position: relative;       
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题