瀑布流

const defaultConfig = {
  boxName: '#waterfall',
  itemName: '.waterfall__item',
  gap: 10,
  boxLeft: 15
};

module.exports = class Waterfall {
  constructor(userConfig) {
    const _this = this;

    this.config = Object.assign({}, defaultConfig, userConfig);
    this.$box = $(this.config.boxName);
    this.$items = this.$box.find(this.config.itemName);
    this.pageWidth = $(document).width();
    this.itemWidth = this.$items.eq(0).outerWidth();
    this.gap = (this.pageWidth / 375) * this.config.gap;
    this.boxLeft = (this.pageWidth / 375) * this.config.boxLeft;
    this.columns = parseInt(this.pageWidth / (this.itemWidth + this.gap), 10);
    this.itemHeightArr = [];

    for (let i = 0; i < this.$items.length; i++) {
      const $curItem = this.$items.eq(i);
      const counted = $curItem.data('count');

      if (i < this.columns) {
        // 2- 确定第一行
        if (!counted) {
          $curItem.css({
            top: 0,
            left: (_this.itemWidth + _this.gap) * i + _this.boxLeft + 'px'
          });
          // 标记当前项被计算过,防止重复计算
          $curItem.data('count', true);
        }
        this.itemHeightArr.push($curItem.outerHeight());
      } else {
        // eslint-disable-next-line
        // 其他行
        // 3- 找到数组中最小高度  和 它的索引
        this.minHeight = this.itemHeightArr[0];
        this.minIndex = 0;

        for (let j = 0; j < this.itemHeightArr.length; j++) {
          if (this.minHeight > this.itemHeightArr[j]) {
            this.minHeight = this.itemHeightArr[j];
            this.minIndex = j;
          }
        }
        // 4- 设置下一行的第一个盒子位置
        // top值就是最小列的高度 + gap
        if (!counted) {
          $curItem.css({
            top: _this.itemHeightArr[_this.minIndex] + _this.gap + 'px',
            left: _this.$items.eq(_this.minIndex).offset().left + 'px'
          });
          // 标记当前项被计算过,防止重复计算
          $curItem.data('count', true);
        }
        // 5- 修改最小列的高度
        // 最小列的高度 = 当前自己的高度 + 拼接过来的高度 + 间隙的高度
        this.itemHeightArr[this.minIndex] =
          this.itemHeightArr[this.minIndex] + $curItem.outerHeight() + this.gap;
      }
    }
  }
};