You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求将N个相同尺寸矩形打包入大矩形的算法(JavaScript缩略图生成场景)

等尺寸缩略图规则网格布局实现方案

核心算法思路

你需要的是等大矩形的规则行列排布,不需要用到复杂的不等边矩形最密打包算法,核心逻辑围绕「匹配容器宽高比选择最优行列数」展开,步骤如下:

  • 确定最优行列组合:遍历所有可行的行数取值(范围为1到√N向上取整,N为缩略图总数),对应列数为Math.ceil(N/行数),计算每组行列的宽高比(列数/行数),选择和目标容器宽高比差值最小的组合,能最大程度减少容器留白,视觉效果最优。
  • 计算缩略图最大可用尺寸:先扣除上下左右的外边框总占用空间,再扣除行列之间的内部间距总占用空间(横向总间距=内部间距*(列数-1),纵向总间距=内部间距*(行数-1)),剩余空间除以列数得到缩略图最大可用宽度,除以行数得到最大可用高度,取二者较小值作为最终缩略图尺寸,保证不变形。
  • 计算每个缩略图的坐标:按行列索引依次计算位置即可,需要整体居中的话可额外计算网格整体的偏移量叠加。

JS代码实现示例

/**
 * 计算缩略图布局参数
 * @param {number} containerWidth 目标容器宽度
 * @param {number} containerHeight 目标容器高度
 * @param {number} thumbnailCount 缩略图总数
 * @param {number} outerBorder 外部边框宽度
 * @param {number} gap 缩略图之间的间距
 * @returns {Array<{x:number, y:number, w:number, h:number}>} 每个缩略图的位置和尺寸
 */
function calculateThumbnailLayout(containerWidth, containerHeight, thumbnailCount, outerBorder = 10, gap = 8) {
  // 1. 找最优行列组合
  let bestRows = 1, bestCols = thumbnailCount;
  let minRatioDiff = Infinity;
  const containerRatio = containerWidth / containerHeight;
  const maxPossibleRows = Math.ceil(Math.sqrt(thumbnailCount));

  for (let rows = 1; rows <= maxPossibleRows; rows++) {
    const cols = Math.ceil(thumbnailCount / rows);
    const gridRatio = cols / rows;
    const ratioDiff = Math.abs(gridRatio - containerRatio);
    if (ratioDiff < minRatioDiff) {
      minRatioDiff = ratioDiff;
      bestRows = rows;
      bestCols = cols;
    }
  }

  // 2. 计算缩略图尺寸
  const availableWidth = containerWidth - outerBorder * 2 - gap * (bestCols - 1);
  const availableHeight = containerHeight - outerBorder * 2 - gap * (bestRows - 1);
  const thumbWidth = Math.min(availableWidth / bestCols, availableHeight / bestRows);
  const thumbHeight = thumbWidth; // 如果缩略图不是正方形可按对应比例换算

  // 3. 计算网格整体居中偏移(可选)
  const gridTotalWidth = thumbWidth * bestCols + gap * (bestCols - 1);
  const gridTotalHeight = thumbHeight * bestRows + gap * (bestRows - 1);
  const offsetX = outerBorder + (availableWidth - gridTotalWidth) / 2;
  const offsetY = outerBorder + (availableHeight - gridTotalHeight) / 2;

  // 4. 生成每个缩略图的参数
  const result = [];
  for (let i = 0; i < thumbnailCount; i++) {
    const col = i % bestCols;
    const row = Math.floor(i / bestCols);
    result.push({
      x: offsetX + col * (thumbWidth + gap),
      y: offsetY + row * (thumbHeight + gap),
      w: thumbWidth,
      h: thumbHeight
    });
  }
  return result;
}

优化扩展说明

  • 如果允许缩略图轻微变形填满容器,可以不用取宽高的较小值,直接分别赋值,适配需要无留白的场景。
  • 可以根据实际需求加阈值判断,当缩略图数量过少时强制最小行列数,避免单张图铺满容器的情况。

内容的提问来源于stack exchange,提问作者Molly Birk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 22:15:07