整理了一下當時學js寫的一些案例,再次體驗了一把用原生JS實現動態瀑布流效果的樂趣,現在把它整理出來,需要的小夥伴可以參考一下。
該案例主要是用HTML+CSS控制樣式,通過JS實現全域性瀑布流以及點選圖片放大、上下切換效果。HTML佈局寫的很簡單,圖片載入主要是在JS中通過訪問自定義的JSON字串來實現。
動態瀑布流的原理簡單理解就是把新需要載入的圖片放在上一排總高度最小的圖片或模組下面,實現參差不齊的多欄佈局效果。
具體效果如下:
![image.png](https://upload-images.jianshu.io/upload_images/17943987-baddff77d2a79c20.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![image.png](https://upload-images.jianshu.io/upload_images/17943987-7f1644f70ddf3b2b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![image.png](https://upload-images.jianshu.io/upload_images/17943987-07e43078e88778de.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![image.png](https://upload-images.jianshu.io/upload_images/17943987-596fa06235983296.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
做這個案例我用了之前自己封裝的框架,所以小夥伴需要到我的另一篇文章裡面自己下載,連結:https://www.jianshu.com/p/e88e15ceabf3
**HTML程式碼:**
```
<template id="temp">
<div>
<figure>
<img src="{{img}}">
<p>{{info}}</p>
</figure>
</div>
</template>
<template id="temp1">
<img src="{{src}}">
<p>{{info}}</p>
<aside>
<a href="##" class="prev">上一張</a>
<a href="##" class="next">下一張</a>
</aside>
</template>
<section id="box" class="box"></section>
<div id="show_big" class="show_big">
<img src="images/w_1.jpg">
<p id="txt">這是詳細內容</p>
<aside>
<a href="##" class="pre">上一張</a>
<a href="##" class="next">下一張</a>
</aside>
</div>
<div class="mask" id="mask"></div>
<span id="show" class="show"></span>
```
**css程式碼:**
```
*{
margin: 0;
padding: 0;
}
section.box{
margin: 0 auto;
position: relative;
font-size: 0;//行塊取消間距
}
section.box div{
width: 200px;
padding: 14px 7px 0;
box-sizing: border-box;
/*float: left;*/
display: inline-block;
vertical-align: top;
}
section.box div figure{
border: 1px #cccccc solid;
border-radius: 4px;
padding: 10px;
box-shadow: 0 0 3px 1px rgba(0,0,0,.1);
}
section.box div figure img{
width: 100%;
}
section.box div figure p{
font-size: 16px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
span.show{
position: fixed;
bottom: 0;
}
div.show_big{
background-color: #f2f2f2;
border-radius: 4px;
position: fixed;
padding: 10px;
top: 50px;
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.5);
display: none;
z-index: 100;
}
div.mask{
content: '';
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(101, 101, 101, 0.28);
display: none;
}
div.show_big img{
border-radius: 3px;
}
div.show_big p{
font-size: 13px;
color: #666666;
text-indent: 2em;
line-height: 17px;
margin-bottom: 10px;
overflow : hidden;/*多行文字省略號*/
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
div.show_big aside{
display: flex;
justify-content: space-around;
}
div.show_big a{
display: inline-block;
padding: 5px 13px;
background-color: #318fff;
color: white;
line-height: 17px;
text-decoration: none;
border-radius: 2px;
}
```
**JS程式碼:**
```
var data=[
{src:'images/w_1.jpg',info:'描述內容描述內容描述內容描述內容描述內容描述內容描述內容描述內容描述內容描述內容描述內容描述內容描述內容描述內容描述內容描述內容描述內容描述內容'},
{src:'images/w_2.jpg',info:'描述內容'},
{src:'images/w_3.jpg',info:'描述內容'},
{src:'images/w_4.jpg',info:'描述內容'},
{src:'images/w_5.jpg',info:'描述內容'}
];
var data1=[
{src:'images/w_4.jpg',info:'描述內容'},
{src:'images/w_5.jpg',info:'描述內容'},
{src:'images/w_6.jpg',info:'描述內容'}
];
var json={data,data1};//這裡是圖片資料
var img_w=200;
var len;
var box=sEO.$('#box');
resize();
function resize() {
//len:每排顯示的圖片數目
len=parseInt((window.innerWidth-17)/img_w);
box.style.width=len*img_w+'px';//瀑布流總的寬度
}
var temp=sEO.$('#temp').innerHTML;
function load_img(arr) { //動態新增圖片
var str='';
arr.forEach(function (el,i) {
str+=temp.replace('{{img}}',el.src).replace('{{info}}',el.info);
});
box.innerHTML+=str;
}
load_img(data);//自動載入圖片帶HTML中
var divs=sEO.$('#box div');
function isComplete(els,fun) {//判斷圖片是否全部載入完成,完成之後才執行回撥函式fun
var flag=true;//設定一個標誌,flag=true表示所有圖片載入完成
els.forEach(function (div,i) {
var img=div.getElementsByTagName('img')[0];
if (!img.complete)flag=false;//表示存在圖片載入未完成
return false;
});
if (flag)fun();
}
function water(oarr) {//瀑布流具體實現
var arr=[];
var timer=setInterval(function () {
isComplete(oarr,function () {
clearInterval(timer);
oarr.forEach(function (div, i) {
if (i<len){
arr.push(div.offsetHeight);//把第一排div的高儲存起來
}else {//通過div的left和top決定div的位置
var min_h=Math.min.apply(null,arr);//求上一排總高度的最小值
var index=arr.indexOf(min_h);//求最小高度那一列的下標
div.style.cssText=`position: absolute;left: ${index*img_w}px;top: ${arr[index]}px;`;
arr[index]+=div.offsetHeight;//儲存的當前新增圖片的那一列的高度改變
}
})
})
},100);
}
water(divs);
var j_len=json.length,j=1;
var show=sEO.$('#show');
window.onscroll=function () {
var div_e=divs[divs.length-1];
var h=div_e.offsetHeight;
var top=div_e.offsetTop;
if (sEO.getScroll(document).top+window.innerHeight>h/2+top){
if (j<j_len){ //當最後半屏圖片即將顯示完時
load_img(data1); //動態新增資料
divs=sEO.$('#box div');
water(divs);
j++;
}else {//當導航條滑動到最後時提示,頁面到底
show.innerText='我是有底線的噢';
show.style.left=(window.innerWidth-show.offsetWidth)/2+'px';
}
}else {
show.innerText='';
}
};
divs=sEO.$('#box div');
window.onresize=function () {//瀏覽器視窗發生變化,瀑布流排列調整
resize();
water(divs)
};
divs.forEach(function (div,i) {//未每張圖片新增自定義屬性i
div.i=i;
});
/*到這裡動態瀑布流結束,
接下來是點選圖片放大及上下切換效果實現*/
var temp1=sEO.$('#temp1').innerHTML;
var show_big=sEO.$('#show_big');
var info=sEO.$('#txt');
var mask=sEO.$('#mask');
var index,txt,show_imgW;
sEO.agent(box,'img','click',function () {//為每張圖片新增事件代理
show_big.style.display='block';
src=this.getAttribute('src');
txt=this.nextElementSibling.innerHTML;
public_b();
mask.style.display='block';
index=this.parentNode.parentNode.i; //當前點選的圖片位置
});
sEO.agent(show_big,'a','click',function () {
//為左右圖片切換按鈕新增事件代理
var cls=this.className;
cls==='prev'?index--:index++;
index=index===-1?(divs.length-1):index;/*圖片迴圈載入*/
index=index===divs.length?0:index;
src=divs[index].children[0].children[0].getAttribute('src');/*點選之後圖片路徑*/
txt=divs[index].children[0].children[1].innerHTML;/*點選之後圖片描述內容*/
public_b()
});
var show_img,max_h;
function public_b() {
show_big.innerHTML=temp1.replace('{{src}}',src).replace('{{info}}',txt);
show_img=show_big.children[0];
// var img_h=show_big.children[0].offsetHeight;
max_h=window.innerHeight-140;
// if (img_h>max_h)img_h=max_h;
show_img.style.height=max_h+'px';
show_imgW=show_big.children[0].offsetWidth;
show_big.style.width=show_imgW+'px';
info.style.width=show_imgW-20+'px';
show_big.style.left=(window.innerWidth-show_imgW)/2+'px';
show_img.onclick=mask.onclick=hidden;
}
function hidden() {
show_big.style.display='';
mask.style.display='';
this.onclick=null;
}
```