$.fn.waterfall = function (options) { var defaults = { hGap: null, vGap: null, itemSelector: '.waterfall-item', containerSelector: '.waterfall-container', }; var settings = $.extend(defaults, options); this.each(function () { var $this = $(this); initWaterfall($this); if ($this.data('waterfall-init')) return; $this.data('waterfall-init', true); $(window).on( 'resize', debounce(function () { initWaterfall($this); }, 100) ); $this.on( 'lazyloaded', 'img', debounce(function () { initWaterfall($this); }, 50) ); $this.on('post_ajax.ed', function () { initWaterfall($this); }); }); function getGap(container) { var horizontalGap = settings.hGap; var verticalGap = settings.vGap; var items = container.find(settings.itemSelector); if (items.length && horizontalGap === null) { horizontalGap = parseInt(container.data('h-gap')); // 水平间距 if (!horizontalGap) { horizontalGap = parseInt(items.eq(0).css('margin-left')) + parseInt(items.eq(0).css('margin-right')); } } if (items.length && verticalGap === null) { verticalGap = parseInt(container.data('v-gap')); // 垂直间距 if (!verticalGap) { verticalGap = parseInt(items.eq(0).css('margin-top')) + parseInt(items.eq(0).css('margin-bottom')); } } return { horizontalGap: horizontalGap, verticalGap: verticalGap }; } //瀑布流布局 function initWaterfall(container) { if (!container.length) return; var items = container.find(settings.itemSelector); if (!items.length) return; //获取列数和间距 const containerWidth = container.width(); const itemWidth = items.eq(0).outerWidth(); const columns = Math.floor(containerWidth / itemWidth); const { horizontalGap, verticalGap } = getGap(container); //计算第一个项目距离容器顶部的位置,减去自身margin-top const firstItemTop = items.eq(0).offset().top - container.offset().top - parseInt(items.eq(0).css('margin-top')); //初始化列高度数组 let colHeights = new Array(columns).fill(firstItemTop); //遍历所有子项目 items.each(function () { const $item = $(this); //找到最短的列 const minHeight = Math.min(...colHeights); const minCol = colHeights.indexOf(minHeight); //计算位置,加入间距 const left = minCol * itemWidth + horizontalGap * minCol; const top = minHeight + (minHeight > 0 ? verticalGap : 0); //设置位置 $item .css({ position: 'absolute', left: '0', top: '0', transform: 'translate3d(' + left + 'px,' + top + 'px,0)', }) .addClass('waterfall-item'); //更新列高度 colHeights[minCol] += $item.height() + verticalGap; }); //设置容器高度,考虑底部间距 container.css('height', Math.max(...colHeights) + verticalGap + 'px'); } };