重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
每列的宽度相等而高度不等,且第二行的第一个容器需要放在第一行高度最小的容器下面,依次类推放置。
目前创新互联已为成百上千家的企业提供了网站建设、域名、网络空间、网站运营、企业网站设计、泰州网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。
代码仅实现了瀑布流的布局方式和 resize 监听,如果大家有需要,可以自己拓展下:实现监听滚动事件,页面滚动加载图片的功能。
代码中写了详细注释,可以直接使用。
DOCTYPE html>
<htmllang="en">
<head>
<metacharset="UTF-8" />
<metahttp-equiv="X-UA-Compatible" content="IE=edge" />
<metaname="viewport" content="width=device-width, initial-scale=1.0" />
<title>瀑布流布局JS实现title>
head>
<body>
<style>
*{
margin: 0;
padding: 0;
}
body{
width: 100vw;
height: 100vh;
}
.container{
width: 100vw;
height: 100vh;
overflow: scroll;
position: relative;
background-color: lightgray;
}
.item{
width: 200px;
height: auto;
box-sizing: border-box;
background: #fff;
border: 1px solid #000;
border-radius: 15px;
text-align: center;
font-size: 40px;
font-weight: bold;
position: absolute;
top: 0;
left: 0;
}
.item1,
.item8{
height: 300px;
}
.item2,
.item6{
height: 150px;
}
.item3,
.item9{
height: 120px;
}
.item4,
.item10{
height: 270px;
}
.item5,
.item7{
height: 350px;
}
style>
<divclass="container">
<divclass="item item1">1div>
<divclass="item item2">2div>
<divclass="item item3">3div>
<divclass="item item4">4div>
<divclass="item item5">5div>
<divclass="item item6">6div>
<divclass="item item7">7div>
<divclass="item item8">8div>
<divclass="item item9">9div>
<divclass="item item10">10div>
div>
<script>
function waterFullLayout() {
console.log("start");
// 获取页面宽度
let pageWidth=
document.getElementsByClassName("container")[0].clientWidth;
// 获取图片固定的宽度
let itemWidth= document.getElementsByClassName("item")[0].offsetWidth;
// 设置图片之间间距
let gap= 10;
// 获取一行最多可以展示几张图片
let nums= Math.floor(pageWidth/ (itemWidth+ gap));
// 瀑布流实现原则:
// 所有图片元素绝对定位,从第二行开始,依次从第一行图片元素高度最小的下方填充,这里注意,不是从左至右填充,即优先填补空位,填补一个后,再填补下一个较大的空位
// 定义第一行图片的所有高度的数组,之后每张图片下方填充图片后,会更新数组对应位置下的最小高度
let heightList= [];
let itemArr= document.getElementsByClassName("item");
let imgLen= itemArr.length;
for (let i= 0; i< imgLen; i++) {
// 如果 当前图片元素索引小于一行最多可以展示的图片个数,说明是第一行,top 已在css中默认设置为0,需要统一设置 left 值,top值如果加gap,则还需设置gap值
if (i< nums) {
// 将第一行的图片元素的高度放入 heightList 数组
heightList.push(itemArr[i].offsetHeight+ gap);
itemArr[i].style.top= gap+ "px";
itemArr[i].style.left= (itemWidth+ gap)* i+ "px";
}else {
// 否则从第二行开始,要根据第一行图片元素的高度,设置top和left
// 先假设 heightList[0] 为最小高度
let minItem= {
minHeight: heightList[0],
minIndex:0,
};
for (let j= 0; j< heightList.length; j++) {
if (heightList[j]< minItem["minHeight"]) {
minItem["minHeight"]= heightList[j];
minItem["minIndex"]= j;
}
}
itemArr[i].style.top= minItem["minHeight"]+ gap+ "px";
itemArr[i].style.left=
(itemWidth+ gap)* minItem["minIndex"]+ "px";
// 关键步骤,更新 heightList 中对应位置下整列图片的高度,以便在下次循环时根据heightList 重新寻找最小高度
heightList[minItem["minIndex"]]=
parseFloat(itemArr[i].style.top)+
parseFloat(itemArr[i].offsetHeight);
}
}
}
// 防抖
function debounce(fn, delay) {
let timer= null;
return function () {
if (timer) {
clearTimeout(timer);
}
timer= setTimeout(()=> {
fn.apply(this, arguments);
}, delay);
};
}
window.onload= function () {
// 为了保证页面宽度可以正常获取,onload 之后再执行
waterFullLayout();
};
// 页面宽度变化要重新布局
window.onresize= debounce(waterFullLayout,100);
script>
body>
html>