领先的免费Web技术教程,涵盖HTML到ASP.NET

网站首页 > 知识剖析 正文

【JS 图片瀑布流】简单易用的图片瀑布流

nixiaole 2025-03-25 16:04:55 知识剖析 7 ℃

最近项目里有瀑布流的需求,本来打算使用现有轮子的,后来发现在兼容大小屏时样式会出现错乱,因此决定手动实现一个。以下一个简单的demo。(完整代码可已查看next-demo: next-demo - Gitee.com

如上图所示,瀑布流实现的核心逻辑主要是根据容器宽度,排列数,自动计算图片宽度,然后计算各个图片的绝对定位位置。

技术要点

  1. 获取容器宽度,确定大小屏时图片的排列数(小屏2列,中屏3列,大屏4,超大屏5.。。)
  2. 根据容器宽度和列数计算出每项的宽度
  3. 根据每项宽度,使用New image计算出每个图片的宽高
  4. 将容器相对定位,每项绝对定位
  5. 计算每项绝对定位(left和top)
  6. 计算绝对定位时需要将每项的额外距离计算在内(padding,margin,border)
  7. 根据定位信息进行页面布局

代码实现

  1. 获取每项宽度
const getColumnWidth = (node: HTMLElement, gap = 20) => {
  let COLUMN_COUNT = 2;
  if (node.clientWidth > 968 && node.clientWidth <= 1200 column_count='3;' else if node.clientwidth> 1200 && node.clientWidth <= 1400 column_count='4;' else if node.clientwidth> 1400 && node.clientWidth <= 1600 column_count='5;' else if node.clientwidth> 1600) {
    COLUMN_COUNT = 6;
  }
  return {
    column: COLUMN_COUNT,
    columnWidth: Math.floor((node.clientWidth - gap * (COLUMN_COUNT - 1)) / COLUMN_COUNT),
  }
}
  1. 根据列宽计算出渲染尺寸宽高
const loadImage = async (url: string, width: number) => {
  const img = new Image();
  img.src = url;
  await new Promise(res => img.onload = res);
  return {
    w: width,
    h: Math.floor((img.naturalHeight / img.naturalWidth) * width),
    src: img.src,
  };
};
  1. 计算每项的绝对定位
const calculatePositions = (data:any[]) => {
    const newPositions: Iposition[] = [];
    const tempHeights = [...columnHeights.current];

    data.forEach((img,index:number) => {
      // 计算元素高度
      const elementHeight = img.h + (ITEM_PADDING * 2) + (BORDER_WIDTH * 2) + 20;
      // 找到最小高度列
      const minHeight = Math.min(...tempHeights);
      const columnIndex = tempHeights.indexOf(minHeight);

      // 计算位置
      newPositions.push({
        left: columnIndex * (columns.columnWidth + GAP),
        top: minHeight
      });

      // 更新列高度(图片高度 + 间距)
      tempHeights[columnIndex] += elementHeight + GAP;
    });

    columnHeights.current = tempHeights;
    setPositions([...newPositions]);
  }
  1. 完整的代码可查看 next-demo: next-demo - Gitee.com

Tags:

最近发表
标签列表