瀑布流布局

// 通常配合上拉刷新一起使用(可见另一篇文章,交叉监听器的使用)
// 类似于PC抖音首页布局
//卡片宽度260px,左右间距6px,上下间距18px

废话不多说,直接上代码:

import React, { useState, useEffect, useRef } from 'react';
import './App.css';

function App() {
  const [cards, setCards] = useState([]);
  const containerRef = useRef(null);

  useEffect(() => {
    // 模拟异步加载卡片数据
    const loadCards = async () => {
      // 假设有一个 fetchCards 函数用于获取卡片数据
      const data = await fetchCards();
      setCards(data);
    };

    loadCards();
  }, []);

  useEffect(() => {
    const masonryLayout = () => {
      const container = containerRef.current;
      const cards = container.getElementsByClassName('card');
      const columnCount = Math.floor(container.offsetWidth / 266); // 每列宽度为 260px + 6px 左右间距
      const columnHeights = Array(columnCount).fill(0);

      for (let i = 0; i < cards.length; i++) {
        const card = cards[i];
        const minHeight = Math.min(...columnHeights);
        const minHeightIndex = columnHeights.indexOf(minHeight);
        const left = minHeightIndex * 266; // 每列宽度为 260px + 6px 左右间距
        const top = minHeight;

        card.style.left = `${left}px`;
        card.style.top = `${top}px`;

        columnHeights[minHeightIndex] += card.offsetHeight + 18; // 18px 为卡片之间的上下间距
      }

      const maxHeight = Math.max(...columnHeights);
      container.style.height = `${maxHeight}px`;
    };

    masonryLayout();
    window.addEventListener('resize', masonryLayout);

    return () => {
      window.removeEventListener('resize', masonryLayout);
    };
  }, [cards]);

  return (
    <div className="card-container" ref={containerRef}>
      {cards.map((card, index) => (
        <div key={index} className="card">
          <img src={card.imageUrl} alt={card.title} />
          <h3>{card.title}</h3>
          <p>{card.description}</p>
        </div>
      ))}
    </div>
  );
}

export default App;
.card-container {
  position: relative;
}

.card {
  position: absolute;
  width: 260px;
  background-color: #f2f2f2;
  padding: 8px;
  border-radius: 10px;
  margin: 0 
  }

思路:
1、获取要展示的dom元素,根据dom去计算当前页面能展示几列数据
2、通过这个几列,将一个数组分成这个长度,数组的每一项代表每一列
3、根据这个数据展示开始的列表,每个卡片的高度不同(后端数据返回),展示开始的一行
4、再通过这个数组去查看那一列高度最低,完了吧第二行的第一个卡片放到这个最低的列,以此往复即可

  • 10
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值