Waterfall stream layout seems to be very popular at present. For details about the analysis, principles, and knowledge used, you can refer to the following articles written by some cool people.
Waterfall flow layout analysis
Talking about the problems and solutions encountered by individuals in implementing waterfall web pages
Tossing: waterfall flow layout (based on the multi-column list Fluid layout)
Javascript waterfall stream, Major waterfall Stream Analysis and Suggestions
Because I use jquery more often, I came up with the idea of making waterfall streams into plug-ins. I just borrowed some beautiful images from Thunder UED.
First look at the Demo
Release the code.
; (Function ($) {var // parameter setting = {column_width: 204, // column width column_className: 'waterfall _ column', // column Class Name column_space: 10, // The column spacing cell_selector :'. cell ', // The selector of the bricks to be arranged, limited to img_selector: 'img' in the container of the waterfall stream, // The selector auto_imgHeight: true for the image to be loaded, // whether to automatically calculate the Image Height fadein: true, // whether to load fadein_speed: 600, // The gradient speed, in milliseconds insert_type: 1, // The Brick insertion mode, 1: insert the shortest column, 2: insert getResource: function (index) {}// obtain the dynamic resource function in turn, and a set of bricks and elements must be returned, number of incoming parameters}, // wa Terfall = $. waterfall ={}, $ container = null; // container waterfall. load_index = 0, // Number of loads $. fn. extend ({waterfall: function (opt) {opt = opt | |{}; setting = $. extend (setting, opt); $ container = waterfall. $ container = $ (this); waterfall. $ columns = creatColumn (); render ($ (this ). find (setting. cell_selector ). detach (), false); // force waterfall to be not gradually displayed when an existing element is reshuffled. _ scrollTimer2 = null; $ (window ). bind ('scroll ', function () {clearTimeout (waterfall. _ ScrollTimer2); waterfall. _ scrollTimer2 = setTimeout (onScroll, 300) ;}); waterfall. _ scrollTimer3 = null; $ (window ). bind ('resize', function () {clearTimeout (waterfall. _ scrollTimer3); waterfall. _ scrollTimer3 = setTimeout (onResize, 300) ;}}}); function creatColumn () {// create the waterfall column. column_num = calculateColumns (); // Number of columns // create a column in a loop var html = ''; for (var I = 0; I <waterfall. column_num; I ++) {html + = '<div class = "' + setting. c Olumn_className + '"style =" width:' + setting. column_width + 'px; display: inline-block; * display: inline; zoom: 1; margin-left: '+ setting. column_space/2 + 'px; margin-right: '+ setting. column_space/2 + 'px; vertical-align: top; overflow: hidden "> </div> ';} $ container. prepend (html); // insert column return $ ('. '+ setting. column_className, $ container); // column set} function calculateColumns () {// calculate the required number of columns var num = Math. floor ($ container. inne RWidth ()/(setting. column_width + setting. column_space); if (num <1) {num = 1;} // ensure that at least one column of return num;} function render (elements, fadein) {// render element if (! $ (Elements). length) return; // No element var $ columns = waterfall. $ columns; $ (elements). each (function (I) {if (! Setting. auto_imgHeight | setting. insert_type = 2) {// if the image height is given or inserted sequentially, you do not have to wait until the image is loaded to calculate the column height if (setting. insert_type = 1) {insert ($ (elements ). eq (I), setting. fadein & fadein); // insert element} else if (setting. insert_type = 2) {insert2 ($ (elements ). eq (I), I, setting. fadein & fadein); // insert element} return true; // continue} if ($ (this) [0]. nodeName. toLowerCase () = 'img '| $ (this ). find (setting. img_selector ). length> 0) {// The image itself or the var im containing the image Age = new Image; var src = $ (this) [0]. nodeName. toLowerCase () = 'img '? $ (This ). attr ('src'): $ (this ). find (setting. img_selector ). attr ('src'); image. onload = function () {// The image size can be automatically calculated after the image is loaded. onreadystatechange = null; if (setting. insert_type = 1) {insert ($ (elements ). eq (I), setting. fadein & fadein); // insert element} else if (setting. insert_type = 2) {insert2 ($ (elements ). eq (I), I, setting. fadein & fadein); // insert element} image = null;} image. onreadystatechange = function () {// handle the cache issue of IE and other browsers: the onload event will not be triggered after the image is cached if (image. readyState = "complete") {image. onload = null; if (setting. insert_type = 1) {insert ($ (elements ). eq (I), setting. fadein & fadein); // insert element} else if (setting. insert_type = 2) {insert2 ($ (elements ). eq (I), I, setting. fadein & fadein); // insert element} image = null ;}} image. src = src;} else {// you do not need to consider loading if (setting. insert_type = 1) {insert ($ (elements ). eq (I), setting. fadein & fadein); // insert element} else if (setting. insert_type = 2) {insert2 ($ (elements ). eq (I), I, setting. fadein & fadein); // insert element }});} function public_render (elem) {// Asynchronous Data Rendering interface function render (elem, true );} function insert ($ element, fadein) {// insert the element into the shortest column if (fadein) {// progressively show element.css ('opacity ', 0 ). appendTo (waterfall. $ columns. eq (calculateLowest ())). fadeTo (setting. fadein_speed, 1);} else {// do not show $ element. appendTo (waterfall. $ columns. eq (calculateLowest ();} function insert2 ($ element, I, fadein) {// insert element if (fadein) in turn in order) {// progressively show element.css ('opacity ', 0 ). appendTo (waterfall. $ columns. eq (I % waterfall. column_num )). fadeTo (setting. fadein_speed, 1);} else {// do not show $ element. appendTo (waterfall. $ columns. eq (I % waterfall. column_num);} function calculateLowest () {// calculate the index var min = waterfall for the column with the shortest possible length. $ columns. eq (0 ). outerHeight (), min_key = 0; waterfall. $ columns. each (function (I) {if ($ (this ). outerHeight () <min) {min = $ (this ). outerHeight (); min_key = I ;}}); return min_key ;}function getElements () {// get resources $. waterfall. load_index ++; return setting. getResource ($. waterfall. load_index, public_render);} waterfall. _ scrollTimer = null; // delayed rolling loading timer function onScroll () {// rolling loading clearTimeout (waterfall. _ scrollTimer); waterfall. _ scrollTimer = setTimeout (function () {var $ lowest_column = waterfall. $ columns. eq (calculateLowest (); // The shortest column var bottom = $ lowest_column.offset (). top + $ lowest_column.outerHeight (); // distance from the bottom of the shortest column to the top of the browser window var scrollTop=document.doc umentElement. scrollTop | document. body. scrollTop | 0; // the scroll bar is located at the distance of var javaswheight?document.doc umentElement. clientHeight | document. body. clientHeight | 0; // window height if (scrollTop> = bottom-javaswheight) {render (getElements (), true) ;}, 100);} function onResize () {// re-arrange if (calculateColumns () = waterfall. column_num) return; // The number of Columns has not changed. You do not need to rearrange var $ cells = waterfall. $ container. find (setting. cell_selector); waterfall. $ columns. remove (); waterfall. $ columns = creatColumn (); render ($ cells, false); // force not fade when an existing element is rearranged}) (jQuery );
It seems that the format of the Code is messy. If the above Code is not clear, you can directly view the source file on the demo page.
Plugin usage:
$ (Selector). waterfall (opt); // Where selector is the selector of the waterfall flow container, and opt is the configuration parameter object
The required html structure: the html structure can be an empty container element, such as <div id = "container"> </div>. The bricks in the structure are dynamically loaded. Of course, you can also put some bricks in advance, such as
<div id="container"> <div class="cell"><p>00</p></div> <div class="cell"><p>01</p></div> <div class="cell"><p>02</p></div> <div class="cell"><p>03</p></div> <div class="cell"><p>04</p></div> <div class="cell"><p>05</p></div> <div class="cell"><p>06</p></div> <div class="cell"><p>07</p></div> <div class="cell"><p>08</p></div> <div class="cell"><p>09</p></div> <div class="cell"><p>10</p></div> <div class="cell"><p>11</p></div> <div class="cell"><p>12</p></div> <div class="cell"><p>13</p></div> <div class="cell"><p>14</p></div> <div class="cell"><p>15</p></div> <div class="cell"><p>16</p></div> <div class="cell"><p>17</p></div> <div class="cell"><p>18</p></div> <div class="cell"><p>19</p></div></div>
The following describes in detail the role of the attributes of the Configuration Parameter object opt and its default values.
Column_width: 204 // The waterfall stream is composed of columns. This parameter specifies the width of each column. This parameter will directly affect the number of columns of the waterfall stream.
Column_className: 'Waterfall _ column' // Class Name of the column to facilitate custom styles
Column_space: 10 // spacing between columns and columns
Cell_selector:'. Cell '// The selector of the bricks to be arranged, which is limited to the container of the waterfall stream. That is, the plug-in obtains the brick element through this selector, in addition, the elements matched by this selector are searched in the waterfall flow container.
Img_selector: 'Img '// specifies the selector of the image to be loaded. If the subject content of the brick element to be loaded in your waterfall stream is an image of varying size, this parameter is the selector of these images. The plugin needs to obtain these images for calculation.
Auto_imgHeight: True // whether to automatically calculate the Image Height. If the image size is fixed, set this parameter to false.
Fadein: True // whether to incrementally Load
Fadein_speed: 600 // incremental display rate, in milliseconds
Insert_type: 1 // brick insertion method. 1 indicates the column with the shortest insertion length, and 2 indicates the insertion speed in turn.
GetResource: Function (index, render) {}// gets a dynamic resource function. A set of brick elements must be returned. The index of the first input parameter is the number of times loaded, the second parameter is the rendering function. It can accept the cooperation of a brick element set as the parameter. If ajax is used to load data, you need to manually call the function for rendering after obtaining the data. This function is automatically triggered every time you reach the bottom of the waterfall stream to load more resources.
Slot time:
The content loaded by the waterfall stream is generally the same width and different heights. If you can know the Image Height in advance, it is much easier, but if you cannot, the height of the image can be calculated only after the image is loaded. This is the most annoying part of the waterfall stream, and it is precisely because, if the image is of an unknown height, the order of insertion may be a bit messy, and the order of each refresh is different, because the order of loading of each image is not fixed. Maybe this time is faster, but it will be faster next time. Therefore, if the image height is unknown, the height of the entire brick is unknown. The height of the brick must be calculated after the image in the brick is loaded. If this is the case but you want to ensure the insertion sequence of bricks, we recommend that you insert bricks in turn in order, that isInsert_typeSet the parameter to 2. Because it is a plug-in, you need to consider the ease of use, but the easier it is to use, the more complicated the plug-in, the more vulnerabilities and bugs will increase, so I will continue to improve this plug-in.
This plug-in supports mainstream browsers such as IE6 +, chrome, firefox, opera, and safari.