Implementation of waterfall flow (native js+jquery+css3)

  • 2021-07-04 17:38:00
  • OfStack

Preface

Project requirements to get a waterfall flow of the page, using waterfall this plug-in, the feeling is OK, the project rushed not their own hands-on writing. I have nothing to do recently, so I'll write one myself. The general idea is clear, but it is quite easy to achieve...

Native javascript version


<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title> Waterfall flow -javascript</title>
 <style>
 *{margin:0;padding:0;}
 #content{position: relative;margin:0 auto;}
 .box{padding:10px;float: left;}/* The first line floats, the first 2 Row start absolute positioning */
 .box img{width: 180px;height:auto;display: block;}
 </style>
 <script>
 window.onload=function(){
 waterfall('content','box');
 
 // When you change the window size, rearrange 
 window.onresize = function(){
 waterfall('content','box');
 }
 
 // If there is not enough data, the scroll bar does not appear, and the data is automatically loaded 
 var time=setInterval(function(){
 if(checkscrollside()){
  addDate();// Insert data 
  waterfall('content','box');// After loading the data, rearrange it 
 }else{
  clearInterval(time);
  window.onscroll=function(){
  if(checkscrollside()){
  addDate();
  waterfall('content','box');
  };
  }
 }
 },1000) 
 
 } 
 //  Data insertion 
 function addDate(){
 var dataInt=['1.jpg','2.jpg','3.jpg','4.jpg','5.jpg','6.jpg','7.jpg','8.jpg'];// Analog data, which can also be an object 
 var oParent = document.getElementById('content');
 for(var i=0;i<dataInt.length;i++){// Insert data in a loop  
 var oBox=document.createElement('div');
 oBox.className='box';
 oParent.appendChild(oBox);
 var oImg=document.createElement('img');
 oImg.src='./img/'+dataInt[i];
 oBox.appendChild(oImg);
 }
 }
 // Principal function 
 function waterfall(parentID,childClass){
 var oParent=document.getElementById(parentID);
 var arrBox=getClassObj(parentID,childClass);// getClassObj() Acquirer class Array of 
 var iBoxW=arrBox[0].offsetWidth;//  Gets the width of the waterfall block 
 var num=Math.floor(document.documentElement.clientWidth/iBoxW);// How many columns can the calculation window hold 
 oParent.style.width=iBoxW*num+'px';// Setting Parent Width 
 var arrBoxH=[];// An array that stores the heights of all block boxes in each column 
 for(var i=0;i<arrBox.length;i++){// Traversing array waterfall   Block 
 var boxH=arrBox[i].offsetHeight;// Gets the height of the current block 
 if(i<num){
  arrBox[i].style.cssText="";// Prevent the user from changing the window size, and then the style will go wrong 
  arrBoxH[i]=boxH; // No. 1 1 In the row num Block box  Add to the array first arrBoxH
 }else{
  var minH=Math.min.apply(null,arrBoxH);// Get an array arrBoxH The minimum value in minH
  var minHIndex=getminHIndex(arrBoxH,minH);// Traverse the array to get the minimum value minH Index of 
  arrBox[i].style.position='absolute';// Set absolute displacement 
  arrBox[i].style.top=minH+'px';
  arrBox[i].style.left=minHIndex*iBoxW+'px';// You can also get it directly arrBox[minHIndex].offsetLeft
  arrBoxH[minHIndex]+=arrBox[i].offsetHeight;// After adding, update the minimum column height 
 }
 }
 }
 // Acquirer class Array of 
 function getClassObj(parentID,childClass){
 var oParent=document.getElementById(parentID);
 var allChildObj=oParent.getElementsByTagName('*');// Get all subsets under the parent 
 var childObj=[];// Create 1 Array of numbers   Used to collect child elements 
 for (var i=0;i<allChildObj.length;i++) {// Traverse child elements, determine categories, and press into arrays 
 if (allChildObj[i].className==childClass){
  childObj.push(allChildObj[i]);
 }
 };
 return childObj;
 }
 // Gets the index of the minimum value of the array 
 function getminHIndex(arr,minH){
 for(var i in arr){
 if(arr[i]==minH){
  return i;
 }
 }
 }
 //  Determine whether the scroll bar goes to the bottom 
 function checkscrollside(){
 var arrBox=getClassObj("content",'box');
 // Get the last 1 Height of waterfall block: distance from the top of web page ( Implementation starts loading before rolling through )
 var lastBoxH=arrBox[arrBox.length-1].offsetTop;
 var scrollTop=document.documentElement.scrollTop||document.body.scrollTop;// Gets the height at which the scroll bar is swept away 
 var documentH=document.documentElement.clientHeight;// Displays the height of the page document 
 return (lastBoxH<scrollTop+documentH)?true:false;// After reaching the specified height,   Return true , trigger waterfall() Function 
 }
 </script>
</head>
<body>
 <div id="content">
 <div class="box"><img src="img/0.jpg" alt=""></div>
 <div class="box"><img src="img/1.jpg" alt=""></div>
 <div class="box"><img src="img/2.jpg" alt=""></div>
 <div class="box"><img src="img/3.jpg" alt=""></div>
 <div class="box"><img src="img/4.jpg" alt=""></div>
 <div class="box"><img src="img/5.jpg" alt=""></div>
 <div class="box"><img src="img/6.jpg" alt=""></div>
 <div class="box"><img src="img/7.jpg" alt=""></div>
 <div class="box"><img src="img/8.jpg" alt=""></div>
 <div class="box"><img src="img/9.jpg" alt=""></div>
 <div class="box"><img src="img/10.jpg" alt=""></div>
 </div>
</body>
</html>

jquery version


<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title> Waterfall flow -jquery</title>
 <style>
 *{margin:0;padding:0;}
 #content{position: relative;margin:0 auto;}
 .box{padding:10px;float: left;}
 .box img{width: 180px;height:auto;display: block;}
 </style>
 <script src="js/jquery-1.11.1.min.js"></script>
 <script>
 $(function(){
 waterfall();
 
 // When you change the window size, rearrange 
 $(window).resize(function(){
 waterfall();
 })
 
 // If there is not enough data, the scroll bar does not appear, and the data is automatically loaded 
 var time=setInterval(function(){
 if(checkscrollside()){
  addDate();// Insert data 
  waterfall();// After loading the data, rearrange it 
 }else{
  clearInterval(time);
  $(window).scroll(function(){
  if(checkscrollside()){
  addDate();
  waterfall();
  };
  })
 }
 },1000) 
 
 }) 
 //  Data insertion 
 function addDate(){
 var dataInt=['1.jpg','2.jpg','3.jpg','4.jpg','5.jpg','6.jpg','7.jpg','8.jpg'];// Analog data, which can also be an object 
 var oParent = $('#content');
 for(var i=0;i<dataInt.length;i++){// Insert data in a loop 
 oParent.append('<div class="box"><img src="./img/'+dataInt[i]+'" alt=""></div>'); 
 }
 }
 // Principal function 
 function waterfall(){
 var arrBox=$('#content').children('.box');// box Object 
 var iBoxW=arrBox.eq(0).innerWidth();//  Gets the width of the waterfall block , Attention width(), Follow innerWidth() Difference between 
 var num=Math.floor($(window).width()/iBoxW);// How many columns can the calculation window hold 
 $('#content').css('width',iBoxW*num);// Setting Parent Width 
 var arrBoxH=[];// An array that stores the heights of all block boxes in each column 
 for(var i=0;i<arrBox.length;i++){// Traversing array waterfall   Block 
 var boxH=arrBox.eq(i).innerHeight();// Gets the height of the current block 
 if(i<num){
  arrBox.eq(i).attr('style','');// Prevent the user from changing the window size, and then the style will go wrong 
  arrBoxH[i]=boxH; // No. 1 1 In the row num Block box  Add to the array first arrBoxH
 }else{
  var minH=Math.min.apply(null,arrBoxH);// Get an array arrBoxH The minimum value in minH
  var minHIndex=$.inArray(minH,arrBoxH);// Use jquery Tools provided 
  arrBox.eq(i).css({'position':'absolute','top':minH,'left':minHIndex*iBoxW});// Set positioning 
  arrBoxH[minHIndex]+=arrBox.eq(i).innerHeight();// After adding, update the minimum column height 
 }
 }
 }
 //  Determine whether the scroll bar goes to the bottom 
 function checkscrollside(){
 var arrBox=$('#content').children('.box');
 // Get the last 1 Height of waterfall block: distance from the top of web page ( Implementation starts loading before rolling through )
 var lastBoxH=arrBox.eq(arrBox.length-1).offset().top;
 var scrollTop=$(window).scrollTop()// Gets the height at which the scroll bar is swept away 
 var documentH=$(window).height();;// Displays the height of the page document 
 return (lastBoxH<scrollTop+documentH)?true:false;// After reaching the specified height,   Return true , trigger waterfall() Function 
 }
 </script>
</head>
<body>
 <div id="content">
 <div class="box"><img src="img/0.jpg" alt=""></div>
 <div class="box"><img src="img/1.jpg" alt=""></div>
 <div class="box"><img src="img/2.jpg" alt=""></div>
 <div class="box"><img src="img/3.jpg" alt=""></div>
 <div class="box"><img src="img/4.jpg" alt=""></div>
 <div class="box"><img src="img/5.jpg" alt=""></div>
 <div class="box"><img src="img/6.jpg" alt=""></div>
 <div class="box"><img src="img/7.jpg" alt=""></div>
 <div class="box"><img src="img/8.jpg" alt=""></div>
 <div class="box"><img src="img/9.jpg" alt=""></div>
 <div class="box"><img src="img/10.jpg" alt=""></div>
 </div>
</body>
</html>

General train of thought

1. Let Line 1 float first
2. Calculate the height of each block in line 1
3. Traverse every 1 block after line 1 and place it below the minimum height one by one
4. Load the data insert. Finally, recalculate

Attention points

a. Native js

1. The getClassObj () function is defined to get the object of class class, which is convenient to call. Compatibility is considered getElementsByClassName
2. Defines the index of getminHIndex () function for users to get the minimum value
3. It is best to use padding to set the distance between blocks, so that offsetHeight can directly obtain the height. If you set margin, you have to add an extra outer margin distance
4. The timer is set in the code to load data, which can be omitted, as long as the data loaded for the first time can be full screen. The onscroll event will not be executed if the scroll bar does not appear. There is no way to load the data
5. The calculated width in the code can also be modified, and the designed page is a waterfall flow with fixed width. Here, the response processing is mainly done


var arrBox=getClassObj(parentID,childClass);// getClassObj() Acquirer class Array of 
var iBoxW=arrBox[0].offsetWidth;//  Gets the width of the waterfall block 
var num=Math.floor(document.documentElement.clientWidth/iBoxW);// How many columns can the calculation window hold 
oParent.style.width=iBoxW*num+'px';// Setting Parent Width  

6. Every time you set a block displacement, you should increase the value on the array of column height to prevent the blocks from overlapping


arrBox[i].style.position='absolute';// Set absolute displacement 
arrBox[i].style.top=minH+'px';
arrBox[i].style.left=minHIndex*iBoxW+'px';// You can also get it directly arrBox[minHIndex].offsetLeft
arrBoxH[minHIndex]+=arrBox[i].offsetHeight;// After adding, update the minimum column height  

b.jquery

1. The idea is similar to js1, but jquery encapsulates many methods, which makes us realize them easily
2. Notice the difference between width () and innerWidth (). The former can only get the width value (excluding the white padding)

css3 version


<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title> Waterfall flow -css3</title>
 <style>
 *{margin:0;padding:0;}
 #content{margin:0 auto;position: relative;width:1200px;column-count:6;-moz-column-count:6;-webkit-column-count:6;}
 .box{padding:10px;width: 180px;}
 .box img{width: 180px;height:auto;display: block;}
 </style>
 <script>
 window.onload=function(){
 // If there is not enough data, the scroll bar does not appear, and the data is automatically loaded 
 var time=setInterval(function(){
 if(checkscrollside()){
  addDate();// Insert data 
 }else{
  clearInterval(time);
  window.onscroll=function(){
  if(checkscrollside()){
  addDate();
  };
  }
 }
 },1000) 
 
 } 
 //  Data insertion 
 function addDate(){
 var dataInt=['1.jpg','2.jpg','3.jpg','4.jpg','5.jpg','6.jpg','7.jpg','8.jpg'];// Analog data, which can also be an object 
 var oParent = document.getElementById('content');
 for(var i=0;i<dataInt.length;i++){// Insert data in a loop  
 var oBox=document.createElement('div');
 oBox.className='box';
 oParent.appendChild(oBox);
 var oImg=document.createElement('img');
 oImg.src='./img/'+dataInt[i];
 oBox.appendChild(oImg);
 }
 }
 // Acquirer class Array of 
 function getClassObj(parentID,childClass){
 var oParent=document.getElementById(parentID);
 var allChildObj=oParent.getElementsByTagName('*');// Get all subsets under the parent 
 var childObj=[];// Create 1 Array of numbers   Used to collect child elements 
 for (var i=0;i<allChildObj.length;i++) {// Traverse child elements, determine categories, and press into arrays 
 if (allChildObj[i].className==childClass){
  childObj.push(allChildObj[i]);
 }
 };
 return childObj;
 }
 //  Determine whether the scroll bar goes to the bottom 
 function checkscrollside(){
 var arrBox=getClassObj("content",'box');
 // Get the last 1 Height of waterfall block: distance from the top of web page ( Implementation starts loading before rolling through )
 var lastBoxH=arrBox[arrBox.length-1].offsetTop;
 var scrollTop=document.documentElement.scrollTop||document.body.scrollTop;// Gets the height at which the scroll bar is swept away 
 var documentH=document.documentElement.clientHeight;// Displays the height of the page document 
 return (lastBoxH<scrollTop+documentH)?true:false;// After reaching the specified height,   Return true , trigger waterfall() Function 
 }
 </script>
</head>
<body>
 <div id="content">
 <div class="box"><img src="img/0.jpg" alt=""></div>
 <div class="box"><img src="img/1.jpg" alt=""></div>
 <div class="box"><img src="img/2.jpg" alt=""></div>
 <div class="box"><img src="img/3.jpg" alt=""></div>
 <div class="box"><img src="img/4.jpg" alt=""></div>
 <div class="box"><img src="img/5.jpg" alt=""></div>
 <div class="box"><img src="img/6.jpg" alt=""></div>
 <div class="box"><img src="img/7.jpg" alt=""></div>
 <div class="box"><img src="img/8.jpg" alt=""></div>
 <div class="box"><img src="img/9.jpg" alt=""></div>
 <div class="box"><img src="img/10.jpg" alt=""></div>
 </div>
</body>
</html>

Attention points

1. Rolling load or adding js
2. The loaded data is arranged vertically. The experience is not very friendly
3. Compatibility issues, Internet Explorer 10 +


Related articles: