JQuery implements waterfall stream layout (PC and Mobile End) and jquery Layout

Source: Internet
Author: User

JQuery implements waterfall stream layout (PC and Mobile End) and jquery Layout

Waterfall stream layout has become a very common way of displaying images on mobile devices such as PCs and mobile phones. The layout of an image can be divided into three types: High-width, high-width, high-width, and high-width. Next we will use the most common form of width and height as an example.

We use Baidu images as an example:

 

This is a common waterfall stream layout method on the PC end. Next, let's review the elements to see how Baidu pictures are laid out:

It can be seen that there are actually several column containers with equal width, and the image is pushed to different containers through computation. The presentation method described in this article is through positioning. Although the layout display method is different, the previous algorithms are similar.

Hands-on

First, we will write several units of the following style into the body, and the "box" will move to the left:

<div class="box">  <div class="desc">Description</div></div><div class="box">  <div class="desc">Description</div></div><div class="box">  <div class="desc">Description</div></div>

The following results are obtained:

Next:

var boxArr = $('.box'),  num = Math.floor(document.body.clientWidth / boxArr.eq(0).outerWidth(true)), columnHeightArr = [];columnHeightArr.length = num;boxArr.each(function(index, item) { if (index < num) { columnHeightArr[index] = $(item).outerHeight(true); } else { var minHeight = Math.min.apply(null, columnHeightArr), minHeightIndex = $.inArray(minHeight,columnHeightArr); $(item).css({ position: 'absolute', top: minHeight, left: boxArr.eq(minHeightIndex).position().left }); }}); 

The above code indicates:

1. calculate the number of images (num) that can be accommodated in a row in the browser. Note that outerWidth is used here. When true is passed in, the returned elements include the dimensions of all the box model attributes of margin, padding, and border;

2. Create an array (columnHeightArr) that stores the height of each column. The length of the array is the num value;

3. traverse all the images and store the Image Height of the first row in the column height array (columnHeightArr). Starting from the second row, calculate the minimum height (minHeight) of all the columns) and minHeightIndex ). Then, locate the image starting from the second row under the smallest height column. The effect is as follows:

We can see that all the images are placed in the same place although they are in the correct place. This is because we need to increase the height of the column after placing an image:

var boxArr = $('.box'), num = Math.floor(document.body.clientWidth / boxArr.eq(0).outerWidth(true)), columnHeightArr = [];columnHeightArr.length = num;boxArr.each(function(index, item) {  if (index < num) {    columnHeightArr[index] = $(item).outerHeight(true);  } else {    var minHeight = Math.min.apply(null, columnHeightArr), minHeightIndex = $.inArray(minHeight, columnHeightArr);    $(item).css({   position: 'absolute',   top: minHeight,   left: boxArr.eq(minHeightIndex).position().left });    columnHeightArr[minHeightIndex] += $(item).outerHeight(true);  }});

The result is correct:

Note:The above code needs to run in the window. onload method, because the height of each image is valid only when all the image resources on the page are loaded.

As a result, there may be some serious problems. When the network is poor, when the image is not fully loaded, the image display height will be incomplete and missing, which is obvious on the Mobile End. In addition, when we load more images, it is more difficult to determine whether the newly appended images are loaded.

In actual production, the image will not be written to HTML at the beginning, so we usually use the following method:

First, we also need to obtain the width and height of the image when obtaining the image address. This is not difficult for the server background. You can ask the background brother to splice the image width and height data into JSON, passed to you;

* Tips, Very practical, it canMake sure that the ratio of an element is consistent regardless of its size.. This technique is especially applicable to mobile terminals, because elements usually use percentages for the response type.

If there is an image on the mobile phone page, the width should be half of the screen, and the aspect ratio should be, and the proportion should remain unchanged on any phone. How to do it? Set the following attributes for the element:

.box { width: 50%; height: 0; padding-bottom: 100%;}

Instead of setting the height, we use padding to "squeeze" the element height, and the percentage value of padding is based on the width of the parent container. How much do padding need to squeeze? That is, multiply the width by the aspect ratio (both width and padding values are percentage values), which is why we need to get the image size.

Effect:

In the chrome mobile phone simulator, ipone4 and kidney 6Plus are displayed in the same way. In the mobile phone page, the width is fixed, and the height changes with the page content. This technique uses the element padding percentage value based on the width of its parent container, cleverly converts a high value into a width-related one.

Now, some may have to ask, but I have talked about the relationship between the waterfall stream and the waterfall stream!Simply put, we need to discard the img tag and use the background image. To use a background image, you must keep the element ratio consistent with that of the image.

In this way, you can directly generate some divs with the same proportion of the image without judging that the image has been loaded, and then set the background image for it, as shown below:

For example, if the box width of the outermost layer is 100% PX, the img element width can be, and the height can be squeezed out through padding.

Lazy Loading

Another advantage of using the background image is that it is easier to implement lazy loading. So what is lazy loading? That is, when elements are displayed in our field of view, the image at the bottom of the screen is not displayed during scrolling, which can greatly increase the loading speed and improve the experience.

First, we add a box-item Class Name (useful later) to the outermost box, and assign the image url to a custom attribute instead of the backgroundImage attribute:Data-src.

<div class="box box-item"> <div class="img" data-src="./resource/images/1.jpg"></div> <div class="desc">Description</div></div>

Next we will compile the lazy loading function:

function lazyLoad() {  var boxArr = $('.box-item');    boxArr.each(function(index, item) {    var viewTop = $(item).offset().top - $(window).scrollTop(), imgObj = $(item).find('.img'); if ((viewTop < $(window).height()) && (($(item).offset().top + $(item).outerHeight(true)) > $(window).scrollTop())) {   imgObj.css('backgroundImage','url('+imgObj.attr("data-src")+')').removeClass('data-src');   $(item).removeClass('box-item'); } })}

First, we retrieve all the elements with the. box-item class name and traverse them. ViewTop is the relative height of the image relative to the browser window, similar to position: fixed.

The condition is used to determine whether to display the data-src value of the background image element and delete the attribute only when the image is in the browser window (neither above nor below.

Then, delete the box-item of the outermost element, because the displayed image does not need to be judged, when the class name is deleted, the displayed elements will not be retrieved once and the number of traversal times will become fewer and fewer. This will play an optimization role.

This function needs to be called when your element has been appended to the page and when scrolling:

LazyLoad ();
$ (Window). scroll (lazyLoad );

Rolling Loading

Lazy loading is finished, and rolling loading is also said. The so-called rolling loading means loading a new image when the page is scrolled near the bottom. I chose to load new data when scrolling to the bottom of the column with the smallest height. You can also make a judgment based on your preferences.

function scrollLoad() {  var viewHeight = $(window).scrollTop() + $(window).height(), minHeight = Math.min.apply(null, columnHeightArr);  if (viewHeight >= minHeight) {   //loadMore...  }}

Rolling loading is also monitored in the rolling event of the window, which can be carried out together with lazy loading:

$(window).scroll(function() { scrollLoad(); lazyLoad(); });

Let's talk about the PC end.Mobile phone. In fact, the principle is the same, but from multiple columns to fixed two columns.

var boxArr = $('.box'), columnHeightArr = [];columnHeightArr.length = 2;boxArr.each(function(index, item) {  if (index < 2) {    columnHeightArr[index] = $(item).outerHeight(true);  } else {    var minHeight = Math.min.apply(null, columnHeightArr), minHeightIndex = $.inArray(minHeight, columnHeightArr);    $(item).css({   position: 'absolute',   top: minHeight,   left: boxArr.eq(minHeightIndex).position().left });    columnHeightArr[minHeightIndex] += $(item).outerHeight(true);  }});

The difference is that in order to adapt to the mobile phone of different screens, the width and margin of the box container on the outermost layer should be set as a percentage.

The last thing to do isNote:Because we do not use column boxes to install them like Baidu, but instead use positioning methods.ProblemsIt is the parent level of the image element that cannot adapt to the height. If you have related requirements, we can calculate the longest length of all columns, assign this value to the min-height attribute of the parent container:

Detail ('body'detail .css ('minheight', Math. max. apply (null, columnHeightArr )); 

After finishing the complete code, the full set of services of waterfall stream is here.

var dataArr = [ {picUrl:'./resource/images/1.jpg',width:522,height:783}, {picUrl:'./resource/images/2.jpg',width:550,height:786}, {picUrl:'./resource/images/3.jpg',width:535,height:800}, {picUrl:'./resource/images/4.jpg',width:578,height:504}, {picUrl:'./resource/images/5.jpg',width:1440,height:900} ]; $.each(dataArr, function(index, item) { $("body").append('<div class="box box-item">' +  '<div class="img" style="height:0;padding-bottom:'+cRate(item) * 100 + "%"+'" data-src="'+item.picUrl+'"></div>' +  '<div class="desc">Description</div>' +  '</div>'); }); var boxArr = $('.box'), num = Math.floor(document.body.clientWidth / boxArr.eq(0).outerWidth(true)), columnHeightArr = []; columnHeightArr.length = num;  arrangement();  $('body').css('minHeight',Math.max.apply(null, columnHeightArr)); lazyLoad(); function arrangement() { boxArr.each(function(index, item) { if (index < num) { columnHeightArr[index] = $(item).outerHeight(true); } else { var minHeight = Math.min.apply(null, columnHeightArr),  minHeightIndex = $.inArray(minHeight, columnHeightArr); $(item).css({  position: 'absolute',  top: minHeight,  left: boxArr.eq(minHeightIndex).position().left }); columnHeightArr[minHeightIndex] += $(item).outerHeight(true); } }); } function lazyLoad() { var boxArr = $('.box-item'); boxArr.each(function(index, item) { var viewTop = $(item).offset().top - $(window).scrollTop(), imgObj = $(item).find('.img'); if ((viewTop < $(window).height()) && ($(item).offset().top + $(item).outerHeight(true) > $(window).scrollTop())) {// console.log($(item).attr('data-src')); imgObj.css('backgroundImage','url('+imgObj.attr("data-src")+')').removeClass('data-src'); $(item).removeClass('box-item'); } }) } function cRate(obj) { return obj.height / obj.width; } function scrollLoad() { var viewHeight = $(window).scrollTop() + $(window).height(), minHeight = Math.min.apply(null, columnHeightArr); if (viewHeight >= minHeight) { //loadMore... } } $(window).scroll(function() { lazyLoad(); scrollLoad(); });

The above is the stream layout of jQuery waterfall, which is rich in content and requires a little understanding and understanding. We hope to help you.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.