跳到主要内容

案例02:瀑布流图片

我们有时候逛网站的时候,有的图片网站的图片排列在纵向上是错落有致的,并不是高度统一的,如下图,这个效果是怎么做的呢?(下图是我截取花瓣网站的图片)

解决思路:

解决的思路就是先确定显示的列数,每一列都是一个li标签,然后图片是一张一张生成放上去的,在放上去的时候,判断四列中哪一个的高度最矮,然后在最矮的位置的li中插入图片,就这样一张一张插入,直到插入所有的图片,就显示这样的瀑布流。

代码:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
*{margin: 0;padding: 0;}
ul{list-style: none;}
li{float: left;margin-left: 5px}

</style>
</head>
<body>
<script>
const COL=4;
// 存储li的数组
var arr=[];
// 最小高度数值列表
var minHeightList=[];
// 初始化函数执行
init();
/*
* 初始化函数
* 1、创建ul,并且放在body中
* 2、根据常数COL创建若干个li,这里循环COL次
* 3、创建li并且将li放在ul中,设置每个li的宽度
* 4、将创建好的li放在数组中
* 5、给最小高度数组放置数据0,也就是最小高度都是从0开始
* 6、加载图片
* */
function init() {
var ul=document.createElement("ul");
document.body.appendChild(ul);
for(var i=0;i<COL;i++){
var li=document.createElement("li");
ul.appendChild(li);
li.style.width=document.documentElement.clientWidth/COL-10+"px";
arr.push(li);
minHeightList.push(0);
}
loadImg();
}

/*
*
* 加载图片函数
* 1、新建一个图片
* 2、设置图片的num属性是2
* 3、给这个图片增加load事件侦听,加载图片后执行loadHandler函数
* 4、设置图片的地址是2-.jpg(我们所有图片都是2-,3-,4-这样的)
* */
function loadImg() {
var img=new Image();
img.num=2;
img.addEventListener("load",loadHandler);
img.src="img/"+img.num+"-.jpg";
}

/*
* 加载图片后执行的事件函数
* 1、求出最小高度数组中最小的值
* 2、求出这个最小值在数组中的下标
* 3、浅复制当前加载图片,并且设置这个图片的宽度
* 4、将图片放在和最小高度数组对应下标的li中
* 5、将这个图片的高度累加到最小高度数组对应的数值上
* 6、累加num值
* 7、判断num是否大于79,如果大于79删除事件加载侦听,并且标识加载完成
* 8、设置继续加载num所对应的图片
*
* */
function loadHandler(e) {
var min=Math.min.apply(null,minHeightList);
var index=minHeightList.indexOf(min);
var image=this.cloneNode(false);
image.style.width=document.documentElement.clientWidth/COL-10+"px";
arr[index].appendChild(image);
minHeightList[index]+=image.offsetHeight;
this.num++;
if(this.num>79){
this.removeEventListener("load",loadHandler);
console.log("加载完成");
return;
}
this.src="img/"+this.num+"-.jpg";
}

</script>
</body>
</html>

其中 loadHandler 中使用了浅拷贝,主要是不想在新创建一个img时要拷贝以前的src,num,事件等,因为都是一样的,所以直接浅拷贝就行。其实和下面方法等同(我其中有用jQuery的语法):

在这里使用浅拷贝和深拷贝是一样的,因为这里img元素没有子元素。

DOM的浅拷贝和深拷贝的区别是:是否拷贝元素里面的子元素。

而jQuery的浅拷贝就相当于DOM的深拷贝,jQuery的深拷贝是将拷贝的元素的事件都拷贝下来。

function loadHandler() {
let min = Math.min.apply(null, minHeight);
let minIndex = minHeight.indexOf(min);

arr[minIndex].append(this);
minHeight[minIndex] += this.getBoundingClientRect().height;
// // let im = this.cloneNode(false);
let im = new Image();
im.src = this.src;
im.num = this.num;
$(im).css("width", "100%");
$(im).on("load", loadHandler);

im.num++;

if (this.num > 78) {
$(im).off("load", loadHandler);
return;
}
im.src = `../images/img/${im.num}-.jpg`;

arr[minIndex].append(im);
minHeight[minIndex] += im.getBoundingClientRect().height;
}

最后的效果就是这样: