Untitled

⭐️ 核心思路

  1. 找到第一次排完,高度最小的那个列
  2. 把下一页第一张图放进去
  3. 再比较排完后高度最小的那一列
  4. 再把第二张图放进去
  5. 循环上边 3、4 步骤
;(function(doc){

  var Waterfall = function(wrapper, opt){
    this.oWrapper = doc.getElementsByClassName(wrapper)[0];
    this.column = opt.column;
    this.gap = opt.gap;
    this.imgApi = opt.imgApi;
    this.itemWidth = (this.oWrapper.offsetWidth - (this.column - 1) * this.gap) / this.column;
    this.pageNum = 0;
    this.pageSize = 0;
    this.heightArr = [];
  }

  Waterfall.prototype = {
    init: function(){
      this.getImgDatas(this.pageNum);
      this.bindEvent();
    },

    bindEvent: function(){
      window.addEventListener('scroll', this.scrollToBottom.bind(this), false);
    },

    scrollToBottom: function(){
      // 当 页面已经滚动了的高度 + window自身高度 === 滚动+窗口高度 时
      if (getScrollTop() + getWindowHeight() == getScrollHeight()) {
        this.pageNum++;

        if(this.pageNum <= this.pageSize - 1){
          this.getImgDatas(this.pageNum);
        }
      }
    },

    getImgDatas: function(pageNum){
      var _self = this;

      xhr.ajax({
        url: this.imgApi,
        type: 'POST',
        dataType: 'JSON',
        data: {
          pageNum: pageNum
        },
        success: function(data){
          if(data != 'NO DATA'){
            var pageData = JSON.parse(data.pageData);
            _self.pageSize = parseInt(data.pageSize);
            _self.renderList(pageData, _self.pageNum);
          }
        }
      });
    },

    renderList: function(data, pageNum){
      var _self = this,
          oItems = null,
          minIdx = -1;

      data.forEach(function(elem, idx){
        var oItem = doc.createElement('div'),
            oImg = new Image(),
            oTitle = doc.createElement('div'),
            // 第一张图片没有左间距,用 (i + 1) % 列数 === 1 去判断,代表是每一行第一张图
            // 每行的后续图片的 left 定位值,就是 (i * (每列宽度 + 间隔))
            itemLeft = (idx + 1) % _self.column === 1 ? '0' : idx * (_self.itemWidth + _self.gap);

        oItem.className = 'wf-item';
        oItem.style.width = _self.itemWidth + 'px';
        oItem.style.height = (elem.height * _self.itemWidth / elem.width + 44) + 'px';
        oImg.src = elem.img;
        oTitle.innerHTML = '<p>测试文本</p>';
        oTitle.className = 'title-box';

        oItem.appendChild(oImg);
        oItem.appendChild(oTitle);
        _self.oWrapper.appendChild(oItem);

        oItems = doc.getElementsByClassName('wf-item');

        // 设置第一页的第一行所有图片的top、left
        if(idx < _self.column && pageNum == 0){
          _self.heightArr.push(oItem.offsetHeight);
          oItem.style.top = '0';
          oItem.style.left = itemLeft + 'px';
        }else{ // 后续都是根据之前数组算的
          minIdx = getMinIdx(_self.heightArr);
          oItem.style.left = oItems[minIdx].offsetLeft + 'px';
          oItem.style.top = (_self.heightArr[minIdx] + _self.gap) + 'px';
          _self.heightArr[minIdx] += (oItems[idx].offsetHeight + _self.gap);
        }
        oImg.style.opacity = '1';
      });
    }
  }

  // 数组只会有 column 个,保存的是每一列的当前总和高度
  // 该方法用来计算数组中最小高度的那一项的idx
  function getMinIdx(arr) {
    return [].indexOf.call(arr, Math.min.apply(null, arr));
  }

  window.Waterfall = Waterfall;

})(document);