如何用 JS 實現瀑布流佈局
前言
瀑布流佈局,是現在比較流行的一種頁面佈局方式,即
多行等寬
元素排列,等寬不等高
,後面的元素依次
添加到前一行最矮
的元素下方
。
它可以有效的降低頁面的複雜度,節省很多的空間;並且,瀑布流的參差不齊的排列方式,可以通過界面展示給用戶多條數據,並且讓用戶可以有向下瀏覽的衝動,提供了很好的用戶體驗!例如淘寶的頁面就採用了這種佈局方式,給大家看看淘寶的瀑布流佈局的效果圖(手機端)以及我們要實現的效果圖(PC 端)吧~
思路準備
通過了解瀑布流佈局的方式,我們來梳理一下實現它的步驟,方便我們代碼的編寫。
1、首先我們需要準備很多張圖片(我這準備的是 40 張),還有 vscode 開發工具。
2、編寫前端代碼,給圖片添加樣式讓圖片等寬並同行顯示。
3、編寫 js 代碼,要知道第一行圖片數量,下一張圖片的序號以及前一行最矮的元素的序號,還有擺放的位置。
正文
一、前端代碼編寫
1、首先我們定義一個 container 容器來裝所有圖片,在這個容器中用 box 容器裝 box-img 容器再裝入每張圖片,這樣方便之後樣式的編寫。
2、使圖片同行顯示 -- 給 box 容器使用 float:left; 屬性。
3、讓圖片等寬顯示 -- 給 box-img 容器設置 width:150px;,img 標籤設置** width:100%; 繼承父容器 box-img 高度的 100%**。
4、爲了使效果更好看,我們給裝圖片的容器設置內邊距,邊框和陰影的效果。
前端完整代碼附上:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta >
<title>waterFall</title>
<script src="./index.js"></script>
</head>
<style>
*{
margin: 0;
padding: 0;
}
.container {
overflow: hidden;
position: relative;
}
.box{
float: left;
padding: 5px;
}
.box-img{
width: 150px;
padding: 5px;
border: 1px solid #484848;
box-shadow: 0 0 5px #484848;
}
.box-img img{
width: 100%;
}
</style>
<body>
<div id="container">
<div class="box">
<div class="box-img">
<img src="./img/1.jpg" alt="">
</div>
</div>
/*.......後面接39個box,此處省略*/
</div>
</body>
</html>
複製代碼
二、js 代碼編寫
1、首先用 window.onload=function(){} 來實現頁面加載完畢後立即執行的功能
在這個函數中,我們調用 imgLocation('container','box') 函數來呈現最終效果,傳入的實參是父容器'container'以及裝圖片的子容器'box'。
window.onload=function() {
imgLocation('container','box')
}
複製代碼
2、實現 imgLocation() 函數功能
1)首先我們得獲取所有要擺放的圖片
,並將其存入一個數組
中
利用 document.getElementById(parent) 得到父容器;
調用 getChildElement(cparent,content) 方法,在這個方法中,先獲取父容器所有標籤,對所有標籤遍歷並用 if 條件語句得到類名爲 box 的容器(裝圖片的容器),將其存入我們自己構建的一個數組中,返回值爲這個數組,方便之後通過遍歷來操作圖片擺放的位置。
function imgLocation(parent,content){
var cparent=document.getElementById(parent)
//cparent下的所有的第一層的子容器 box
var ccontent=getChildElement(cparent,content)//數組,40個div
}
//取到父容器中的某一層子容器
function getChildElement(parent,content){
var contentArr=[]
var allContent=parent.getElementsByTagName('*')//通過標籤來選中得到一個數組
//遍歷allContent把其中類名爲content的容器都存到contentArr數組中
for(var i=0;i<allContent.length;i++){
if(allContent[i].className==content){ //當前這個容器的類名是否爲content
contentArr.push(allContent[i])
}
}
return contentArr;
}
複製代碼
2)得到這個數組
後,找出從誰開始
是需要被擺放
位置的
我們採用以下方法:
首先獲取視窗的寬度和每張圖片的寬度,將兩者相除並向下取整可得到第一行可以放置圖片的數量,自然也就知道了我們需要操作的那張圖片的序號。
//從誰開始是需要被擺放位置的
var winWidth=document.documentElement.clientWidth;//視窗寬度
var imgWidth=ccontent[0].offsetWidth;//圖片寬度
var num=Math.floor(winWidth/imgWidth)//第一行能放幾張圖
複製代碼
3)得到需要被擺放
位置的圖片序號後,確定其擺放位置
我們自己定義一個存儲高度的數組,對前一行元素的高度進行遍歷並存入數組,當遍歷到需要被擺放位置的圖片時,用 Math.min() 方法獲取前一行高度最矮的元素高度,並用 indexOf() 方法獲取到其下標。
再對我們所操作的這個圖片容器的樣式調整:
position:absolute; 絕對定位, top 值設置爲前一行高度最矮的圖片高度 minHeight,left 值設置爲單張圖片寬度乘這張圖片的下標 minIndex。
最後,不要忘啦,擺放好圖片後,還要更新擺放的那一列的高度喲~
//操作num+1張圖
var BoxHeightArr=[]
for(var i=0;i<ccontent.length;i++){
//前num張只要計算高度
if(i<num){
BoxHeightArr[i]=ccontent[i].offsetHeight
}
else{
//我們要操作的box :ccontent[i]
var minHeight=Math.min.apply(null,BoxHeightArr)//apply:把最小值這個方法借給它用
var minIndex=BoxHeightArr.indexOf(minHeight)//返回數組下標
ccontent[i].style.position='absolute'//style設置樣式
ccontent[i].style.top=minHeight+'px'
ccontent[i].style.left=imgWidth*minIndex+'px'
//更新最矮的那一列的高度
BoxHeightArr[minIndex]+=ccontent[i].offsetHeight
}
}
複製代碼
最終整合一下就可以實現瀑布流的佈局效果啦!
最後
以上就是瀑布流佈局的實現過程,看完本文如果覺得有用,記得點個贊支持,收藏起來說不定哪天就用上啦~
文章可能有一些錯誤,歡迎評論指出,也歡迎一起討論。
關於本文
作者:zt_ever
https://juejin.cn/post/7216200378341589052
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/_B5tEsc2WjSeMP2PDjKmcg