JS实现瀑布流布局(附代码)
你可以准备一些长宽都不相等的图片。瀑布流特点等宽不等高为了让最后一行的差距最小,从第二行开始,需要将图片放在第一行最矮的图片下面实现思路设定每一列图片的宽度和间距获取当前窗口的总宽度,从而根据图片宽度去判断分为几列获取所有图片元素,定义一个空数组来保存高度遍历容器4.1 第一排,top固定 为gap;left 根据列数递增 为 (itemWidth+gap)i + gap4.2 非第一批, top
·
你可以准备一些长宽都不相等的图片。
瀑布流特点
- 等宽不等高
- 为了让最后一行的差距最小,从第二行开始,需要将图片放在第一行最矮的图片下面
实现思路
- 设定每一列图片的宽度和间距
- 获取当前窗口的总宽度,从而根据图片宽度去判断分为几列
- 获取所有图片元素,定义一个空数组来保存高度
- 遍历容器
4.1 第一排,top固定 为gap;left 根据列数递增 为 (itemWidth+gap)i + gap
4.2 非第一批, top( minHeight+gap2) left的计算方式和4.1一样,其中i的位置是minHeight所在的列数 - 调用
function waterFall(){
const minGap = 20 // 粗略设定一个你想要的最小间距
const itemWidth = 300 // 定义每一项的宽度(保证等宽)
const scrollBarWidth = getScrollbarWidth(); //获取滚动条宽度
const pageWidth = window.innerWidth - scrollBarWidth; // 获取当前页面的宽度
// 实际列数= 页面宽度/(图片宽度+最小间距)
const column - Math.floor(pageWidth/(itemWidth+minGap))
//计算真实间距
const gap = (pageWidth - itemWidth*column) / column / 2;
const items = document.querySelectorAll("img")
const heightArr = [] // 定义一个空数组,保存最低高度
//便利所有的外层容器
for(let i = 0; i < items.length; i++){
const height = items[i].offsetHeight;
if(i < column){
// 索引i小于列数,当前为第一行;直接设置元素距离上一个左边距
items[i].style.cssText = `top: ${gap}px; left: ${(itemWidth + gap) * i + gap}px`;
// 保存当前元素的高度
heightArr.push(height)
}else{
// 不是第一行,进行比对
let minHeight = heightArr[0]
let minIndex = 0
for(let j = 0; j < heightArr.length; j++){
// 通过循环遍历比对,拿到最小值和最小值的索引
if(minHeight > heightArr[j]){
minHeight = heightArr[j]
minIndex = j
}
}
items[i].style.cssText = `top:${minHeight+gap*2}px; left: ${(itemWidth+gap)*minIndex + gap}px`
heightArr[minIndex] = minHeight + gap + height
}
}
}
// 获取滚动条宽度
function getScrollbarWidth(){
const oDiv = document.createElement('div')
oDiv.style.cssTex = `width:50px; height:50px; overflow:scroll;`
document.body.appendChild(oDiv) // 把div添加到body中
const scrollbarWidth = oDiv.offsetWidth - oDiv.clientWidth; // 使最大宽度和可视宽度相减,获得滚动条宽度
oDiv.remove();// 移出创建的div
return scrollbarWidth; // 返回滚动条宽度
}
window.onload = waterFall
window.onresize = waterFall;
完整代码
<!DOCTYPE html>
<html>
<head>
<style>
.box {
width: 100%;
height: 100%;
position:relative;
}
.item img{
position: absolute;
width: 300px;
}
</style>
</head>
<body>
<div class="box" style="border: 10px red solid;">
<div class="item">
<img src="1.jpeg" alt="" />
</div>
<div class="item" style="border: 1px red solid;">
<img src="2.jpeg" alt="" />
</div>
<div class="item">
<img src="3.jpeg" alt="" />
</div>
<div class="item">
<img src="4.jpeg" alt="" />
</div>
<div class="item">
<img src="5.jpeg" alt="" />
</div>
<div class="item">
<img src="6.jpeg" alt="" />
</div>
<div class="item">
<img src="7.jpeg" alt="" />
</div>
<div class="item">
<img src="8.jpeg" alt="" />
</div>
<div class="item">
<img src="9.jpeg" alt="" />
</div>
<div class="item">
<img src="10.jpeg" alt="" />
</div>
<div class="item">
<img src="11.jpeg" alt="" />
</div>
</div>
</body>
1 <script type="text/javascript">
// 定义瀑布流算法函数
function fall() {
const minGap = 10; // 最小间距,让每一列的最小空隙可以自定义,避免太过拥挤的情况发生。但是,会通过计算得到真实的间距。
const itemWidth = 300; // 每一项的宽度,即当前每一个图片容器的宽度。保证每一列都是等宽不等高的。
const scrollBarWidth = getScrollbarWidth(); // 获取滚动条的宽度
console.log("##############3",scrollBarWidth);
const pageWidth = window.innerWidth - scrollBarWidth; // 获取当前页面的宽度 = window.innerWidth - 滚动条的宽度
const column = Math.floor(pageWidth / (itemWidth + minGap)); // 实际列数=页面宽度/(图片宽度+最小间距)
const gap = (pageWidth - itemWidth * column) / column/2; // 计算真实间距 = (页面宽度- 图片宽度*实际列数)/实际列数/2
const items = document.querySelectorAll('img'); // 获取所有的外层元素
const heightArr = []; // 定义一个空数组,保存最低高度。
// 获取滚动条的宽度
function getScrollbarWidth() {
const oDiv = document.createElement('div');//创建一个div
// 给div设置样式。随便定义宽高,只要能获取到滚动条就可以
oDiv.style.cssText = `width: 50px;height: 50px;overflow: scroll;`
document.body.appendChild(oDiv);//把div添加到body中
const scrollbarWidth = oDiv.offsetWidth - oDiv.clientWidth;// 使最大宽度和可视宽度相减,获得到滚动条宽度。
oDiv.remove();//移除创建的div
return scrollbarWidth;//返回滚动条宽度
}
for (let i = 0; i < items.length; i++) {
// 遍历所有的外层容器
const height = items[i].offsetHeight;
// 如果当前处在第一行
if (i < column) {
// 直接设置元素距离上部的位置和距离左边的距离。
items[i].style.cssText = `top: ${gap}px;left: ${(itemWidth + gap) * i + gap}px`;
// 保存当前元素的高度。
heightArr.push(height);
} else {
// 不是第一行的话,就进行比对。
let minHeight = heightArr[0]; // 先保存第一项的高度
let minIndex = 0; // 保存第一项的索引值
for (let j = 0; j < heightArr.length; j++) {
// 通过循环遍历比对,拿到最小值和最小值的索引。
if (minHeight > heightArr[j]) {
minHeight = heightArr[j];
minIndex = j;
}
}
// 通过最小值为当前元素设置top值,通过索引为当前元素设置left值。
items[i].style.cssText = `top: ${minHeight + gap *2}px; left: ${(itemWidth + gap) * minIndex + gap}px`;
// 并修改当前索引的高度为当前元素的高度
heightArr[minIndex] = minHeight + gap + height;
}
}
}
// 页面加载完成调用一次。
window.onload = fall;
// 页面尺寸发生改变再次调用。
window.onresize = fall;
</script>
</html>
参考
关于瀑布流的布局原理…
更多推荐
已为社区贡献1条内容
所有评论(0)