//
瀑布流
一、认识瀑布流
瀑布流,又称瀑布流式布局。最早采用此布局的网站是Pinterest,视觉效果表现为参差不齐的多栏布局,即多行等宽不等高的元素依次排列。瀑布流布局的具体效果如下图:
二、为什么要使用瀑布流
目前大多数网站采用的布局都是有规律的多列布局,即每列等宽,每行等高。而参差不齐的瀑布流式布局能给用户不一样的视觉冲击效果。另外瀑布流结合下拉刷新,上拉加载进行数据的懒加载等操作,对于用户的体验感也是非常好的。
瀑布流主要针对的是带图片网站的内容展示,对于大小不一的图片按照一定的规律排列。即对大小不一的图片,让其等比缩放的显示在页面中,可保证图片不失真,可以有效的提高用户体验。
三、瀑布流的图例分析
先用图片分析一下我们想要的瀑布流是什么样的
如下图所示,假设一排五列。第一排排满后,显示的是这样的。那么我们要放第6张图片的时候,应该放在什么位置呢?
按照正常逻辑,第六张应该是放在第一张图片下面,然后依次水平排列过去,如下图:
但这样下去可能会导致每列之间的高度差距越来越大,并不符合实际瀑布流效果要求,在瀑布流中,从第六张图片开始,接下去的每一张图片都应该放在高度最低的那一列图片下方。如下图:
即从第六张图片开始都需要计算哪一列的图片累计的高度最小,然后下一张图片就应该放在哪一列。
四、具体实现
HTML代码
加载中...
CSS代码
* {
margin: 0;
padding: 0;
}
.content {
width: 1240px;
margin: 0 auto;
position: relative;
}
.shop {
width: 240px;
border: 1px solid #f00;
box-sizing: border-box;
position: absolute;
}
.shop img {
width: 100%;
}
.shopName{
height: 60px;
}
.loadBox {
display: flex;
justify-content: center;
align-items: center;
padding: 10px;
color: gray;
font-size: 14px;
}
.loadBox img{
animation: load 0.8s infinite;
}
@keyframes load {
from{
transform: rotate(0);
}to{
transform: rotate(360deg);
}
}
JS代码
let data = [{
id: 1,
shopname: '图片1',
imgUrl:
"https://img1.baidu.com/it/u=709381787,3386403196&fm=253&fmt=auto&app=138&f=JPEG?w=599&h=500"
}, {
id: 2,
shopname: '图片2',
imgUrl: "https://img0.baidu.com/it/u=1489670366,411382419&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=753"
}, {
id: 3,
shopname: '图片3',
imgUrl: "https://img1.baidu.com/it/u=3255035444,3515309779&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=666"
}, {
id: 4,
shopname: '图片4',
imgUrl: "https://img2.baidu.com/it/u=3173263148,4118504965&fm=253&fmt=auto&app=138&f=JPEG?w=620&h=500"
}, {
id: 5,
shopname: '图片5',
imgUrl: "https://img0.baidu.com/it/u=2628882850,1202220801&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=498"
}, {
id: 6,
shopname: '图片6',
imgUrl: "https://img1.baidu.com/it/u=740708162,4263244726&fm=253&fmt=auto&app=120&f=JPEG?w=1280&h=800"
}, {
id: 7,
shopname: '图片7',
imgUrl: "https://img1.baidu.com/it/u=701043886,582191677&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500"
}, {
id: 8,
shopname: '图片8',
imgUrl: "https://img0.baidu.com/it/u=3878848433,891453978&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=667"
}, {
id: 9,
shopname: '图片9',
imgUrl: "https://img1.baidu.com/it/u=1621477098,3345707124&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=771"
}, {
id: 10,
shopname: '图片10',
imgUrl: "https://img1.baidu.com/it/u=2062807354,75688956&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500"
}, {
id: 11,
shopname: '图片11',
imgUrl: "https://img2.baidu.com/it/u=1190852256,1138303662&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=375"
}, {
id: 12,
shopname: '图片12',
imgUrl: "https://img0.baidu.com/it/u=2280903142,1037129928&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500"
}, {
id: 13,
shopname: '图片13',
imgUrl: "https://img0.baidu.com/it/u=1911023561,1873370868&fm=253&fmt=auto&app=138&f=JPEG?w=282&h=500"
}, {
id: 14,
shopname: '图片14',
imgUrl: "https://img0.baidu.com/it/u=1303056880,3446954677&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=667"
}, {
id: 15,
shopname: '图片15',
imgUrl: "https://img0.baidu.com/it/u=2463246409,2913214612&fm=253&fmt=auto&app=138&f=JPEG?w=750&h=500"
}, {
id: 16,
shopname: '图片16',
imgUrl: "https://img1.baidu.com/it/u=673572676,3486461689&fm=253&fmt=auto&app=138&f=JPEG?w=667&h=500"
}, {
id: 17,
shopname: '图片17',
imgUrl: "https://img0.baidu.com/it/u=1118388590,847334752&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500"
}, {
id: 18,
shopname: '图片18',
imgUrl: "https://img2.baidu.com/it/u=1392060445,3405288279&fm=253&fmt=auto&app=138&f=JPEG?w=300&h=500"
}];
let content = document.querySelector('.content');
function getData() {
return new Promise((resolve, reject) => {
setInterval(() => {
resolve(data);
}, 600);//假设发起网络请求数据需要600ms
});
}
let colHeight = [];//用于存储每一列的高度
let lastShop = null;//用于存储最后放入content的div
async function showData(isScroll=false) {
let r = await getData();
let shopBox = document.createDocumentFragment();
r.forEach((item, index) => {
// 创建图片
let img = new Image();
img.src = item.imgUrl;
let imgInfo = item.imgUrl.split("?")[1].split("&");
/*
imgHeight imgWidth:240
imgInfo[1].split("=")[1] imgInfo[0].split("=")[1]
*/
let imgHeight = imgInfo[1].split("=")[1]*240/imgInfo[0].split("=")[1];
img.style.height = imgHeight + 'px';
// 创建图片div
let shopdiv = document.createElement('div');
shopdiv.classList.add('shop');
// 创建放图片名字的div
let shopNameDiv = document.createElement('div');
shopNameDiv.classList.add('shopName');
shopNameDiv.innerHTML = item.shopname;
let left;
let top = 0;
if(index<=4&&!isScroll){
colHeight.push(imgHeight+60+2+10);//第一行:图片高度+文字div高度60+上下边框2+底部间距10
// 计算放每个图片的div的left值
left = (240 + 12) * (index % 5);
}else{
//需要每次计算找到最低的一列
let minColH = Math.min(...colHeight);//最低一列的高度
let minCol = colHeight.indexOf(minColH);//找出最低的是第几列
// console.log(minCol,minColH);
// 计算放每个图片的div的left值
left = (240 + 12) * minCol;
// 计算放每个图片的div的top值
top = minColH;
// 改变每一列的高度
colHeight[minCol] += imgHeight+60+2+10;//imgHeight+60+2+10: 图片高度+文字div高度60+上下边框2+底部间距10
}
shopdiv.style.top = top + 'px';
shopdiv.style.left = left + 'px';
shopdiv.append(img);
shopdiv.append(shopNameDiv);
shopBox.append(shopdiv);
if(index == r.length-1){//判断是否是最后一条数据
lastShop = shopdiv;
}
});
content.append(shopBox);
}
showData();
let flag = false;//用于判断触底加载数据是否加载完成
window.onscroll = async function () {//监听滚动条滚动
if (lastShop.getBoundingClientRect().y < window.innerHeight+500 && flag == false) {//触底加载新数据
flag = true;//正在加载
await showData(true);
flag = false;//加载完成
}
}
最终效果图如下:
Copyright © 2004-2024 华清远见教育科技集团 版权所有
京ICP备16055225号-5,京公海网安备11010802025203号