相仿Pinterest的瀑布流布局
类似Pinterest的瀑布流布局
原算法可能会产生一个问题,列之间的高度差会很大。新算法进行了改进,会使得高度差进可能小,达到高度平衡。基本思想是,每次计算一个块的top时,寻找高度最小的那一列。看了实验结果,新算法还不是最优的。
function buildWaterFall(params) { if (! IK.isset(params)) { return; } var colsBlockId = params.id; var colCount = params.count; var margin = params.margin; var container = $("#" + colsBlockId); if (container.length == 0) { return; } if (colCount < 1) { colCount = 1; } if (! IK.isset(margin)) { margin = 20; } var columns = container.children(); if (columns.length < 1) { return; } var colTops = []; for(var i = 0; i < colCount; i++) { colTops[i] = 0; } var colWidth = $(columns[0]).width() + margin; function getPosition(colHeight) { var diff = 0; var index = 0; // 这里其实只需要找高度最小的列就行 for(var i = 0; i < colCount - 1; i++) { for (var j = i + 1; j < colCount; j++) { var df = colTops[i] - colTops[j]; var abDiff = Math.abs(df); if (diff < abDiff) { diff = abDiff; index = df < 0 ? i : j; } } } var left = colWidth * index; var top = colTops[index]; if (IK.isset(colHeight)) { colTops[index] += colHeight + margin; } return {'left': left + 'px', 'top': top + 'px'}; } for(var i = 0; i < columns.length; i++) { var col = $(columns[i]); var url = col.attr('url'); if (IK.isset(url)) { col.click(function(){ Util.redirect($(this).attr('url')); }); } var style = getPosition(col.height()); col.css(style).show(); } var maxHeight = 0; for(var i = 0; i < colCount; i++) { if (maxHeight < colTops[i]) { maxHeight = colTops[i]; } } container.height(maxHeight + 'px'); }, /* buildWaterFall */
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> <title>Water fall demo</title> <script src="http://code.jquery.com/jquery.min.js" type="text/javascript"></script> <style> .columns {border: 1px solid blue; float: left; min-height: 200px; position: relative; width: 100%;} .column {border: 1px solid red; display: none; margin: 10px; position: absolute; width: 100px;} </style> </head> <body> <div id="columns" class="columns"> <div class="column" style="min-height: 100px;"></div> <div class="column" style="min-height: 200px;"></div> <div class="column" style="min-height: 150px;"></div> <div class="column" style="min-height: 180px;"></div> <div class="column" style="min-height: 130px;"></div> <div class="column" style="min-height: 140px;"></div> <div class="column" style="min-height: 120px;"></div> </div> <script type="text/javascript"> function buildWaterFall(colsBlockId, colCount, margin) { if (colCount < 1) { colCount = 1; } if (typeof margin == 'undefined' || margin < 0) { margin = 10; } var container = $("#" + colsBlockId); var columns = container.children(); var left = 0, top = 0; var i = 0; var maxHeight = 0; while(i < columns.length) { var col = $(columns[i]); col.attr('id', i); col.css({ 'left': left + 'px', 'top': top + 'px' }).show(); var mh = computeScrollTop(col) + margin; if (maxHeight < mh) { maxHeight = mh; } i++; if (i % colCount == 0) { left = 0; } else { left += col.scrollLeft() + margin + col.width(); } var aboveIndex = i - colCount; if (aboveIndex >= 0) { top = computeScrollTop($(columns[aboveIndex])) + margin; } } container.height(maxHeight + margin + 'px'); } function computeScrollTop(elem) { // the JQuery method 'scrollTop()' sometimes can't get the expected result, // especially when the columns is less than 3. var h = elem.css('top'); if (typeof h != 'undefined') { h = parseInt(h.replace('/px/', '')); } else { h = 0; } return h + elem.height(); } buildWaterFall('columns', 4); </script> </body> </html>