每日一题之实现瀑布流

每日一题之实现瀑布流


  • 思路:

    • 可以根据父元素总宽度和子元素单个宽度拿到一行可以放下n个元素
    • 可以根据一行n个元素生成n长度的数组用于存放每列的高度
    • 遍历父元素内部的图片根据步骤二中最短的索引设置单个图片的left, top,最后重新设置最短索引所在列的高度
代码如下
class Waterfall {
  constructor(containerSelector, itemSelector, columnWidth, gap) {
    this.container = document.querySelector(containerSelector);
    // 拿到需要排列瀑布流的所有元素并转成数组
    this.items = Array.from(this.container.querySelectorAll(itemSelector));
    // 拿到每列需要设置的宽度
    this.columnWidth = columnWidth;
    // 拿到图片之间的间隔
    this.gap = gap;
    // 根据父元素容器宽度和每张图片的宽度, 向下取整得到一行可以有多少列, 如果小于1, 默认等于1
    this.columns =
      Math.floor(this.container.offsetWidth / (this.columnWidth + this.gap)) ||
      1;
    // 根据上面一步多少列生成对应长度的数组应用存储每一列的高度
    this.columnHeights = new Array(this.columns).fill(0);
    this.init();
  }

  init() {
    this.layoutItems();
    window.addEventListener("resize", this.handleResize.bind(this));
  }

// 主要的代码逻辑
  layoutItems() {
    // 遍历子元素
    this.items.forEach((item, index) => {
    // 拿到所有列的最小索引
      const columnIndex = this.getShortestColumnIndex();
    // 设置最小索引下图片的左上偏移量
      const left = columnIndex * (this.columnWidth + this.gap);
      const top = this.columnHeights[columnIndex] + this.gap;

      item.style.position = "absolute";
      item.style.left = `${left}px`;
      item.style.top = `${top}px`;
    // 设置最小索引下的列高度
      this.columnHeights[columnIndex] = top + item.offsetHeight;
    });

    // 根绝每一列的高度取出最大值并赋值给父元素
    const maxHeight = Math.max(...this.columnHeights);
    this.container.style.height = `${maxHeight}px`;
  }

  getShortestColumnIndex() {
    return this.columnHeights.indexOf(Math.min(...this.columnHeights));
  }

  handleResize() {
  // 窗口大小改变触发, 重新计算父元素可以放下多少列
    this.columns = Math.floor(
      this.container.offsetWidth / (this.columnWidth + this.gap)
    );
    this.columns = this.columns || 1;
    // 重新设置每列的高度, 这里我感觉是否可以只改变最后一列?
    this.columnHeights = new Array(this.columns).fill(0);
    this.layoutItems();
  }
}

// 示例使用
const waterfall = new Waterfall(".container", ".item", 200, 10);

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值