原生js實現瀑布流
阿新 • • 發佈:2020-08-01
前言:
這玩意兒大家肯定經常見到,但是應該怎麼實現的呢?現在列出來三種方式
原始碼:(還未上傳,稍等)
第一種:通過html標籤實現,比如分3列,將資料平分為3分分別填充。
適合:圖片高度一致。
優點:簡單
缺點:因為每個資料不一樣,每一列的高低可能相差比較大。
程式碼如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>瀑布流1</title> <link rel="stylesheet" href="1.css"> <script src="1.js"></script> </head> <body> <div id="box"> </div> </body> <script> //存放參數 let box = document.getElementById("box"); //元素 let width = 600; //寬度,單位px let jianJu = 6; //每列之間的間距,單位px let col = 3; //分為多少列 let dataList = [ { url: "http://pic.sc.chinaz.com/Files/pic/pic9/202007/apic26715_s.jpg", title: "1行主題", content:"1行內容" }, { url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202007/apic26552_s.jpg", title: "1行主體", content: "2行內容2行內容2行內容2行內容" }, { url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202007/apic26408_s.jpg", title: "1行主題", content: "3行內容" }, { url: "http://pic.sc.chinaz.com/Files/pic/pic9/202007/apic26313_s.jpg", title: "1行主題", content: "4行內容" }, { url: "http://pic1.sc.chinaz.com/Files/pic/pic9/202007/bpic20697_s.jpg", title: "1行主題", content: "5行內容" }, { url: "http://pic1.sc.chinaz.com/Files/pic/pic9/202004/bpic20013_s.jpg", title: "2行主題", content: "1行內容" }, { url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202005/apic25546_s.jpg", title: "3行主題", content: "1行內容" }, { url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202005/apic25309_s.jpg", title: "4行主題", content: "1行內容" }, { url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202007/apic26488_s.jpg", title: "4行主題", content: "4行內容" }, { url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202007/apic26473_s.jpg", title: "超過2行的主題", content: "超過3行的內容" }, { url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202007/apic26395_s.jpg", title: "其他", content: "其他" }, { url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202005/apic25357_s.jpg", title: "其他", content: "其他" }, { url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202005/apic25357_s.jpg", title: "其他", content: "其他" } ] </script> <script> //呼叫 aaa(box, width, col, dataList); </script> </html>
.div-class{ float: left; } /*標題文字的樣式*/ .tit{ white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-weight: bold; } /*介紹文字的樣式*/ .con{ }
function aaa(ele, wid, num, arr) { let _this = this; let nData = Math.round(arr.length / num); // 先將資料(arr)分為n(num)份 let colWidth = wid / num; for (let i = 0; i < num; i++) { let colDiv = document.createElement('div'); let startIndex = nData * i; // 每份資料開始的索引 let newData = null; colDiv.style.width = colWidth + "px"; colDiv.style.marginLeft = jianJu + "px"; colDiv.className = "div-class"; if (i==num-1) { newData = arr.slice(startIndex, arr.length + 1); //最後一部分資料 } else { newData = arr.slice(startIndex, startIndex + nData); } for (let j = 0; j < newData.length; j++) { let childDiv = document.createElement("p"); _this.pStyle(childDiv, newData[j], colWidth); colDiv.appendChild(childDiv); } ele.appendChild(colDiv); } } function pStyle(p, item, colWidth) { let img = document.createElement('img'); let tit = document.createElement('p'); let con = document.createElement('p'); img.src = item.url; img.style.width = colWidth + 'px'; tit.className = "tit"; tit.innerHTML = item.title; con.className = "con"; con.innerHTML = item.content; p.appendChild(img); p.appendChild(tit); p.appendChild(con); }
第二種:通過css實現
適合:文字分列
優點:簡單
缺點:因為圖片高低不一,頁面不一致
程式碼如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>瀑布流2</title> <link rel="stylesheet" href="2.css"> </head> <body> <div class="box" style="width:600px"> 主要用於文字分列,主要用於文字分列,主要用於文字分列,主要用於文字分列 主要用於文字分列,主要用於文字分列,主要用於文字分列,主要用於文字分列 主要用於文字分列,主要用於文字分列,主要用於文字分列,主要用於文字分列 <h2>主要用於文字分列,主要用於文字分列,主要用於文字分列,主要用於文字分列</h2> <div> 主要用於文字分列,主要用於文字分列,主要用於文字分列,主要用於文字分列 主要用於文字分列,主要用於文字分列,主要用於文字分列,主要用於文字分列 </div> </div> <div class="box" style="width:600px"> </div> </body> <script> //存放參數 let box = document.getElementsByClassName("box")[1]; //元素 let dataList = [ { url: "http://pic.sc.chinaz.com/Files/pic/pic9/202007/apic26715_s.jpg", title: "1行主題", content: "1行內容" }, { url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202007/apic26552_s.jpg", title: "1行主體", content: "2行內容2行內容2行內容2行內容" }, { url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202007/apic26408_s.jpg", title: "1行主題", content: "3行內容" }, { url: "http://pic.sc.chinaz.com/Files/pic/pic9/202007/apic26313_s.jpg", title: "1行主題", content: "4行內容" }, { url: "http://pic1.sc.chinaz.com/Files/pic/pic9/202007/bpic20697_s.jpg", title: "1行主題", content: "5行內容" }, { url: "http://pic1.sc.chinaz.com/Files/pic/pic9/202004/bpic20013_s.jpg", title: "2行主題", content: "1行內容" }, { url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202005/apic25546_s.jpg", title: "3行主題", content: "1行內容" }, { url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202005/apic25309_s.jpg", title: "4行主題", content: "1行內容" }, { url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202007/apic26488_s.jpg", title: "4行主題", content: "4行內容" }, { url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202007/apic26473_s.jpg", title: "超過2行的主題", content: "超過3行的內容" }, { url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202007/apic26395_s.jpg", title: "其他", content: "其他" }, { url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202005/apic25357_s.jpg", title: "其他", content: "其他" }, { url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202005/apic25357_s.jpg", title: "其他", content: "其他" } ] </script> <script> for (let a = 0; a < dataList.length; a++) { var img = document.createElement("img"); img.src = dataList[a].url; box.appendChild(img); } </script> </html>
*{ margin: 0; padding: 0; } .box{ -webkit-column-count: 3; /* Chrome, Safari, Opera */ -moz-column-count: 3; /* Firefox */ column-count: 3; /*建立多列*/ -webkit-column-gap: 10px; /* Chrome, Safari, Opera */ -moz-column-gap: 10px; /* Firefox */ column-gap: 10px; /*列與列間的間隙*/ -webkit-column-rule-style: solid; /* Chrome, Safari, Opera */ -moz-column-rule-style: solid; /* Firefox */ column-rule-style: solid; /*列與列間的邊框樣式*/ -webkit-column-rule-width: 1px; /* Chrome, Safari, Opera */ -moz-column-rule-width: 1px; /* Firefox */ column-rule-width: 1px; -webkit-column-rule-color: lightblue; /* Chrome, Safari, Opera */ -moz-column-rule-color: lightblue; /* Firefox */ column-rule-color: lightblue; -webkit-column-width: 100px; /* Chrome, Safari, Opera */ column-width: 100px; /*指定列的寬度*/ } h2{ -webkit-column-span: all; /* Chrome, Safari, Opera */ column-span: all; /*指定元素跨越多少列*/ } img{ width: 100%; }
第三種:通過js實現,檢測每一列的高度,然後選擇最低的插入資料
適合:相容
優點:不會出現每列高度差很多的情況
缺點:能耗高,資料多的話效率慢
程式碼如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>瀑布流3</title> <style> * { margin: 0; padding: 0; } .tit { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-weight: bold; } .con { } </style> <script src="3.js"></script> </head> <body> <div id="waterFallBox"> </div> </body> <script> // 分為N列 // 每列的高度為 heightList = [100, 200, 300, 400, 200, 400.....] // 每次插入前,選出最低的一列 // 然後插入 // 最後更新陣列資訊,重複以上步驟 let boxWidth = 600; //外層div的寬度 let N = 3; //分為N列 let mar = 5; //列與列之間的寬度 let round = { is: true, //是否圓角 content: "5px" //設定圓角(is為true時生效) }; let dataList = [ //需要填充的資料 { url: "http://pic.sc.chinaz.com/Files/pic/pic9/202007/apic26715_s.jpg", title: "1行主題", content: "1行內容" }, { url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202007/apic26552_s.jpg", title: "1行主體", content: "2行內容2行內容2行內容2行內容" }, { url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202007/apic26408_s.jpg", title: "1行主題", content: "3行內容" }, { url: "http://pic.sc.chinaz.com/Files/pic/pic9/202007/apic26313_s.jpg", title: "1行主題", content: "4行內容" }, { url: "http://pic1.sc.chinaz.com/Files/pic/pic9/202007/bpic20697_s.jpg", title: "1行主題", content: "5行內容" }, { url: "http://pic1.sc.chinaz.com/Files/pic/pic9/202004/bpic20013_s.jpg", title: "2行主題", content: "1行內容" }, { url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202005/apic25546_s.jpg", title: "3行主題", content: "1行內容" }, { url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202005/apic25309_s.jpg", title: "4行主題", content: "1行內容" }, { url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202007/apic26488_s.jpg", title: "4行主題", content: "4行內容" }, { url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202007/apic26473_s.jpg", title: "超過2行的主題", content: "超過3行的內容" }, { url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202007/apic26395_s.jpg", title: "其他", content: "其他" }, { url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202005/apic25357_s.jpg", title: "其他", content: "其他" }, { url: "https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=2760607627,944470302&fm=26&gp=0.jpg", title: "其他", content: "其他" } ] window.onload = function () { this.appendChild(); } </script> </html>
function appendChild() { let box = document.getElementById("waterFallBox"); for (let i = 0; i < N; i++) { //根據需要生成N列,然後裝飾一下 let childBox = document.createElement("div"); childBox.className = 'water-fall' + i; childBox.style.width = boxWidth/N + 'px'; childBox.style.float = "left"; childBox.style.marginLeft = mar + 'px'; childBox.style.marginRight = mar + 'px'; box.appendChild(childBox); } for (let j = 0; j < dataList.length; j++) { //每次填充一個數據就檢測一次每一列的高度,找出最低的填充 this.imgNodes(dataList[j]); } } function imgNodes(imgData) { let heightList = []; let minHeight = Infinity; let minIndex = 0; let createImgNode = null; let chooseNode = null; let nodeList = []; for (let i = 0; i < N; i++) { let node = document.getElementsByClassName('water-fall' + i)[0]; nodeList.push(node); heightList.push(node.clientHeight); } for (let j = 0; j < heightList.length; j++) { //找出最低列 if (minHeight > heightList[j]) { minHeight = heightList[j]; minIndex = j; } } //填充資料 createImgNode = document.createElement('img'); createTitNode = document.createElement('p'); createContNode = document.createElement('p'); createImgNode.src = imgData.url; createImgNode.style.width = boxWidth/N + 'px'; if(round.is){ createImgNode.style.borderRadius = round.content; } createTitNode.innerHTML = imgData.title; createTitNode.className = "tit"; createContNode.innerHTML = imgData.content; createContNode.className = "con"; nodeList[minIndex].appendChild(createImgNode); nodeList[minIndex].appendChild(createTitNode); nodeList[minIndex].appendChild(createContNode); }