纯JS实现瀑布流布局与动态加载详解
本文详细解析如何使用纯JavaScript实现瀑布流布局,涵盖初始化定位、滚动监听及动态加载新数据的核心逻辑。通过计算列高最小值实现图片自动排列,并结合模拟Ajax请求实现滚动到底部时自动追加内容,解决非响应式及重定位性能问题。
纯JS瀑布流布局与动态加载概述
本文介绍如何使用纯JavaScript代码构建一个瀑布流网页效果,初步实现基础的瀑布流布局,并演示在滚动至底部时模拟Ajax加载新图片的功能。
方案局限性分析
该方案存在以下局限性:
1. 程序不具备响应式特性,无法根据页面宽度变化实时调整布局;
2. 在通过Ajax模拟加载新数据图片后,程序会对页面内所有图片重新执行一次定位计算;
3. 程序逻辑要求等待所有图片加载完成后才读取尺寸,这在真实场景中并不适用;
4. 在实际项目中,建议由后端接口直接提供图片尺寸数据,前端JS代码直接读取图片的width属性即可。
本程序的核心实现思路如下:
HTML结构部分:
HTML结构与初始化布局实现
<body>
<div id="container">
<div class="box">
<div class="box_img">
<img src="img/1.jpg" />
</div>
</div>
<div class="box">
<div class="box_img">
<img src="img/2.jpg" />
</div>
</div>
...
</div>
</body>
一、初始化布局逻辑
1. 将#container元素设置为position:relative;;
2. 将.box元素设置为float:left;;
3. 页面加载完成后,对所有图片执行定位操作;
3.1 由于图片宽度固定,需计算当前页面每行能容纳的图片数量num,进而确定#container的宽度并实现页面居中;
3.2 遍历所有图片,前num个图片保持默认float布局作为第一行,并将它们的高度存入数组BoxHeightArr = [];;
3.3 第一行布局完成后,开始排列后续图片,并同步更新BoxHeightArr[]:
3.3.1 将下一张放置到第一行中最矮图片的下方(采用position:absolute定位),即找到BoxHeightArr[]中高度最小值对应的列索引minIndex;
3.3.2 更新BoxHeightArr[]中该最小值,即BoxHeightArr[minIndex]加上当前新图片的高度;
3.4 循环执行3.3步骤,直至所有图片排列完毕。
滚动监听与数据加载机制
二、实时监测滚动高度以触发数据加载
1. 初始化完成后,计算最后一个图片距离页面顶部的总高度:lastContentHeight;
2. 绑定window.onscroll = function(){...}事件;
实时获取当前页面的滚动高度scrollTop;
实时获取当前页面视窗高度pageHeight;
3. 当监测到条件:lastContentHeight < scrollTop + pageHeight 成立时,发起Ajax请求获取新增图片的JSON数据。
动态内容追加与重定位处理
三、页面底部新增内容处理
1. 通过循环创建新的图片容器并添加至页面底部,将JSON数据中的图片路径等信息写入容器以完成图片添加;
2. 所有新增图片添加完毕后,对整个页面的所有图片及布局重新执行步骤一的初始化定位操作。
项目文件结构与代码示例
项目文件结构:

index.html: 预先置入部分初始图片数据
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="css/style.css"/>
<script src="js/app.js"></script>
<title>JavaScript瀑布流</title>
</head>
<body>
<div id="container">
<div class="box">
<div class="box_img">
<img src="img/1.jpg"/>
</div>
</div>
<div class="box">
<div class="box_img">
<img src="img/2.jpg"/>
</div>
</div>
<div class="box">
<div class="box_img">
<img src="img/3.jpg"/>
</div>
</div>
<div class="box">
<div class="box_img">
<img src="img/4.jpg"/>
</div>
</div>
<div class="box">
<div class="box_img">
<img src="img/5.jpg"/>
</div>
</div>
<div class="box">
<div class="box_img">
<img src="img/6.jpg"/>
</div>
</div>
<div class="box">
<div class="box_img">
<img src="img/7.jpg"/>
</div>
</div>
<div class="box">
<div class="box_img">
<img src="img/8.jpg"/>
</div>
</div>
<div class="box">
<div class="box_img">
<img src="img/9.jpg"/>
</div>
</div>
<div class="box">
<div class="box_img">
<img src="img/10.jpg"/>
</div>
</div>
<div class="box">
<div class="box_img">
<img src="img/1.jpg"/>
</div>
</div>
<div class="box">
<div class="box_img">
<img src="img/2.jpg"/>
</div>
</div>
<div class="box">
<div class="box_img">
<img src="img/3.jpg"/>
</div>
</div>
<div class="box">
<div class="box_img">
<img src="img/4.jpg"/>
</div>
</div>
<div class="box">
<div class="box_img">
<img src="img/5.jpg"/>
</div>
</div>
<div class="box">
<div class="box_img">
<img src="img/6.jpg"/>
</div>
</div>
<div class="box">
<div class="box_img">
<img src="img/7.jpg"/>
</div>
</div>
<div class="box">
<div class="box_img">
<img src="img/8.jpg"/>
</div>
</div>
<div class="box">
<div class="box_img">
<img src="img/9.jpg"/>
</div>
</div>
<div class="box">
<div class="box_img">
<img src="img/10.jpg"/>
</div>
</div>
<div class="box">
<div class="box_img">
<img src="img/1.jpg"/>
</div>
</div>
<div class="box">
<div class="box_img">
<img src="img/2.jpg"/>
</div>
</div>
<div class="box">
<div class="box_img">
<img src="img/3.jpg"/>
</div>
</div>
<div class="box">
<div class="box_img">
<img src="img/4.jpg"/>
</div>
</div>
<div class="box">
<div class="box_img">
<img src="img/5.jpg"/>
</div>
</div>
<div class="box">
<div class="box_img">
<img src="img/6.jpg"/>
</div>
</div>
<div class="box">
<div class="box_img">
<img src="img/7.jpg"/>
</div>
</div>
<div class="box">
<div class="box_img">
<img src="img/8.jpg"/>
</div>
</div>
<div class="box">
<div class="box_img">
<img src="img/9.jpg"/>
</div>
</div>
<div class="box">
<div class="box_img">
<img src="img/9.jpg"/>
</div>
</div>
<div class="box">
<div class="box_img">
<img src="img/10.jpg"/>
</div>
</div>
</div>
</body>
</html>
style.css:
*{
margin: 0;
padding: 0;
}
#container{
position: relative;
}
.box{
padding: 5px;
float: left;
}
.box_img{
padding: 5px;
border: 1px solid #ccc;
box-shadow: 0 0 5px #ccc;
border-radius: 5px;
}
.box_img img{
width: 150px;
height: auto;
}
app.js:
window.onload = function(){
imgLocation("container", "box");
//ajax模拟数据
var imgData = {"data":[{"src":"2.jpg"},{"src":"3.jpg"},{"src":"4.jpg"},{"src":"5.jpg"},{"src":"6.jpg"},{"src":"8.jpg"},{"src":"2.jpg"},{"src":"3.jpg"},{"src":"4.jpg"},{"src":"5.jpg"},{"src":"6.jpg"},{"src":"8.jpg"}]}
window.onscroll = function(){
if(checkFlag()){ //判断是否到底部要加载新的数据
var cparent = document.getElementById("container");
//把ajax数据加载进页面
for(var i=0; i<imgData.data.length; i++){
var ccontent = document.createElement("div");
ccontent.className="box";
cparent.appendChild(ccontent);
var boximg = document.createElement("div");
boximg.className = "box_img";
ccontent.appendChild(boximg);
var img = document.createElement("img");
img.src = "img/"+imgData.data[i].src;
boximg.appendChild(img);
}
//把所有图片数据重新定位一次
imgLocation("container", "box");
}
}
};
function checkFlag(){
var cparent = document.getElementById("container");
var ccontent = getChildElement(cparent, "box");
//得到最后一张图距顶部的高度,滚动高度,窗口高度
var lastContentHeight = ccontent[ccontent.length-1].offsetTop;
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
var pageHeight = document.documentElement.clientHeight || document.body.clientHeight;
console.log(lastContentHeight+":"+scrollTop+":"+pageHeight);
if(lastContentHeight < scrollTop + pageHeight){
return true;
}
}
function imgLocation(parent, content){
//将parent下所有的content全部取出
var cparent = document.getElementById(parent);
var ccontent = getChildElement(cparent, content);
//根据当前浏览器窗口的宽度,确定每行图片数并固定,居中
var imgWidth = ccontent[0].offsetWidth; //offsetWidth = width + padding + border
var num = Math.floor(document.documentElement.clientWidth / imgWidth);
cparent.style.cssText = "width:"+imgWidth*num+"px;margin:0 auto";
//alert("pause");
//设置一个数组,用来承载第一行的图片信息
var BoxHeightArr = [];
for(var i=0; i<ccontent.length; i++){
if(i<num){
//第一行的图片的高度记录下来
BoxHeightArr[i] = ccontent[i].offsetHeight;
//当ajax数据加载后,程序是将所有图片重新定位,所以第一行的图片要清除position:absolute
ccontent[i].style.position = "static";
}else{
var minHeight = Math.min.apply(null, BoxHeightArr);
var minIndex = getminheightLocation(BoxHeightArr, minHeight);
//把图放在第一行图索引值最小的下面
ccontent[i].style.position = "absolute";
ccontent[i].style.top = minHeight+"px";
ccontent[i].style.left = ccontent[minIndex].offsetLeft+"px";
//图片放好位置后更新“第一行图片信息的最小高度”,
//然后利用for循环重复这个动作到结束
BoxHeightArr[minIndex] = BoxHeightArr[minIndex] + ccontent[i].offsetHeight;
}
}
;}
//获取第一行图片高度最小的索引值
function getminheightLocation(BoxHeightArr, minHeight){
for(var i in BoxHeightArr){
if(BoxHeightArr[i] == minHeight){
return i;
}
}
}
//获取所有box
function getChildElement(parent, content){
contentArr = parent.getElementsByClassName(content);
return contentArr;
}
效果图展示:

以上就是本文的全部内容,希望对大家学习javascript程序设计有所帮助。
D3.js 比例尺与坐标轴的配置详解
2026-11-05 16:54:46
JavaScript怎么遍历对象的Symbol键和不可枚举属性
2026-11-05 13:13:39
封装一个健壮的JS字符串判空工具函数
2026-11-05 12:16:14
JavaScript合并数组的三种常用方法:concat、扩展运算符与push
2026-11-05 11:22:29
JavaScript立即执行函数(IIFE)是什么及基本语法
2026-11-05 10:51:19
